Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sc/source/ui/app/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 34 kB image not shown  

Quelle  transobj.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   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 .
 */


#include <scitems.hxx>
#include <editeng/justifyitem.hxx>

#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/embed/XTransactedObject.hpp>

#include <o3tl/unit_conversion.hxx>
#include <osl/diagnose.h>
#include <unotools/tempfile.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/streamwrap.hxx>
#include <comphelper/fileformat.h>
#include <comphelper/lok.hxx>
#include <comphelper/storagehelper.hxx>
#include <comphelper/servicehelper.hxx>
#include <sot/storage.hxx>
#include <utility>
#include <vcl/gdimtf.hxx>
#include <vcl/jobset.hxx>
#include <vcl/svapp.hxx>
#include <vcl/virdev.hxx>
#include <sfx2/docfile.hxx>

#include <transobj.hxx>
#include <patattr.hxx>
#include <cellvalue.hxx>
#include <cellform.hxx>
#include <document.hxx>
#include <viewopti.hxx>
#include <editutil.hxx>
#include <impex.hxx>
#include <formulacell.hxx>
#include <printfun.hxx>
#include <docfunc.hxx>
#include <scmod.hxx>
#include <dragdata.hxx>
#include <sortparam.hxx>
#include <tabvwsh.hxx>

#include <editeng/paperinf.hxx>
#include <editeng/sizeitem.hxx>
#include <formula/errorcodes.hxx>
#include <docsh.hxx>
#include <markdata.hxx>
#include <stlpool.hxx>
#include <viewdata.hxx>
#include <dociter.hxx>
#include <cellsuno.hxx>
#include <stringutil.hxx>
#include <formulaiter.hxx>

using namespace com::sun::star;

constexpr sal_uInt32 SCTRANS_TYPE_IMPEX              = 1;
constexpr sal_uInt32 SCTRANS_TYPE_EDIT_RTF           = 2;
constexpr sal_uInt32 SCTRANS_TYPE_EDIT_BIN           = 3;
constexpr sal_uInt32 SCTRANS_TYPE_EMBOBJ             = 4;
constexpr sal_uInt32 SCTRANS_TYPE_EDIT_ODF_TEXT_FLAT = 5;

void ScTransferObj::GetAreaSize( const ScDocument& rDoc, 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( rDoc.GetPrintArea( nTab, nLastCol, nLastRow ) )
        {
            if( nLastCol > nMaxCol )
                nMaxCol = nLastCol;
            if( nLastRow > nMaxRow  )
                nMaxRow = nLastRow;
        }
    }
    nRow = nMaxRow;
    nCol = nMaxCol;
}

void ScTransferObj::PaintToDev( OutputDevice* pDev, ScDocShell& rDocSh, double nPrintFactor,
                                const ScRange& rBlock )
{
    tools::Rectangle aBound( Point(), pDev->GetOutputSize() );      //! use size from clip area?

    ScViewData aViewData(rDocSh, nullptr);

    aViewData.SetScreen( rBlock.aStart.Col(), rBlock.aStart.Row(),
                            rBlock.aEnd.Col(), rBlock.aEnd.Row() );

    ScPrintFunc::DrawToDev( rDocSh.GetDocument(), pDev, nPrintFactor, aBound, aViewData, false/*bMetaFile*/ );
}

ScTransferObj::ScTransferObj( const std::shared_ptr<ScDocument>& pClipDoc, TransferableObjectDescriptor aDesc ) :
    m_pDoc( pClipDoc ),
    m_nNonFiltered(0),
    m_aObjDesc(std::move( aDesc )),
    m_nDragHandleX( 0 ),
    m_nDragHandleY( 0 ),
    m_nSourceCursorX( m_pDoc->MaxCol() + 1 ),
    m_nSourceCursorY( m_pDoc->MaxRow() + 1 ),
    m_nDragSourceFlags( ScDragSrc::Undefined ),
    m_bDragWasInternal( false ),
    m_bUsedForLink( false ),
    m_bUseInApi( false )
{
    OSL_ENSURE(m_pDoc->IsClipboard(), "wrong document");

    // get aBlock from clipboard doc

    SCCOL nCol1;
    SCROW nRow1;
    SCCOL nCol2;
    SCROW nRow2;
    m_pDoc->GetClipStart( nCol1, nRow1 );
    m_pDoc->GetClipArea( nCol2, nRow2, 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;
    m_pDoc->GetClipArea( nDummy, m_nNonFiltered, false );
    m_bHasFiltered = (m_nNonFiltered < (nRow2 - nRow1));
    ++m_nNonFiltered;     // to get count instead of diff

    SCTAB nTab1=0;
    SCTAB nTab2=0;
    bool bFirst = true;
    for (SCTAB i=0; i< m_pDoc->GetTableCount(); i++)
        if (m_pDoc->HasTable(i))
        {
            if (bFirst)
                nTab1 = i;
            nTab2 = i;
            bFirst = false;
        }
    OSL_ENSURE(!bFirst, "no sheet selected");

    //  only limit to used cells if whole sheet was marked
    //  (so empty cell areas can be copied)
    if ( nCol2>=m_pDoc->MaxCol() && nRow2>=m_pDoc->MaxRow() )
    {
        SCROW nMaxRow;
        SCCOL nMaxCol;
        GetAreaSize( *m_pDoc, nTab1, nTab2, nMaxRow, nMaxCol );
        if( nMaxRow < nRow2 )
            nRow2 = nMaxRow;
        if( nMaxCol < nCol2 )
            nCol2 = nMaxCol;
    }

    m_aBlock = ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
    m_nVisibleTab = nTab1;    // valid table as default

    tools::Rectangle aMMRect = m_pDoc->GetMMRect( nCol1,nRow1, nCol2,nRow2, nTab1 );
    m_aObjDesc.maSize = aMMRect.GetSize();
    PrepareOLE( m_aObjDesc );
}

ScTransferObj::~ScTransferObj()
{
    SolarMutexGuard aSolarGuard;

    ScModule* pScMod = ScModule::get();
    const ScDragData* pDragData = pScMod ? pScMod->GetDragData() : nullptr;
    if (pDragData && pDragData->pCellTransfer == this)
    {
        OSL_FAIL("ScTransferObj wasn't released");
        pScMod->ResetDragObject();
    }

    m_pDoc.reset();        // ScTransferObj is owner of clipboard document

    m_aDocShellRef.clear();   // before releasing the mutex

    m_aDrawPersistRef.clear();                    // after the model

}

ScTransferObj* ScTransferObj::GetOwnClipboard(const uno::Reference<datatransfer::XTransferable2>& xTransferable)
{
    return dynamic_cast<ScTransferObj*>(xTransferable.get());
}

void ScTransferObj::AddSupportedFormats()
{
    //  same formats as in ScSelectionTransferObj::AddSupportedFormats
    AddFormat( SotClipboardFormatId::EMBED_SOURCE );
    AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
    AddFormat( SotClipboardFormatId::GDIMETAFILE );
    AddFormat( SotClipboardFormatId::PNG );
    AddFormat( SotClipboardFormatId::BITMAP );

    // ScImportExport formats
    AddFormat( SotClipboardFormatId::HTML );
    AddFormat( SotClipboardFormatId::SYLK );
    AddFormat( SotClipboardFormatId::LINK );
    AddFormat( SotClipboardFormatId::DIF );
    AddFormat( SotClipboardFormatId::STRING );
    AddFormat( SotClipboardFormatId::STRING_TSVC );

    AddFormat( SotClipboardFormatId::RTF );
    AddFormat( SotClipboardFormatId::RICHTEXT );
    if ( m_aBlock.aStart == m_aBlock.aEnd )
    {
        AddFormat( SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT );
    }
}

static ScRange lcl_reduceBlock(const ScDocument& rDoc, ScRange aReducedBlock, bool bIncludeVisual = false)
{
    if ((aReducedBlock.aEnd.Col() == rDoc.MaxCol() || aReducedBlock.aEnd.Row() == rDoc.MaxRow()) &&
        aReducedBlock.aStart.Tab() == aReducedBlock.aEnd.Tab())
    {
        // Shrink the block here so we don't waste time creating huge
        // output when whole columns or rows are selected.

        SCCOL nPrintAreaEndCol = 0;
        SCROW nPrintAreaEndRow = 0;
        if (bIncludeVisual)
            rDoc.GetPrintArea( aReducedBlock.aStart.Tab(), nPrintAreaEndCol, nPrintAreaEndRow, true );

        // Shrink the area to allow pasting to external applications.
        // Shrink to real data area for HTML, RTF and RICHTEXT, but include
        // all objects and top-left area for BITMAP and PNG.
        SCCOL nStartCol = aReducedBlock.aStart.Col();
        SCROW nStartRow = aReducedBlock.aStart.Row();
        SCCOL nEndCol = aReducedBlock.aEnd.Col();
        SCROW nEndRow = aReducedBlock.aEnd.Row();

        if (bIncludeVisual)
        {
            ScDataAreaExtras aDataAreaExtras;
            aDataAreaExtras.mbCellNotes = true;
            aDataAreaExtras.mbCellDrawObjects = true;
            bool bShrunk = false;
            rDoc.ShrinkToUsedDataArea( bShrunk, aReducedBlock.aStart.Tab(), nStartCol, nStartRow, nEndCol, nEndRow,
                    falsetrue /*bStickyTopRow*/, true /*bStickyLeftCol*/, &aDataAreaExtras);
            aDataAreaExtras.GetOverallRange( nStartCol, nStartRow, nEndCol, nEndRow, ScDataAreaExtras::Clip::None);
        }
        else
        {
            bool bShrunk = false;
            rDoc.ShrinkToUsedDataArea( bShrunk, aReducedBlock.aStart.Tab(), nStartCol, nStartRow, nEndCol, nEndRow,
                    falsefalse /*bStickyTopRow*/, false /*bStickyLeftCol*/);
        }

        if ( nPrintAreaEndRow > nEndRow )
            nEndRow = nPrintAreaEndRow;

        if ( nPrintAreaEndCol > nEndCol )
            nEndCol = nPrintAreaEndCol;

        aReducedBlock = ScRange(nStartCol, nStartRow, aReducedBlock.aStart.Tab(), nEndCol, nEndRow, aReducedBlock.aEnd.Tab());
    }
    return aReducedBlock;
}

bool ScTransferObj::GetData( const datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
{
    SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );
    bool        bOK = false;

    if( HasFormat( nFormat ) )
    {
        ScRange aReducedBlock = m_aBlock;

        bool bReduceBlockFormat =
            nFormat == SotClipboardFormatId::HTML
            || nFormat == SotClipboardFormatId::RTF
            || nFormat == SotClipboardFormatId::RICHTEXT
            || nFormat == SotClipboardFormatId::BITMAP
            || nFormat == SotClipboardFormatId::PNG;

        const bool bIncludeVisual = (nFormat == SotClipboardFormatId::BITMAP ||
                                     nFormat == SotClipboardFormatId::PNG);

        if (bReduceBlockFormat)
            aReducedBlock = lcl_reduceBlock(*m_pDoc, m_aBlock, bIncludeVisual);

        if ( nFormat == SotClipboardFormatId::LINKSRCDESCRIPTOR || nFormat == SotClipboardFormatId::OBJECTDESCRIPTOR )
        {
            bOK = SetTransferableObjectDescriptor( m_aObjDesc );
        }
        else if ( ( nFormat == SotClipboardFormatId::RTF || nFormat == SotClipboardFormatId::RICHTEXT ||
            nFormat == SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT ) && m_aBlock.aStart == m_aBlock.aEnd )
        {
            //  RTF from a single cell is handled by EditEngine

            SCCOL nCol = m_aBlock.aStart.Col();
            SCROW nRow = m_aBlock.aStart.Row();
            SCTAB nTab = m_aBlock.aStart.Tab();
            ScAddress aPos(nCol, nRow, nTab);

            const ScPatternAttr* pPattern = m_pDoc->GetPattern( nCol, nRow, nTab );
            if (pPattern)
            {
                ScTabEditEngine aEngine(*pPattern, m_pDoc->GetEditPool(), *m_pDoc);
                ScRefCellValue aCell(*m_pDoc, aPos);
                if (aCell.getType() == CELLTYPE_EDIT)
                {
                    const EditTextObject* pObj = aCell.getEditText();
                    aEngine.SetTextCurrentDefaults(*pObj);
                }
                else
                {
                    ScInterpreterContext& rContext = m_pDoc->GetNonThreadedContext();
                    sal_uInt32 nNumFmt = pPattern->GetNumberFormat(rContext);
                    const Color* pColor;
                    OUString aText
                        = ScCellFormat::GetString(aCell, nNumFmt, &pColor, &rContext, *m_pDoc);
                    if (!aText.isEmpty())
                        aEngine.SetTextCurrentDefaults(aText);
                }

                bOK = SetObject(&aEngine,
                                ((nFormat == SotClipboardFormatId::RTF)
                                     ? SCTRANS_TYPE_EDIT_RTF
                                     : ((nFormat == SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT)
                                            ? SCTRANS_TYPE_EDIT_ODF_TEXT_FLAT
                                            : SCTRANS_TYPE_EDIT_BIN)),
                                rFlavor);
            }
        }
        else if ( ScImportExport::IsFormatSupported( nFormat ) || nFormat == SotClipboardFormatId::RTF
            || nFormat == SotClipboardFormatId::RICHTEXT )
        {
            //  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 == SotClipboardFormatId::LINK )
                m_bUsedForLink = true;

            bool bIncludeFiltered = m_pDoc->IsCutMode() || m_bUsedForLink;

            ScImportExport aObj( *m_pDoc, aReducedBlock );
            // Plain text ("Unformatted text") may contain embedded tabs and
            // line breaks but is not enclosed in quotes. Which makes it
            // unsuitable for multiple cells, especially if one of them is
            // multi-line, but otherwise is expected behavior for plain text.
            // For multiple cells replace embedded line breaks (and tabs) with
            // space character, otherwise pasting would yield odd results.
            /* XXX: it's debatable whether this is actually expected, but
             * there's no way to satisfy all possible requirements when
             * copy/pasting unformatted text. */

            const bool bPlainMulti = (nFormat == SotClipboardFormatId::STRING &&
                    aReducedBlock.aStart != aReducedBlock.aEnd);
            // Add quotes only for STRING_TSVC.
            /* TODO: a possible future STRING_TSV should not contain embedded
             * line breaks nor tab (separator) characters and not be quoted.
             * A possible STRING_CSV should. */

            ScExportTextOptions aTextOptions( ScExportTextOptions::None, 0,
                    (nFormat == SotClipboardFormatId::STRING_TSVC));
            if ( bPlainMulti || m_bUsedForLink )
            {
                // For a DDE link or plain text multiple cells, convert line
                // breaks and separators to space.
                aTextOptions.meNewlineConversion = ScExportTextOptions::ToSpace;
                aTextOptions.mcSeparatorConvertTo = ' ';
                aTextOptions.mbAddQuotes = false;
            }
            aObj.SetExportTextOptions(aTextOptions);
            aObj.SetFormulas( m_pDoc->GetViewOptions().GetOption( VOPT_FORMULAS ) );
            aObj.SetIncludeFiltered( bIncludeFiltered );

            //  DataType depends on format type:

            if ( rFlavor.DataType.equals( ::cppu::UnoType<OUString>::get() ) )
            {
                OUString aString;
                if ( aObj.ExportString( aString, nFormat ) )
                    bOK = SetString( aString );
            }
            else if ( rFlavor.DataType.equals( cppu::UnoType<uno::Sequence< sal_Int8 >>::get() ) )
            {
                //  SetObject converts a stream into an Int8-Sequence
                bOK = SetObject( &aObj, SCTRANS_TYPE_IMPEX, rFlavor );
            }
            else
            {
                OSL_FAIL("unknown DataType");
            }
        }
        else if ( nFormat == SotClipboardFormatId::BITMAP || nFormat == SotClipboardFormatId::PNG )
        {
            tools::Rectangle aMMRect = m_pDoc->GetMMRect( aReducedBlock.aStart.Col(), aReducedBlock.aStart.Row(),
                                                 aReducedBlock.aEnd.Col(), aReducedBlock.aEnd.Row(),
                                                 aReducedBlock.aStart.Tab() );
            ScopedVclPtrInstance< VirtualDevice > pVirtDev;

            // tdf#160855 fix crash due to Skia's internal maximum pixel limit
            // Somewhere in the tens of thousands of selected fill cells,
            // the size of the VirtualDevice exceeds 1 GB of pixels. But
            // Skia, at least on macOS, will fail to create a surface.
            // Even if there is ample free memory, Skia/Raster will fail.
            // The second problem is that even if you disable Skia, the
            // crash is just delayed when a BitmapEx is created from the
            // VirtualDevice and malloc() fails.
            // Since this data flavor really triggers one or more system
            // memory limits, lower the resolution of the bitmap by keeping
            // the VirtualDevice pixel size within an arbitrary number of
            // pixels.
            // Note: the arbitrary "maximum number of pixels" limit that
            // that Skia can handle may need to be raised or lowered for
            // platforms other than macOS.
            static constexpr tools::Long nCopyToImageMaxPixels = 8192 * 8192;
            Fraction aScale(1.0);
            Size aPixelSize = pVirtDev->LogicToPixel(aMMRect.GetSize(), MapMode(MapUnit::Map100thMM));
            tools::Long nPixels(aPixelSize.Width() * aPixelSize.Height());
            if (nPixels < 0 || nPixels > nCopyToImageMaxPixels)
            {
                aScale = Fraction(nCopyToImageMaxPixels, nPixels);
                aPixelSize = pVirtDev->LogicToPixel(aMMRect.GetSize(), MapMode(MapUnit::Map100thMM, Point(), aScale, aScale));
                nPixels = aPixelSize.Width() * aPixelSize.Height();
            }

            pVirtDev->SetOutputSizePixel(aPixelSize);

            InitDocShell(true);
            PaintToDev( pVirtDev, *m_aDocShellRef, 1.0, aReducedBlock );

            pVirtDev->SetMapMode( MapMode( MapUnit::MapPixel, Point(), aScale, aScale ) );
            BitmapEx aBmp = pVirtDev->GetBitmapEx( Point(), pVirtDev->GetOutputSize() );
            bOK = SetBitmapEx( aBmp, rFlavor );
        }
        else if ( nFormat == SotClipboardFormatId::GDIMETAFILE )
        {
            // #i123405# 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 = m_aDocShellRef.get();

            // like SvEmbeddedTransfer::GetData:
            GDIMetaFile     aMtf;
            ScopedVclPtrInstance< VirtualDevice > pVDev;
            MapMode         aMapMode( pEmbObj->GetMapUnit() );
            tools::Rectangle       aVisArea( pEmbObj->GetVisArea( ASPECT_CONTENT ) );

            pVDev->EnableOutput( false );
            pVDev->SetMapMode( aMapMode );
            aMtf.SetPrefSize( aVisArea.GetSize() );
            aMtf.SetPrefMapMode( aMapMode );
            aMtf.Record( pVDev );

            pEmbObj->DoDraw( pVDev, Point(), aVisArea.GetSize(), JobSetup() );

            aMtf.Stop();
            aMtf.WindStart();

            bOK = SetGDIMetaFile( aMtf );
        }
        else if ( nFormat == SotClipboardFormatId::EMBED_SOURCE )
        {
            //TODO/LATER: differentiate between formats?!
            // #i123405# Do limit visual size calculation to PageSize
            InitDocShell(true);         // set aDocShellRef

            SfxObjectShell* pEmbObj = m_aDocShellRef.get();
            bOK = SetObject( pEmbObj, SCTRANS_TYPE_EMBOBJ, rFlavor );
        }
    }
    return bOK;
}

bool ScTransferObj::WriteObject( SvStream& rOStm, void* pUserObject, sal_uInt32 nUserObjectId,
                                        const datatransfer::DataFlavor& rFlavor )
{
    // called from SetObject, put data into stream

    bool bRet = false;
    switch (nUserObjectId)
    {
        case SCTRANS_TYPE_IMPEX:
            {
                ScImportExport* pImpEx = static_cast<ScImportExport*>(pUserObject);

                SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );
                // mba: no BaseURL for data exchange
                if ( pImpEx->ExportStream( rOStm, OUString(), nFormat ) )
                    bRet = ( rOStm.GetError() == ERRCODE_NONE );
            }
            break;

        case SCTRANS_TYPE_EDIT_RTF:
        case SCTRANS_TYPE_EDIT_BIN:
            {
                ScTabEditEngine* pEngine = static_cast<ScTabEditEngine*>(pUserObject);
                if ( nUserObjectId == SCTRANS_TYPE_EDIT_RTF )
                {
                    pEngine->Write( rOStm, EETextFormat::Rtf );
                    bRet = ( rOStm.GetError() == ERRCODE_NONE );
                }
                else
                {
                    //  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_Int32 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 );

                    std::unique_ptr<SvStream> xStrm = aEditHelper.GetSotStorageStream( rFlavor );
                    bRet = bool(xStrm);
                    if (bRet)
                        rOStm.WriteStream(*xStrm);
                }
            }
            break;

        case SCTRANS_TYPE_EDIT_ODF_TEXT_FLAT:
            {
                ScTabEditEngine* pEngine = static_cast<ScTabEditEngine*>(pUserObject);
                pEngine->Write(rOStm, EETextFormat::Xml);
                bRet = (rOStm.GetError() == ERRCODE_NONE);
            }
            break;

        case SCTRANS_TYPE_EMBOBJ:
            {
                // TODO/MBA: testing
                SfxObjectShell*   pEmbObj = static_cast<SfxObjectShell*>(pUserObject);
                ::utl::TempFileFast aTempFile;
                SvStream* pTempStream = aTempFile.GetStream(StreamMode::READWRITE);
                uno::Reference< embed::XStorage > xWorkStore =
                    ::comphelper::OStorageHelper::GetStorageFromStream( new utl::OStreamWrapper(*pTempStream) );

                // write document storage
                pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, false );

                // mba: no relative URLs for clipboard!
                SfxMedium aMedium( xWorkStore, OUString() );
                pEmbObj->DoSaveObjectAs( aMedium, false );
                pEmbObj->DoSaveCompleted();

                uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
                if ( xTransact.is() )
                    xTransact->commit();

                rOStm.SetBufferSize( 0xff00 );
                rOStm.WriteStream( *pTempStream );

                bRet = true;

                xWorkStore->dispose();
                xWorkStore.clear();
            }
            break;

        default:
            OSL_FAIL("unknown object id");
    }
    return bRet;
}

sal_Bool SAL_CALL ScTransferObj::isComplex()
{
    ScRange aReduced = lcl_reduceBlock(*m_pDoc, m_aBlock);
    size_t nCells = (aReduced.aEnd.Col() - aReduced.aStart.Col() + 1) *
                    (aReduced.aEnd.Row() - aReduced.aStart.Row() + 1) *
                    (aReduced.aEnd.Tab() - aReduced.aStart.Tab() + 1);
    return nCells > 1000;
}

void ScTransferObj::DragFinished( sal_Int8 nDropAction )
{
    if ( nDropAction == DND_ACTION_MOVE && !m_bDragWasInternal && !(m_nDragSourceFlags & ScDragSrc::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:
            //  bApi=TRUE, don't show error messages from drag&drop
            pSourceSh->GetDocFunc().DeleteContents( aMarkData, InsertDeleteFlags::ALL & ~InsertDeleteFlags::OBJECTS, truetrue );
        }
    }

    ScModule* pScMod = ScModule::get();
    const ScDragData* pDragData = pScMod ? pScMod->GetDragData() : nullptr;
    if (pDragData && pDragData->pCellTransfer == this)
        pScMod->ResetDragObject();

    m_xDragSourceRanges = nullptr;       // don't keep source after dropping

    TransferDataContainer::DragFinished( nDropAction );
}

void ScTransferObj::SetDragHandlePos( SCCOL nX, SCROW nY )
{
    m_nDragHandleX = nX;
    m_nDragHandleY = nY;
}

void ScTransferObj::SetSourceCursorPos( SCCOL nX, SCROW nY )
{
    m_nSourceCursorX = nX;
    m_nSourceCursorY = nY;
}

bool ScTransferObj::WasSourceCursorInSelection() const
{
    return
        m_nSourceCursorX >= m_aBlock.aStart.Col() && m_nSourceCursorX <= m_aBlock.aEnd.Col() &&
        m_nSourceCursorY >= m_aBlock.aStart.Row() && m_nSourceCursorY <= m_aBlock.aEnd.Row();
}

void ScTransferObj::SetVisibleTab( SCTAB nNew )
{
    m_nVisibleTab = nNew;
}

void ScTransferObj::SetDrawPersist( const SfxObjectShellRef& rRef )
{
    m_aDrawPersistRef = rRef;
}

void ScTransferObj::SetDragSource( ScDocShell* pSourceShell, const ScMarkData& rMark )
{
    ScRangeList aRanges;
    rMark.FillRangeListWithMarks( &aRanges, false );
    m_xDragSourceRanges = new ScCellRangesObj( pSourceShell, aRanges );
}

void ScTransferObj::SetDragSourceFlags(ScDragSrc nFlags)
{
    m_nDragSourceFlags = nFlags;
}

void ScTransferObj::SetDragWasInternal()
{
    m_bDragWasInternal = true;
}

void ScTransferObj::SetUseInApi( bool bSet )
{
    m_bUseInApi = bSet;
}

ScDocument* ScTransferObj::GetSourceDocument()
{
    ScDocShell* pSourceDocSh = GetSourceDocShell();
    if (pSourceDocSh)
        return &pSourceDocSh->GetDocument();
    return nullptr;
}

ScDocShell* ScTransferObj::GetSourceDocShell()
{
    if (m_xDragSourceRanges)
        return m_xDragSourceRanges->GetDocShell();

    return nullptr;    // none set
}

ScMarkData ScTransferObj::GetSourceMarkData() const
{
    ScMarkData aMarkData(m_pDoc->GetSheetLimits());
    if (m_xDragSourceRanges)
    {
        const ScRangeList& rRanges = m_xDragSourceRanges->GetRangeList();
        aMarkData.MarkFromRangeList( rRanges, false );
    }
    return aMarkData;
}

//  initialize aDocShellRef with a live document from the ClipDoc

// #i123405# added parameter to allow size calculation without limitation
// to PageSize, e.g. used for Metafile creation for clipboard.

void ScTransferObj::InitDocShell(bool bLimitToPageSize)
{
    if ( m_aDocShellRef.is() )
        return;

    m_aDocShellRef = new ScDocShell; // ref must be there before InitNew

    m_aDocShellRef->DoInitNew();

    ScDocument& rDestDoc = m_aDocShellRef->GetDocument();
    ScMarkData aDestMark(rDestDoc.GetSheetLimits());
    aDestMark.SelectTable( 0, true );

    rDestDoc.SetDocOptions( m_pDoc->GetDocOptions() );   // #i42666#

    OUString aTabName;
    m_pDoc->GetName( m_aBlock.aStart.Tab(), aTabName );
    rDestDoc.RenameTab( 0, aTabName );

    m_aDocShellRef->MakeDrawLayer();

    rDestDoc.CopyStdStylesFrom(*m_pDoc);

    SCCOL nStartX = m_aBlock.aStart.Col();
    SCROW nStartY = m_aBlock.aStart.Row();
    SCCOL nEndX = m_aBlock.aEnd.Col();
    SCROW nEndY = m_aBlock.aEnd.Row();

    //  widths / heights
    //  (must be copied before CopyFromClip, for drawing objects)

    SCCOL nCol;
    SCTAB nSrcTab = m_aBlock.aStart.Tab();
    rDestDoc.SetLayoutRTL(0, m_pDoc->IsLayoutRTL(nSrcTab));
    for (nCol=nStartX; nCol<=nEndX; nCol++)
        if ( m_pDoc->ColHidden(nCol, nSrcTab) )
            rDestDoc.ShowCol( nCol, 0, false );
        else
            rDestDoc.SetColWidth( nCol, 0, m_pDoc->GetColWidth( nCol, nSrcTab ) );

    if (nStartY > 0)
    {
        // Set manual height for all previous rows so we can ensure
        // that visible area will not change due to autoheight
        rDestDoc.SetManualHeight(0, nStartY - 1, 0, true);
    }
    for (SCROW nRow = nStartY; nRow <= nEndY; ++nRow)
    {
        if ( m_pDoc->RowHidden(nRow, nSrcTab) )
            rDestDoc.ShowRow( nRow, 0, false );
        else
        {
            rDestDoc.SetRowHeight( nRow, 0, m_pDoc->GetOriginalHeight( nRow, nSrcTab ) );

            //  if height was set manually, that flag has to be copied, too
            bool bManual = m_pDoc->IsManualRowHeight(nRow, nSrcTab);
            rDestDoc.SetManualHeight(nRow, nRow, 0, bManual);
        }
    }

    //  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 );
    bool bWasCut = m_pDoc->IsCutMode();
    if (!bWasCut)
        m_pDoc->SetClipArea( aDestRange, true );          // Cut
    rDestDoc.CopyFromClip( aDestRange, aDestMark, InsertDeleteFlags::ALL, nullptr, m_pDoc.get(), false );
    m_pDoc->SetClipArea( aDestRange, bWasCut );

    StripRefs(*m_pDoc, nStartX,nStartY, nEndX,nEndY, rDestDoc);

    ScRange aMergeRange = aDestRange;
    rDestDoc.ExtendMerge( aMergeRange, true );

    m_pDoc->CopyDdeLinks( rDestDoc );         // 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 = m_pDoc->GetStyleSheetPool();
    OUString aStyleName = m_pDoc->GetPageStyle( m_aBlock.aStart.Tab() );
    SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
    if (pStyleSheet)
    {
        const SfxItemSet& rSourceSet = pStyleSheet->GetItemSet();
        aPaperSize = rSourceSet.Get(ATTR_PAGE_SIZE).GetSize();

        // CopyStyleFrom copies SetItems with correct pool
        ScStyleSheetPool* pDestPool = rDestDoc.GetStyleSheetPool();
        pDestPool->CopyStyleFrom( pStylePool, aStyleName, SfxStyleFamily::Page );
    }

    ScViewData aViewData(*m_aDocShellRef, nullptr);
    aViewData.SetScreen( nStartX,nStartY, nEndX,nEndY );
    aViewData.SetCurX( nStartX );
    aViewData.SetCurY( nStartY );

    rDestDoc.SetViewOptions( m_pDoc->GetViewOptions() );

    //      Size
    //! get while copying sizes

    tools::Long nPosX = 0;
    tools::Long nPosY = 0;

    for (nCol=0; nCol<nStartX; nCol++)
        nPosX += rDestDoc.GetColWidth( nCol, 0 );
    nPosY += rDestDoc.GetRowHeight( 0, nStartY-1, 0 );
    nPosX = o3tl::convert(nPosX, o3tl::Length::twip, o3tl::Length::mm100);
    nPosY = o3tl::convert(nPosY, o3tl::Length::twip, o3tl::Length::mm100);

    aPaperSize.setWidth( aPaperSize.Width() * 2 );       // limit OLE object to double of page size
    aPaperSize.setHeight( aPaperSize.Height() * 2 );

    tools::Long nSizeX = 0;
    tools::Long nSizeY = 0;
    for (nCol=nStartX; nCol<=nEndX; nCol++)
    {
        tools::Long nAdd = rDestDoc.GetColWidth( nCol, 0 );
        if ( bLimitToPageSize && nSizeX+nAdd > aPaperSize.Width() && nSizeX )   // above limit?
            break;
        nSizeX += nAdd;
    }
    for (SCROW nRow=nStartY; nRow<=nEndY; nRow++)
    {
        tools::Long nAdd = rDestDoc.GetRowHeight( nRow, 0 );
        if ( bLimitToPageSize && nSizeY+nAdd > aPaperSize.Height() && nSizeY )  // above limit?
            break;
        nSizeY += nAdd;
    }
    nSizeX = o3tl::convert(nSizeX, o3tl::Length::twip, o3tl::Length::mm100);
    nSizeY = o3tl::convert(nSizeY, o3tl::Length::twip, o3tl::Length::mm100);

//      m_aDocShellRef->SetVisAreaSize( Size(nSizeX,nSizeY) );

    tools::Rectangle aNewArea( Point(nPosX,nPosY), Size(nSizeX,nSizeY) );
    //TODO/LATER: why twice?!
    //m_aDocShellRef->SvInPlaceObject::SetVisArea( aNewArea );
    m_aDocShellRef->SetVisArea(aNewArea);

    m_aDocShellRef->UpdateOle(aViewData, true);

    //! SetDocumentModified?
    if ( rDestDoc.IsChartListenerCollectionNeedsUpdate() )
        rDestDoc.UpdateChartListenerCollection();
}

SfxObjectShell* ScTransferObj::SetDrawClipDoc( bool bAnyOle, const std::shared_ptr<ScDocument>& pDoc )
{
    // update ScGlobal::xDrawClipDocShellRef

    ScGlobal::xDrawClipDocShellRef.clear();
    if (bAnyOle)
    {
        ScGlobal::xDrawClipDocShellRef = new ScDocShell(SfxModelFlags::EMBEDDED_OBJECT | SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS, pDoc); // there must be a ref
        ScGlobal::xDrawClipDocShellRef->DoInitNew();
    }

    return ScGlobal::xDrawClipDocShellRef.get();
}

void ScTransferObj::StripRefs( ScDocument& rDoc,
                    SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY,
                    ScDocument& rDestDoc )
{
    //  In a clipboard doc the data don't have to be on the first sheet

    SCTAB nSrcTab = 0;
    while (nSrcTab < rDoc.GetTableCount() && !rDoc.HasTable(nSrcTab))
        ++nSrcTab;
    SCTAB nDestTab = 0;
    while (nDestTab < rDestDoc.GetTableCount() && !rDestDoc.HasTable(nDestTab))
        ++nDestTab;

    if (!rDoc.HasTable(nSrcTab) || !rDestDoc.HasTable(nDestTab))
    {
        OSL_FAIL("Sheet not found in ScTransferObj::StripRefs");
        return;
    }

    ScRange aRef;

    ScCellIterator aIter( rDoc, ScRange(nStartX, nStartY, nSrcTab, nEndX, nEndY, nSrcTab) );
    for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
    {
        if (aIter.getType() != CELLTYPE_FORMULA)
            continue;

        ScFormulaCell* pFCell = aIter.getFormulaCell();
        bool bOut = false;
        ScDetectiveRefIter aRefIter( rDoc, 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 = true;
        }
        if (bOut)
        {
            SCCOL nCol = aIter.GetPos().Col();
            SCROW nRow = aIter.GetPos().Row();

            FormulaError nErrCode = pFCell->GetErrCode();
            ScAddress aPos(nCol, nRow, nDestTab);
            if (nErrCode != FormulaError::NONE)
            {
                if ( rDestDoc.GetAttr( nCol,nRow,nDestTab, ATTR_HOR_JUSTIFY)->GetValue() ==
                        SvxCellHorJustify::Standard )
                    rDestDoc.ApplyAttr( nCol,nRow,nDestTab,
                            SvxHorJustifyItem(SvxCellHorJustify::Right, ATTR_HOR_JUSTIFY) );

                ScSetStringParam aParam;
                aParam.setTextInput();
                rDestDoc.SetString(aPos, ScGlobal::GetErrorString(nErrCode), &aParam);
            }
            else if (pFCell->IsValue())
            {
                rDestDoc.SetValue(aPos, pFCell->GetValue());
            }
            else
            {
                OUString aStr = pFCell->GetString().getString();
                if ( pFCell->IsMultilineResult() )
                {
                    ScFieldEditEngine& rEngine = rDestDoc.GetEditEngine();
                    rEngine.SetTextCurrentDefaults(aStr);
                    rDestDoc.SetEditText(ScAddress(nCol,nRow,nDestTab), rEngine.CreateTextObject());
                }
                else
                {
                    ScSetStringParam aParam;
                    aParam.setTextInput();
                    rDestDoc.SetString(aPos, aStr, &aParam);
                }
            }
        }
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=92 H=93 G=92

¤ Dauer der Verarbeitung: 0.9 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.