Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sw/source/uibase/dochdl/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 168 kB image not shown  
"_ustr : u"_ustr;
            while((nIdx = aExpand.indexOf(sSearchRowOrCol, nIdx)) > -1)
            {
                // skip rows/columns of nested tables, based on HTML indentation
                if ( lcl_getLevel(aExpand, nIdx) == nTableLevel + (bShifted ? 2 : 1) &&
                    // skip also strange hidden empty rows <tr></tr>
                    !aExpand.match("", nIdx - 4) )
                {
                    ++nSelectedRowsOrCols;
                }
                ++nIdx;
            }
            // are we at the beginning of the cell?
            bool bStartTableBoxNode =
                // first paragraph of the cell?
                rSh.GetCursor()->GetPointNode().GetIndex() == rSh.GetCursor()->GetPointNode().FindTableBoxStartNode()->GetIndex()+1 &&
                // beginning of the paragraph?
                !rSh.GetCursor()->GetPoint()->GetContentIndex();
            SfxDispatcher* pDispatch = rSh.GetView().GetViewFrame().GetDispatcher();

            // go start of the cell
            if (!bStartTableBoxNode)
                pDispatch->Execute(FN_START_OF_DOCUMENT, SfxCallMode::SYNCHRON);

            // store cursor position in row mode
            ::sw::mark::MarkBase* pMark = (!bRowMode || nSelectedRowsOrCols == 0) ? nullptr : rSh.SetBookmark(
                                    vcl::KeyCode(),
                                    SwMarkName(),
                                    IDocumentMarkAccess::MarkType::UNO_BOOKMARK );

            // add a new empty row/column before the actual table row/column and go there
            const sal_uInt16 nDispatchSlot = bRowMode ? FN_TABLE_INSERT_ROW_BEFORE : FN_TABLE_INSERT_COL_BEFORE;
            pDispatch->Execute(nDispatchSlot, SfxCallMode::SYNCHRON);
            pDispatch->Execute(bRowMode ? FN_LINE_UP : FN_CHAR_LEFT, SfxCallMode::SYNCHRON);

            // add the other new empty rows/columns after the actual table row/column
            if ( nSelectedRowsOrCols > 1 )
            {
                SfxInt16Item aCountItem( nDispatchSlot, nSelectedRowsOrCols-1 );
                SfxBoolItem aAfter( FN_PARAM_INSERT_AFTER, true );
                pDispatch->ExecuteList(nDispatchSlot,
                    SfxCallMode::SYNCHRON|SfxCallMode::RECORD,
                    { &aCountItem, &aAfter });
            }

            // paste rows
            bool bResult = SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
                                        nDestination, falsefalse, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext );

            // restore cursor position
            if (pMark != nullptr)
            {
                rSh.GotoMark( pMark );
                rSh.getIDocumentMarkAccess()->deleteMark( pMark );
            }

            return bResult;
        }
    }

    // special case for tables from draw application or 1-cell tables
    if( EXCHG_OUT_ACTION_INSERT_DRAWOBJ == nAction || bSingleCellTable )
    {
        if( rData.HasFormat( SotClipboardFormatId::RTF ) )
        {
            nAction = EXCHG_OUT_ACTION_INSERT_STRING;
            nFormat = SotClipboardFormatId::RTF;
        }
        else if( rData.HasFormat( SotClipboardFormatId::RICHTEXT ) )
        {
            nAction = EXCHG_OUT_ACTION_INSERT_STRING;
            nFormat = SotClipboardFormatId::RICHTEXT;
        }
    }

    // Tweak the format if necessary: the source application can be considered in this context,
    // while not in sot/ code.
    SwTransferable::SelectPasteFormat(rData, nAction, nFormat);

    collectUIInformation(u"PASTE"_ustr, u"parameter"_ustr);

    return EXCHG_INOUT_ACTION_NONE != nAction &&
            SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
                                        nDestination, falsefalse, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext, ePasteTable);
}

bool SwTransferable::PasteData( const TransferableDataHelper& rData,
                            SwWrtShell& rSh, sal_uInt8 nAction, SotExchangeActionFlags nActionFlags,
                            SotClipboardFormatId nFormat,
                            SotExchangeDest nDestination, bool bIsPasteFormat,
                            [[maybe_unused]] bool bIsDefault,
                            const Point* pPt, sal_Int8 nDropAction,
                            bool bPasteSelection, RndStdIds nAnchorType,
                            bool bIgnoreComments,
                            SwPasteContext* pContext,
                            PasteTableType ePasteTable )
{
    SwWait aWait( *rSh.GetView().GetDocShell(), false );
    std::unique_ptr<SwTrnsfrActionAndUndo, o3tl::default_delete<SwTrnsfrActionAndUndo>> pAction;
    SwModule* pMod = SwModule::get();

    bool bRet = false;
    bool bCallAutoCaption = false;

    if( pPt )
    {
        // external Drop
        if ((bPasteSelection ? !pMod->m_pXSelection : !pMod->m_pDragDrop) &&
                // The following condition is used for tdf#156111 to prevent a selection from being
                // cleared by the default case of the nDestination switch.
                !(rSh.GetCursorCnt() == 1 && rSh.TestCurrPam(*pPt) &&
                nDestination == SotExchangeDest::SWDOC_FREE_AREA &&
                nFormat == SotClipboardFormatId::SONLK))
        {
            switch( nDestination )
            {
            case SotExchangeDest::DOC_LNKD_GRAPH_W_IMAP:
            case SotExchangeDest::DOC_LNKD_GRAPHOBJ:
            case SotExchangeDest::DOC_GRAPH_W_IMAP:
            case SotExchangeDest::DOC_GRAPHOBJ:
            case SotExchangeDest::DOC_OLEOBJ:
            case SotExchangeDest::DOC_DRAWOBJ:
            case SotExchangeDest::DOC_URLBUTTON:
            case SotExchangeDest::DOC_GROUPOBJ:
                // select frames/objects
                SwTransferable::SetSelInShell( rSh, true, pPt );
                break;

            default:
                bool bLockView = rSh.IsViewLocked();
                if (nFormat == SotClipboardFormatId::SONLK)
                    rSh.LockView(true); // prevent view jump
                SwTransferable::SetSelInShell( rSh, false, pPt );
                rSh.LockView(bLockView);
                break;
            }
        }
    }
    else if( ( !GetSwTransferable( rData ) || bIsPasteFormat ) &&
            !rSh.IsTableMode() && rSh.HasSelection() )
    {
        // then delete the selections

--> --------------------

--> maximum size reached

--> --------------------

Quelle  swdtflvr.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 <config_features.h>

#include <com/sun/star/embed/XTransactedObject.hpp>
#include <com/sun/star/embed/Aspects.hpp>
#include <com/sun/star/embed/XEmbedObjectClipboardCreator.hpp>
#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
#include <com/sun/star/embed/MSOLEObjectSystemCreator.hpp>
#include <com/sun/star/text/XPasteListener.hpp>

#include <svtools/embedtransfer.hxx>
#include <svtools/insdlg.hxx>
#include <unotools/tempfile.hxx>
#include <comphelper/fileformat.h>
#include <comphelper/processfactory.hxx>
#include <comphelper/propertyvalue.hxx>
#include <comphelper/servicehelper.hxx>
#include <comphelper/storagehelper.hxx>
#include <comphelper/string.hxx>
#include <o3tl/deleter.hxx>
#include <o3tl/temporary.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <sot/filelist.hxx>
#include <svx/svxdlg.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <osl/endian.h>
#include <sfx2/linkmgr.hxx>
#include <tools/urlobj.hxx>
#include <vcl/weld.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/viewfrm.hxx>
#include <svl/stritem.hxx>
#include <vcl/imap.hxx>
#include <sot/storage.hxx>
#include <vcl/graph.hxx>
#include <svl/urihelper.hxx>
#include <svx/svdmodel.hxx>
#include <svx/xmlexchg.hxx>
#include <svx/dbaexchange.hxx>
#include <svx/clipfmtitem.hxx>
#include <sfx2/mieclip.hxx>
#include <svl/urlbmk.hxx>
#include <vcl/inetimg.hxx>
#include <svx/fmview.hxx>
#include <sfx2/docfilt.hxx>
#include <vcl/imapobj.hxx>
#include <sfx2/docfile.hxx>
#include <unotools/transliterationwrapper.hxx>
#include <unotools/streamwrap.hxx>
#include <vcl/graphicfilter.hxx>

#ifdef _WIN32
#include <prewin.h>
#include <postwin.h>
#include <o3tl/char16_t2wchar_t.hxx>
#include <osl/file.hxx>
#include <systools/win32/extended_max_path.hxx>
#endif

#include <svx/unomodel.hxx>
#include <fmturl.hxx>
#include <fmtinfmt.hxx>
#include <swdtflvr.hxx>
#include <shellio.hxx>
#include <ddefld.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <IDocumentFieldsAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <IDocumentState.hxx>
#include <IMark.hxx>
#include <section.hxx>
#include <ndtxt.hxx>
#include <edtdd.hxx>
#include <edtwin.hxx>
#include <navicont.hxx>
#include <swcont.hxx>
#include <wrtsh.hxx>
#include <swmodule.hxx>
#include <view.hxx>
#include <docsh.hxx>
#include <wdocsh.hxx>
#include <fldbas.hxx>
#include <swundo.hxx>
#include <pam.hxx>
#include <ndole.hxx>
#include <swwait.hxx>
#include <viewopt.hxx>
#include <SwCapObjType.hxx>
#include <cmdid.h>
#include <strings.hrc>
#include <svx/svditer.hxx>
#include <editeng/eeitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/prntitem.hxx>
#include <svx/svdpage.hxx>
#include <avmedia/mediawindow.hxx>
#include <swcrsr.hxx>
#include <SwRewriter.hxx>
#include <vcl/svapp.hxx>
#include <swserv.hxx>
#include <fmtmeta.hxx>
#include <itabenum.hxx>
#include <iodetect.hxx>
#include <unotextrange.hxx>
#include <unoframe.hxx>
#include <txatbase.hxx>
#include <unoparaframeenum.hxx>
#include <vcl/uitest/logger.hxx>
#include <vcl/uitest/eventdescription.hxx>

#include <vcl/GraphicNativeTransform.hxx>
#include <vcl/GraphicNativeMetadata.hxx>
#include <vcl/TypeSerializer.hxx>
#include <comphelper/lok.hxx>
#include <sfx2/classificationhelper.hxx>
#include <sfx2/sfxdlg.hxx>
#include <comphelper/classids.hxx>
#include <osl/diagnose.h>

#include <memory>

/* default (A4 format) width of 210mm - 2 * border size (border on both sides) */
constexpr tools::Long constOleWidthInMm = 210 - 2 * lMinBorderInMm;

constexpr Size constOleSize100mm(
    constOleWidthInMm * 100, // convert from mm to 100mm
    3000 // 3 cm
);

constexpr Size constOleSizeTwip = o3tl::convert(constOleSize100mm, o3tl::Length::mm100, o3tl::Length::twip);

constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_DRAWMODEL = 0x00000001;
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_HTML      = 0x00000002;
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_RTF       = 0x00000004;
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_STRING    = 0x00000008;
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_SWOLE     = 0x00000010;
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_DDE       = 0x00000020;
constexpr sal_uInt32 SWTRANSFER_OBJECTTYPE_RICHTEXT  = 0x00000040;

using namespace ::svx;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::datatransfer;
namespace {

void collectUIInformation(const OUString& rAction, const OUString& aParameters)
{
    EventDescription aDescription;
    aDescription.aAction = rAction;
    aDescription.aParameters = {{"parameters", aParameters}};
    aDescription.aID = "writer_edit";
    aDescription.aKeyWord = "SwEditWinUIObject";
    aDescription.aParent = "MainWindow";
    UITestLogger::getInstance().logEvent(aDescription);
}

}

class SwTransferDdeLink : public ::sfx2::SvBaseLink
{
    OUString m_sName;
    ::sfx2::SvLinkSourceRef m_xRefObj;
    SwTransferable& m_rTransfer;
    SwDocShell* m_pDocShell;
    sal_uLong m_nOldTimeOut;
    bool m_bDelBookmark : 1;
    bool m_bInDisconnect : 1;

    bool FindDocShell();

    using sfx2::SvBaseLink::Disconnect;

protected:
    virtual ~SwTransferDdeLink() override;

public:
    SwTransferDdeLink( SwTransferable& rTrans, SwWrtShell& rSh );

    virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
        const OUString& rMimeType, const css::uno::Any & rValue ) override;
    virtual void Closed() override;

    bool WriteData( SvStream& rStrm );

    void Disconnect( bool bRemoveDataAdvise );
};

/// Tracks the boundaries of pasted content and notifies listeners.
class SwPasteContext
{
public:
    SwPasteContext(SwWrtShell& rWrtShell);
    ~SwPasteContext();

    void remember();
    void forget();

private:
    SwWrtShell& m_rWrtShell;
    std::optional<SwPaM> m_oPaM;
    sal_Int32 m_nStartContent = 0;
};

namespace {

// helper class for Action and Undo enclosing
class SwTrnsfrActionAndUndo
{
    SwWrtShell *pSh;
public:
    SwTrnsfrActionAndUndo( SwWrtShell *pS, bool bDelSel = false, SwPasteContext* pContext = nullptr)
        : pSh( pS )
    {
        pSh->StartUndo( SwUndoId::PASTE_CLIPBOARD );
        if( bDelSel )
        {
            if (pContext)
                pContext->forget();
            pSh->DelRight();
            if (pContext)
                pContext->remember();
        }
        pSh->StartAllAction();
    }
    ~SwTrnsfrActionAndUndo() COVERITY_NOEXCEPT_FALSE
    {
        pSh->EndUndo();
        pSh->EndAllAction();
    }
};

}

SwTransferable::SwTransferable( SwWrtShell& rSh )
    : m_pWrtShell( &rSh ),
    m_pCreatorView( nullptr ),
    m_pOrigGraphic( nullptr ),
    m_eBufferType( TransferBufferType::NONE ),
    m_bOldIdle(false),
    m_bCleanUp(false)
{
    rSh.GetView().AddTransferable(*this);
    SwDocShell* pDShell = rSh.GetDoc()->GetDocShell();
    if( !pDShell )
        return;

    pDShell->FillTransferableObjectDescriptor( m_aObjDesc );
    if( pDShell->GetMedium() )
    {
        const INetURLObject& rURLObj = pDShell->GetMedium()->GetURLObject();
        m_aObjDesc.maDisplayName = URIHelper::removePassword(
                            rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
                            INetURLObject::EncodeMechanism::WasEncoded,
                            INetURLObject::DecodeMechanism::Unambiguous );
    }

    PrepareOLE( m_aObjDesc );
}

SwTransferable::~SwTransferable()
{
    SolarMutexGuard aSolarGuard;

    // the DDELink still needs the WrtShell!
    DisconnectDDE();

    m_pWrtShell = nullptr;

    // release reference to the document so that aDocShellRef will delete
    // it (if aDocShellRef is set). Otherwise, the OLE nodes keep references
    // to their sub-storage when the storage is already dead.
    m_pClpDocFac.reset();

    // first close, then the Ref. can be cleared as well, so that
    // the DocShell really gets deleted!
    if( m_aDocShellRef.Is() )
    {
        SfxObjectShell * pObj = m_aDocShellRef;
        SwDocShell* pDocSh = static_cast<SwDocShell*>(pObj);
        pDocSh->DoClose();
    }
    m_aDocShellRef.Clear();

    if (SwModule* pMod = SwModule::get())
    {
        if ( pMod->m_pDragDrop == this )
            pMod->m_pDragDrop = nullptr;
        else if ( pMod->m_pXSelection == this )
            pMod->m_pXSelection = nullptr;
    }

    m_eBufferType = TransferBufferType::NONE;
}

static SwDoc& lcl_GetDoc(SwDocFac & rDocFac)
{
    SwDoc& rDoc = rDocFac.GetDoc();
    rDoc.SetClipBoard( true );
    return rDoc;
}

void SwTransferable::ObjectReleased()
{
    SwModule* pMod = SwModule::get();
    if (!pMod)
        return;
    ifthis == pMod->m_pDragDrop )
        pMod->m_pDragDrop = nullptr;
    else ifthis == pMod->m_pXSelection )
        pMod->m_pXSelection = nullptr;
}

void SwTransferable::AddSupportedFormats()
{
    // only need if we are the current XSelection Object
    if (this == SwModule::get()->m_pXSelection || comphelper::LibreOfficeKit::isActive())
    {
        SetDataForDragAndDrop( Point( 0,0) );
    }
}

void SwTransferable::InitOle( SfxObjectShell* pDoc )
{
    //set OleVisArea. Upper left corner of the page and size of
    //RealSize in Twips.
    const Size aSz(constOleSizeTwip);
    SwRect aVis( Point( DOCUMENTBORDER, DOCUMENTBORDER ), aSz );
    pDoc->SetVisArea( aVis.SVRect() );
}

uno::Reference < embed::XEmbeddedObject > SwTransferable::FindOLEObj( sal_Int64& nAspect ) const
{
    uno::Reference < embed::XEmbeddedObject > xObj;
    if( m_pClpDocFac )
    {
        SwIterator<SwContentNode,SwFormatColl> aIter( *m_pClpDocFac->GetDoc().GetDfltGrfFormatColl() );
        for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
            if( SwNodeType::Ole == pNd->GetNodeType() )
            {
                xObj = static_cast<SwOLENode*>(pNd)->GetOLEObj().GetOleRef();
                nAspect = static_cast<SwOLENode*>(pNd)->GetAspect();
                break;
            }
    }
    return xObj;
}

const Graphic* SwTransferable::FindOLEReplacementGraphic() const
{
    if( m_pClpDocFac )
    {
        SwIterator<SwContentNode,SwFormatColl> aIter( *m_pClpDocFac->GetDoc().GetDfltGrfFormatColl() );
        for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() )
            if( SwNodeType::Ole == pNd->GetNodeType() )
            {
                return static_cast<SwOLENode*>(pNd)->GetGraphic();
            }
    }

    return nullptr;
}

void SwTransferable::RemoveDDELinkFormat(vcl::Window& rWin)
{
    RemoveFormat( SotClipboardFormatId::LINK );
    if (rWin.GetClipboard()->getContents().get() == this)
        CopyToClipboard(&rWin);
}

void SwTransferable::DisconnectDDE()
{
    if( m_xDdeLink.is() )
    {
        m_xDdeLink->Disconnect( true );
        m_xDdeLink.clear();
    }
}

namespace
{
    //Resolves: fdo#40717 surely when we create a clipboard document we should
    //overwrite the clipboard documents styles and settings with that of the
    //source, so that we can WYSIWYG paste. If we want that the destinations
    //styles are used over the source styles, that's a matter of the
    //destination paste code to handle, not the source paste code.
    void lclOverWriteDoc(SwWrtShell &rSrcWrtShell, SwDoc &rDest, bool bDeleteRedlines = true)
    {
        const SwDoc &rSrc = *rSrcWrtShell.GetDoc();

        rDest.ReplaceCompatibilityOptions(rSrc);
        rDest.ReplaceDefaults(rSrc);

        //It would probably make most sense here to only insert the styles used
        //by the selection, e.g. apply SwDoc::IsUsed on styles ?
        rDest.ReplaceStyles(rSrc, false);

        rSrcWrtShell.Copy(rDest, /*pNewClpText=*/nullptr, bDeleteRedlines);

        rDest.GetMetaFieldManager().copyDocumentProperties(rSrc);
    }

    void lclCheckAndPerformRotation(Graphic& aGraphic)
    {
        GraphicNativeMetadata aMetadata;
        if ( !aMetadata.read(aGraphic) )
            return;

        Degree10 aRotation = aMetadata.getRotation();
        if (aRotation)
        {
            GraphicNativeTransform aTransform( aGraphic );
            aTransform.rotate( aRotation );
        }
    }
}

sal_Bool SAL_CALL SwTransferable::isComplex()
{
    sal_Int32 nTextLength = 0;
    SwNodes& aNodes = m_pWrtShell->GetDoc()->GetNodes();
    for (SwPaM& rPaM : m_pWrtShell->GetCursor()->GetRingContainer())
    {
        for (SwNodeOffset nIndex = rPaM.GetMark()->GetNodeIndex();
             nIndex <= rPaM.GetPoint()->GetNodeIndex(); ++nIndex)
        {
            SwNode& rNd = *aNodes[nIndex];

            SwTextNode* pTextNode = rNd.GetTextNode();
            if (pTextNode)
            {
                if (pTextNode->HasHints())
                {
                    for (size_t nHint = 0; nHint < pTextNode->GetSwpHints().Count(); ++nHint)
                    {
                        SwTextAttr* pHint = pTextNode->GetSwpHints().Get(nHint);
                        if (pHint->Which() == RES_TXTATR_FLYCNT)
                        {
                            return true// Complex
                        }
                    }
                }

                FrameClientSortList_t vFrames;
                ::CollectFrameAtNode(rNd, vFrames, true);
                if (!vFrames.empty())
                {
                    // There is an at-char anchored object to this node, that's complex.
                    return true;
                }

                nTextLength += pTextNode->GetText().getLength();
                if (nTextLength >= 1024 * 512)
                    return true// Complex
            }
        }
    }

    if (m_pWrtShell->GetSelectionType() == SelectionType::DrawObject)
        return true// Complex

    // Simple
    return false;
}

bool SwTransferable::GetData( const DataFlavor& rFlavor, const OUString& rDestDoc )
{
    SotClipboardFormatId nFormat = SotExchange::GetFormat( rFlavor );

    // we can only fulfil the request if
    // 1) we have data for this format
    // 2) we have either a clipboard document (pClpDocFac), or
    //    we have a SwWrtShell (so we can generate a new clipboard document)
    if( !HasFormat( nFormat ) || ( m_pClpDocFac == nullptr && m_pWrtShell == nullptr ) )
        return false;

    if( !m_pClpDocFac )
    {
        SelectionType nSelectionType = m_pWrtShell->GetSelectionType();

        // when pending we will not get the correct type, but SelectionType::Text
        // as fallback. This *happens* during D&D, so we need to check if we are in
        // the fallback and just try to get a graphic
        const bool bPending(m_pWrtShell->ActionPend());

        // SEL_GRF is from ContentType of editsh
        if(bPending || ((SelectionType::Graphic | SelectionType::DrawObject | SelectionType::DbForm) & nSelectionType))
        {
            m_oClpGraphic.emplace();
            if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_oClpGraphic ))
                m_pOrigGraphic = &*m_oClpGraphic;
            m_oClpBitmap.emplace();
            if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_oClpBitmap ))
                m_pOrigGraphic = &*m_oClpBitmap;

            // is it a URL-Button ?
            OUString sURL;
            OUString sDesc;
            if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
            {
                m_oBookmark.emplace( sURL, sDesc );
                m_eBufferType = TransferBufferType::InetField;
            }
        }

        m_pClpDocFac.reset(new SwDocFac);
        SwDoc& rTmpDoc = lcl_GetDoc(*m_pClpDocFac);

        rTmpDoc.getIDocumentFieldsAccess().LockExpFields();     // never update fields - leave text as it is
        lclOverWriteDoc(*m_pWrtShell, rTmpDoc);

        // in CORE a new one was created (OLE-objects copied!)
        m_aDocShellRef = rTmpDoc.GetTmpDocShell();
        if( m_aDocShellRef.Is() )
            SwTransferable::InitOle( m_aDocShellRef );
        rTmpDoc.SetTmpDocShell( nullptr );

        if( nSelectionType & SelectionType::Text && !m_pWrtShell->HasMark() )
        {
            SwContentAtPos aContentAtPos( IsAttrAtPos::InetAttr );

            Point aPos( SwEditWin::GetDDStartPosX(), SwEditWin::GetDDStartPosY());

            bool bSelect = g_bExecuteDrag &&
                            m_pWrtShell->GetView().GetDocShell() &&
                            !m_pWrtShell->GetView().GetDocShell()->IsReadOnly();
            if( m_pWrtShell->GetContentAtPos( aPos, aContentAtPos, bSelect ) )
            {
                m_oBookmark.emplace(
                        static_cast<const SwFormatINetFormat*>(aContentAtPos.aFnd.pAttr)->GetValue(),
                        aContentAtPos.sStr );
                m_eBufferType = TransferBufferType::InetField;
                if( bSelect )
                    m_pWrtShell->SelectTextAttr( RES_TXTATR_INETFMT );
            }
        }
        if( m_pWrtShell->IsFrameSelected() )
        {
            SfxItemSetFixed<RES_URL, RES_URL> aSet( m_pWrtShell->GetAttrPool() );
            m_pWrtShell->GetFlyFrameAttr( aSet );
            const SwFormatURL& rURL = aSet.Get( RES_URL );
            if( rURL.GetMap() )
                m_pImageMap.reset(new ImageMap( *rURL.GetMap() ));
            else if( !rURL.GetURL().isEmpty() )
                m_pTargetURL.reset(new INetImage(OUString(), rURL.GetURL(),
                                            rURL.GetTargetFrameName() ));
        }
    }

    bool bOK = false;
    if( TransferBufferType::Ole == m_eBufferType )
    {
        //TODO/MBA: testing - is this the "single OLE object" case?!
        // get OLE-Object from ClipDoc and get the data from that.
        sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT; // will be set in the next statement
        uno::Reference < embed::XEmbeddedObject > xObj = FindOLEObj( nAspect );
        const Graphic* pOLEGraph = FindOLEReplacementGraphic();
        if( xObj.is() )
        {
            TransferableDataHelper aD( new SvEmbedTransferHelper( xObj, pOLEGraph, nAspect ) );
            uno::Any aAny = aD.GetAny(rFlavor, rDestDoc);
            if( aAny.hasValue() )
                bOK = SetAny( aAny );
        }

        // the following solution will be used in the case when the object can not generate the image
        // TODO/LATER: in future the transferhelper must probably be created based on object and the replacement stream
        // TODO: Block not required now, SvEmbedTransferHelper should be able to handle GDIMetaFile format
        if ( nFormat == SotClipboardFormatId::GDIMETAFILE )
        {
            pOLEGraph = FindOLEReplacementGraphic();
            if ( pOLEGraph )
                bOK = SetGDIMetaFile( pOLEGraph->GetGDIMetaFile() );
        }
    }
    else
    {
        switch( nFormat )
        {
        case SotClipboardFormatId::LINK:
            if( m_xDdeLink.is() )
                bOK = SetObject( m_xDdeLink.get(), SWTRANSFER_OBJECTTYPE_DDE, rFlavor );
            break;

        case SotClipboardFormatId::OBJECTDESCRIPTOR:
        case SotClipboardFormatId::LINKSRCDESCRIPTOR:
            bOK = SetTransferableObjectDescriptor( m_aObjDesc );
            break;

        case SotClipboardFormatId::DRAWING:
            {
                SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
                bOK = SetObject( rDoc.getIDocumentDrawModelAccess().GetDrawModel(),
                                SWTRANSFER_OBJECTTYPE_DRAWMODEL, rFlavor );
            }
            break;

        case SotClipboardFormatId::STRING:
        {
            SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
            bOK = SetObject( &rDoc, SWTRANSFER_OBJECTTYPE_STRING, rFlavor );
        }
        break;
        case SotClipboardFormatId::RTF:
        {
            SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
            bOK = SetObject( &rDoc, SWTRANSFER_OBJECTTYPE_RTF, rFlavor );
        }
        break;
        case SotClipboardFormatId::RICHTEXT:
        {
            SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
            bOK = SetObject( &rDoc, SWTRANSFER_OBJECTTYPE_RICHTEXT, rFlavor );
        }
        break;

        case SotClipboardFormatId::HTML:
        {
            SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
            bOK = SetObject( &rDoc, SWTRANSFER_OBJECTTYPE_HTML, rFlavor );
        }
            break;

        case SotClipboardFormatId::SVXB:
            if( m_eBufferType & TransferBufferType::Graphic && m_pOrigGraphic )
                bOK = SetGraphic( *m_pOrigGraphic );
            break;

        case SotClipboardFormatId::GDIMETAFILE:
            if( m_eBufferType & TransferBufferType::Graphic )
                bOK = SetGDIMetaFile( m_oClpGraphic->GetGDIMetaFile() );
            break;
        case SotClipboardFormatId::BITMAP:
        case SotClipboardFormatId::PNG:
            // Neither pClpBitmap nor pClpGraphic are necessarily set
            if( (m_eBufferType & TransferBufferType::Graphic) && (m_oClpBitmap || m_oClpGraphic))
                bOK = SetBitmapEx( (m_oClpBitmap ? m_oClpBitmap : m_oClpGraphic)->GetBitmapEx(), rFlavor );
            break;

        case SotClipboardFormatId::SVIM:
            if( m_pImageMap )
                bOK = SetImageMap( *m_pImageMap );
            break;

        case SotClipboardFormatId::INET_IMAGE:
            if( m_pTargetURL )
                bOK = SetINetImage( *m_pTargetURL, rFlavor );
            break;

        case SotClipboardFormatId::SOLK:
        case SotClipboardFormatId::NETSCAPE_BOOKMARK:
        case SotClipboardFormatId::FILEGRPDESCRIPTOR:
        case SotClipboardFormatId::FILECONTENT:
        case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
        case SotClipboardFormatId::SIMPLE_FILE:
            if( (TransferBufferType::InetField & m_eBufferType) && m_oBookmark )
                bOK = SetINetBookmark( *m_oBookmark, rFlavor );
            break;

        case SotClipboardFormatId::EMBED_SOURCE:
            if( !m_aDocShellRef.Is() )
            {
                SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
                m_aDocShellRef = new SwDocShell(rDoc, SfxObjectCreateMode::EMBEDDED);
                m_aDocShellRef->DoInitNew();
                SwTransferable::InitOle( m_aDocShellRef );
            }
            bOK = SetObject( &m_aDocShellRef, SWTRANSFER_OBJECTTYPE_SWOLE,
                            rFlavor );
            break;
        defaultbreak;
        }
    }
    return bOK;
}

bool SwTransferable::WriteObject( SvStream& rOStream,
                                    void* pObject, sal_uInt32 nObjectType,
                                    const DataFlavor& /*rFlavor*/ )
{
    bool bRet = false;
    WriterRef xWrt;

    switch( nObjectType )
    {
    case SWTRANSFER_OBJECTTYPE_DRAWMODEL:
        {
            // don't change the sequence of commands
            SdrModel *pModel = static_cast<SdrModel*>(pObject);
            rOStream.SetBufferSize( 16348 );

            // for the changed pool defaults from drawing layer pool set those
            // attributes as hard attributes to preserve them for saving
            const SfxItemPool& rItemPool = pModel->GetItemPool();
            const SvxFontHeightItem& rDefaultFontHeight = rItemPool.GetUserOrPoolDefaultItem(EE_CHAR_FONTHEIGHT);

            // SW should have no MasterPages
            OSL_ENSURE(0 == pModel->GetMasterPageCount(), "SW with MasterPages (!)");

            for(sal_uInt16 a(0); a < pModel->GetPageCount(); a++)
            {
                const SdrPage* pPage = pModel->GetPage(a);
                SdrObjListIter aIter(pPage, SdrIterMode::DeepNoGroups);

                while(aIter.IsMore())
                {
                    SdrObject* pObj = aIter.Next();
                    const SvxFontHeightItem& rItem = pObj->GetMergedItem(EE_CHAR_FONTHEIGHT);

                    if(rItem.GetHeight() == rDefaultFontHeight.GetHeight())
                    {
                        pObj->SetMergedItem(rDefaultFontHeight);
                    }
                }
            }

            {
                uno::Reference<io::XOutputStream> xDocOut( new utl::OOutputStreamWrapper( rOStream ) );
                SvxDrawingLayerExport( pModel, xDocOut );
            }

            bRet = ERRCODE_NONE == rOStream.GetError();
        }
        break;

    case SWTRANSFER_OBJECTTYPE_SWOLE:
        {
            SfxObjectShell*   pEmbObj = static_cast<SfxObjectShell*>(pObject);
            try
            {
                ::utl::TempFileFast aTempFile;
                SvStream* pTempStream = aTempFile.GetStream(StreamMode::READWRITE);
                uno::Reference< embed::XStorage > xWorkStore =
                    ::comphelper::OStorageHelper::GetStorageFromStream( new utl::OStreamWrapper(*pTempStream), embed::ElementModes::READWRITE );

                // write document storage
                pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, false );
                // mba: no BaseURL 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();

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

                xWorkStore->dispose();
                xWorkStore.clear();
            }
            catch (const uno::Exception&)
            {
            }

            bRet = ( rOStream.GetError() == ERRCODE_NONE );
        }
        break;

    case SWTRANSFER_OBJECTTYPE_DDE:
        {
            rOStream.SetBufferSize( 1024 );
            SwTransferDdeLink* pDdeLnk = static_cast<SwTransferDdeLink*>(pObject);
            if( pDdeLnk->WriteData( rOStream ) )
            {
                bRet = ERRCODE_NONE == rOStream.GetError();
            }
        }
        break;

    case SWTRANSFER_OBJECTTYPE_HTML:
    {
        // LOK is interested in getting images embedded for copy/paste support.
        GetHTMLWriter( comphelper::LibreOfficeKit::isActive() ? u"EmbedImages;NoPrettyPrint"_ustr : OUString(), OUString(), xWrt );
        break;
    }

    case SWTRANSFER_OBJECTTYPE_RTF:
    case SWTRANSFER_OBJECTTYPE_RICHTEXT:
        GetRTFWriter(std::u16string_view(), OUString(), xWrt);
        break;

    case SWTRANSFER_OBJECTTYPE_STRING:
        GetASCWriter(std::u16string_view(), OUString(), xWrt);
        if( xWrt.is() )
        {
            SwAsciiOptions aAOpt;
            aAOpt.SetCharSet( RTL_TEXTENCODING_UTF8 );
            xWrt->SetAsciiOptions( aAOpt );

            // no start char for clipboard
            xWrt->m_bUCS2_WithStartChar = false;
        }
        break;
    defaultbreak;
    }

    if( xWrt.is() )
    {
        SwDoc* pDoc = static_cast<SwDoc*>(pObject);
        xWrt->m_bWriteClipboardDoc = true;
        xWrt->m_bWriteOnlyFirstTable = bool(TransferBufferType::Table & m_eBufferType);
        xWrt->SetShowProgress(false);

#if defined(DEBUGPASTE)
        SvFileStream aPasteDebug(
            u"PASTEBUFFER.debug"_ustr, StreamMode::WRITE|StreamMode::TRUNC);
        SwWriter aDbgWrt( aPasteDebug, *pDoc );
        aDbgWrt.Write( xWrt );
#endif

        SwWriter aWrt( rOStream, *pDoc );
        if( ! aWrt.Write( xWrt ).IsError() )
        {
            rOStream.WriteChar( '\0' );               // terminate with a zero
            bRet = true;
        }
    }

    return bRet;
}

int SwTransferable::Cut()
{
    int nRet = Copy( true );
    if( nRet )
        DeleteSelection();
    collectUIInformation(u"CUT"_ustr, u"parameter"_ustr);
    return nRet;
}

void SwTransferable::DeleteSelection()
{
    if(!m_pWrtShell)
        return;
    // ask for type of selection before action-bracketing
    const SelectionType nSelection = m_pWrtShell->GetSelectionType();
    // cut rows or columns selected by enhanced table selection and wholly selected tables
    bool bCutMode = ( SelectionType::TableCell & nSelection ) && ( (SelectionType::TableRow | SelectionType::TableCol) & nSelection ||
        m_pWrtShell->HasWholeTabSelection() );

    m_pWrtShell->StartUndo( SwUndoId::START );
    if( bCutMode )
    {
        if( !(SelectionType::TableCol & nSelection) )
            m_pWrtShell->DeleteTable();
        else
        {
            SfxDispatcher* pDispatch = m_pWrtShell->GetView().GetViewFrame().GetDispatcher();
            pDispatch->Execute(FN_TABLE_DELETE_COL, SfxCallMode::SYNCHRON);
        }
    }
    else
    {
        if( ( SelectionType::Text | SelectionType::Table ) & nSelection )
            m_pWrtShell->IntelligentCut( nSelection );
        m_pWrtShell->DelRight();
    }
    m_pWrtShell->EndUndo( SwUndoId::END );
}

static void DeleteDDEAndReminderMarks(SwDoc & rDest)
{
    IDocumentMarkAccess *const pMarkAccess = rDest.getIDocumentMarkAccess();
    std::vector< ::sw::mark::MarkBase* > vMarks;
    // find all DDE-Bookmarks and Navigator-Reminders
    for (auto ppMark = pMarkAccess->getAllMarksBegin();
        ppMark != pMarkAccess->getAllMarksEnd();
        ++ppMark)
    {
        IDocumentMarkAccess::MarkType eMarkType = IDocumentMarkAccess::GetType(**ppMark);
        if (eMarkType == IDocumentMarkAccess::MarkType::DDE_BOOKMARK
            || eMarkType == IDocumentMarkAccess::MarkType::NAVIGATOR_REMINDER)
        {
            vMarks.push_back(*ppMark);
        }
    }
    // remove all DDE-Bookmarks, they are invalid inside the clipdoc!
    // and remove all Navigator-Reminders (tdf#165223)
    for (const auto& rpMark : vMarks)
    {
        pMarkAccess->deleteMark(rpMark);
    }
}

void SwTransferable::PrepareForCopyTextRange(SwPaM & rPaM)
{
    std::optional<SwWait> oWait;
    if (m_pWrtShell->ShouldWait())
    {
        oWait.emplace( *m_pWrtShell->GetView().GetDocShell(), true );
    }

    m_pClpDocFac.reset(new SwDocFac);

    SwDoc& rDest(lcl_GetDoc(*m_pClpDocFac));
    rDest.getIDocumentFieldsAccess().LockExpFields(); // Never update fields - leave text as is
    {
        SwDoc const& rSrc(*m_pWrtShell->GetDoc());
        assert(&rSrc == &rPaM.GetDoc());

        rDest.ReplaceCompatibilityOptions(rSrc);
        rDest.ReplaceDefaults(rSrc);

        //It would probably make most sense here to only insert the styles used
        //by the selection, e.g. apply SwDoc::IsUsed on styles ?
        rDest.ReplaceStyles(rSrc, false);

        // relevant bits of rSrcWrtShell.Copy(rDest);
        rDest.GetIDocumentUndoRedo().DoUndo(false); // always false!
        rDest.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::DeleteRedlines );

        SwNodeIndex const aIdx(rDest.GetNodes().GetEndOfContent(), -1);
        SwContentNode *const pContentNode(aIdx.GetNode().GetContentNode());
        SwPosition aPos(aIdx, pContentNode, pContentNode ? pContentNode->Len() : 0);

        rSrc.getIDocumentContentOperations().CopyRange(rPaM, aPos, SwCopyFlags::CheckPosInFly);

        rDest.getIDocumentRedlineAccess().SetRedlineFlags_intern( RedlineFlags::NONE );

        rDest.GetMetaFieldManager().copyDocumentProperties(rSrc);
    }

    DeleteDDEAndReminderMarks(rDest);

    // a new one was created in core (OLE objects copied!)
    m_aDocShellRef = rDest.GetTmpDocShell();
    if (m_aDocShellRef.Is())
        SwTransferable::InitOle( m_aDocShellRef );
    rDest.SetTmpDocShell( nullptr );

    // let's add some formats
    AddFormat( SotClipboardFormatId::EMBED_SOURCE );
    AddFormat( SotClipboardFormatId::RTF );
#if HAVE_FEATURE_DESKTOP
    AddFormat( SotClipboardFormatId::RICHTEXT );
    AddFormat( SotClipboardFormatId::HTML );
#endif
    AddFormat( SotClipboardFormatId::STRING );
}

int SwTransferable::PrepareForCopy( bool bIsCut, bool bDeleteRedlines )
{
    int nRet = 1;
    if(!m_pWrtShell)
        return 0;

    if ( m_pWrtShell->GetTableInsertMode() != SwTable::SEARCH_NONE )
        m_pWrtShell->SetTableInsertMode( SwTable::SEARCH_NONE );

    if ( m_pWrtShell->GetTableCopied() )
        m_pWrtShell->SetTableCopied( false );

    OUString sGrfNm;
    const SelectionType nSelection = m_pWrtShell->GetSelectionType();
    if( nSelection == SelectionType::Graphic )
    {
        m_oClpGraphic.emplace();
        if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_oClpGraphic ))
            m_pOrigGraphic = &*m_oClpGraphic;
        m_oClpBitmap.emplace();
        if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_oClpBitmap ))
            m_pOrigGraphic = &*m_oClpBitmap;

        m_pClpDocFac.reset(new SwDocFac);
        SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
        m_pWrtShell->Copy(rDoc);

#if HAVE_FEATURE_DESKTOP
        if (m_pOrigGraphic && !m_pOrigGraphic->GetBitmapEx().IsEmpty())
          AddFormat( SotClipboardFormatId::SVXB );
#endif

        PrepareOLE( m_aObjDesc );
        AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );

        const Graphic* pGrf = m_pWrtShell->GetGraphic();
        if( pGrf && pGrf->IsSupportedGraphic() )
        {
            AddFormat( SotClipboardFormatId::PNG );
#if HAVE_FEATURE_DESKTOP
            AddFormat( SotClipboardFormatId::GDIMETAFILE );
            AddFormat( SotClipboardFormatId::BITMAP );
#endif
        }
        m_eBufferType = TransferBufferType::Graphic;
        m_pWrtShell->GetGrfNms( &sGrfNm, nullptr );
    }
    else if ( nSelection == SelectionType::Ole )
    {
        m_pClpDocFac.reset(new SwDocFac);
        SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
        m_aDocShellRef = new SwDocShell(rDoc, SfxObjectCreateMode::EMBEDDED);
        m_aDocShellRef->DoInitNew();
        m_pWrtShell->Copy(rDoc);

        AddFormat( SotClipboardFormatId::EMBED_SOURCE );

        // --> OD #i98753#
        // set size of embedded object at the object description structure
        m_aObjDesc.maSize = o3tl::convert(m_pWrtShell->GetObjSize(), o3tl::Length::twip, o3tl::Length::mm100);

        // <--
        PrepareOLE( m_aObjDesc );

#if HAVE_FEATURE_DESKTOP
        AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
        AddFormat( SotClipboardFormatId::GDIMETAFILE );

        // Fetch the formats supported via embedtransferhelper as well
        sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
        uno::Reference < embed::XEmbeddedObject > xObj = FindOLEObj( nAspect );
        const Graphic* pOLEGraph = FindOLEReplacementGraphic();
        if( xObj.is() )
        {
            TransferableDataHelper aD( new SvEmbedTransferHelper( xObj, pOLEGraph, nAspect ) );
            if ( aD.GetTransferable().is() )
            {
                DataFlavorExVector              aVector( aD.GetDataFlavorExVector() );

                forconst auto& rItem : aVector )
                    AddFormat( rItem );
            }
        }
#endif
        m_eBufferType = TransferBufferType::Ole;
    }
    // Is there anything to provide anyway?
    else if ( m_pWrtShell->IsSelection() || m_pWrtShell->IsFrameSelected() ||
              m_pWrtShell->GetSelectedObjCount() )
    {
        std::optional<SwWait> oWait;
        if( m_pWrtShell->ShouldWait() )
            oWait.emplace( *m_pWrtShell->GetView().GetDocShell(), true );

        m_pClpDocFac.reset(new SwDocFac);

        // create additional cursor so that equal treatment of keyboard
        // and mouse selection is possible.
        // In AddMode with keyboard selection, the new cursor is not created
        // before the cursor is moved after end of selection.
        if( m_pWrtShell->IsAddMode() && m_pWrtShell->SwCursorShell::HasSelection() )
            m_pWrtShell->CreateCursor();

        SwDoc& rTmpDoc = lcl_GetDoc(*m_pClpDocFac);

        rTmpDoc.getIDocumentFieldsAccess().LockExpFields();     // Never update fields - leave text as is
        lclOverWriteDoc(*m_pWrtShell, rTmpDoc, bDeleteRedlines);

        DeleteDDEAndReminderMarks(rTmpDoc);

        // a new one was created in CORE (OLE objects copied!)
        m_aDocShellRef = rTmpDoc.GetTmpDocShell();
        if( m_aDocShellRef.Is() )
            SwTransferable::InitOle( m_aDocShellRef );
        rTmpDoc.SetTmpDocShell( nullptr );

        if( m_pWrtShell->GetSelectedObjCount() )
            m_eBufferType = TransferBufferType::Drawing;
        else
        {
            m_eBufferType = TransferBufferType::Document;
            if (m_pWrtShell->IntelligentCut(nSelection, false) != SwWrtShell::NO_WORD)
                m_eBufferType = TransferBufferType::DocumentWord | m_eBufferType;
        }

        bool bDDELink = m_pWrtShell->IsSelection();
        if( nSelection & SelectionType::TableCell )
        {
            m_eBufferType = TransferBufferType::Table | m_eBufferType;
            bDDELink = m_pWrtShell->HasWholeTabSelection();

            m_pWrtShell->SetTableCopied(true);

            if ( bIsCut && (SelectionType::TableRow | SelectionType::TableCol) & nSelection )
                m_pWrtShell->SetTableInsertMode( (SelectionType::TableRow & nSelection) ? SwTable::SEARCH_ROW : SwTable::SEARCH_COL );
        }

#if HAVE_FEATURE_DESKTOP
        //When someone needs it, we 'OLE' him something
        AddFormat( SotClipboardFormatId::EMBED_SOURCE );
#endif

        //put RTF ahead of  the OLE's Metafile to have less loss
        if( !m_pWrtShell->GetSelectedObjCount() )
        {
            AddFormat( SotClipboardFormatId::RTF );
#if HAVE_FEATURE_DESKTOP
            AddFormat( SotClipboardFormatId::RICHTEXT );
            AddFormat( SotClipboardFormatId::HTML );
#endif
        }
        if( m_pWrtShell->IsSelection() )
            AddFormat( SotClipboardFormatId::STRING );

        if( nSelection & ( SelectionType::DrawObject | SelectionType::DbForm ))
        {
            AddFormat( SotClipboardFormatId::DRAWING );
            if ( nSelection & SelectionType::DrawObject )
            {
#if HAVE_FEATURE_DESKTOP
                AddFormat( SotClipboardFormatId::GDIMETAFILE );
                AddFormat( SotClipboardFormatId::BITMAP );
#endif
                AddFormat( SotClipboardFormatId::PNG );
            }
            m_eBufferType = static_cast<TransferBufferType>( TransferBufferType::Graphic | m_eBufferType );

            m_oClpGraphic.emplace();
            if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::GDIMETAFILE, *m_oClpGraphic ))
                m_pOrigGraphic = &*m_oClpGraphic;
            m_oClpBitmap.emplace();
            if( !m_pWrtShell->GetDrawObjGraphic( SotClipboardFormatId::BITMAP, *m_oClpBitmap ))
                m_pOrigGraphic = &*m_oClpBitmap;

            // is it a URL-Button ?
            OUString sURL;
            OUString sDesc;
            if( m_pWrtShell->GetURLFromButton( sURL, sDesc ) )
            {
                AddFormat( SotClipboardFormatId::STRING );
#if HAVE_FEATURE_DESKTOP
                AddFormat( SotClipboardFormatId::SOLK );
                AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
                AddFormat( SotClipboardFormatId::FILECONTENT );
                AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
#endif
                AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
                m_eBufferType = TransferBufferType::InetField | m_eBufferType;
                nRet = 1;
            }
        }

        // at Cut, DDE-Link doesn't make sense!!
        SwDocShell* pDShell;
        if( !bIsCut && bDDELink &&
            nullptr != ( pDShell = m_pWrtShell->GetDoc()->GetDocShell()) &&
            SfxObjectCreateMode::STANDARD == pDShell->GetCreateMode() )
        {
#if HAVE_FEATURE_DESKTOP
            AddFormat( SotClipboardFormatId::LINK );
#endif
            m_xDdeLink = new SwTransferDdeLink( *this, *m_pWrtShell );
        }

        //ObjectDescriptor was already filly from the old DocShell.
        //Now adjust it. Thus in GetData the first query can still
        //be answered with delayed rendering.
        m_aObjDesc.maSize = constOleSize100mm;

        PrepareOLE( m_aObjDesc );
#if HAVE_FEATURE_DESKTOP
        AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );
#endif
    }
    else
        nRet = 0;

    if( m_pWrtShell->IsFrameSelected() )
    {
        SfxItemSetFixed<RES_URL, RES_URL> aSet( m_pWrtShell->GetAttrPool() );
        m_pWrtShell->GetFlyFrameAttr( aSet );
        const SwFormatURL& rURL = aSet.Get( RES_URL );
        if( rURL.GetMap() )
        {
            m_pImageMap.reset( new ImageMap( *rURL.GetMap() ) );
            AddFormat( SotClipboardFormatId::SVIM );
        }
        else if( !rURL.GetURL().isEmpty() )
        {
            m_pTargetURL.reset(new INetImage( sGrfNm, rURL.GetURL(),
                                        rURL.GetTargetFrameName() ));
            AddFormat( SotClipboardFormatId::INET_IMAGE );
        }
    }

    return nRet;
}

int SwTransferable::Copy( bool bIsCut, bool bDeleteRedlines )
{
    if (m_pWrtShell->GetView().GetObjectShell()->isContentExtractionLocked())
        return 0;

    int nRet = PrepareForCopy( bIsCut, bDeleteRedlines );
    if ( nRet )
    {
        CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
    }

    if( !bIsCut ){
        collectUIInformation(u"COPY"_ustr, u"parameter"_ustr);
    }

    return nRet;
}

void SwTransferable::CalculateAndCopy()
{
    if(!m_pWrtShell)
        return;
    SwWait aWait( *m_pWrtShell->GetView().GetDocShell(), true );

    OUString aStr( m_pWrtShell->Calculate() );

    m_pClpDocFac.reset(new SwDocFac);
    SwDoc& rDoc = lcl_GetDoc(*m_pClpDocFac);
    m_pWrtShell->Copy(rDoc, &aStr);
    m_eBufferType = TransferBufferType::Document;
    AddFormat( SotClipboardFormatId::STRING );

    CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );
}

bool SwTransferable::CopyGlossary( SwTextBlocks& rGlossary, const OUString& rStr )
{
    if(!m_pWrtShell)
        return false;
    SwWait aWait( *m_pWrtShell->GetView().GetDocShell(), true );

    m_pClpDocFac.reset(new SwDocFac);
    SwDoc& rCDoc = lcl_GetDoc(*m_pClpDocFac);

    SwNodes& rNds = rCDoc.GetNodes();
    SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
    SwContentNode* pCNd = SwNodes::GoNext(&aNodeIdx); // go to 1st ContentNode
    SwPaM aPam( *pCNd );

    rCDoc.getIDocumentFieldsAccess().LockExpFields();   // never update fields - leave text as it is

    rCDoc.InsertGlossary( rGlossary, rStr, aPam );

    // a new one was created in CORE (OLE-Objects copied!)
    m_aDocShellRef = rCDoc.GetTmpDocShell();
    if( m_aDocShellRef.Is() )
        SwTransferable::InitOle( m_aDocShellRef );
    rCDoc.SetTmpDocShell( nullptr );

    m_eBufferType = TransferBufferType::Document;

    //When someone needs it, we 'OLE' her something.
    AddFormat( SotClipboardFormatId::EMBED_SOURCE );
    AddFormat( SotClipboardFormatId::RTF );
    AddFormat( SotClipboardFormatId::RICHTEXT );
    AddFormat( SotClipboardFormatId::HTML );
    AddFormat( SotClipboardFormatId::STRING );

    //ObjectDescriptor was already filled from the old DocShell.
    //Now adjust it. Thus in GetData the first query can still
    //be answered with delayed rendering.
    m_aObjDesc.maSize = constOleSize100mm;

    PrepareOLE( m_aObjDesc );
    AddFormat( SotClipboardFormatId::OBJECTDESCRIPTOR );

    CopyToClipboard( &m_pWrtShell->GetView().GetEditWin() );

    return true;
}

static uno::Reference < XTransferable > * lcl_getTransferPointer ( uno::Reference < XTransferable > &xRef )
{
    return &xRef;
}

SwPasteContext::SwPasteContext(SwWrtShell& rWrtShell)
    : m_rWrtShell(rWrtShell)
{
    remember();
}

void SwPasteContext::remember()
{
    if (m_rWrtShell.GetPasteListeners().getLength() == 0)
        return;

    SwPaM* pCursor = m_rWrtShell.GetCursor();
    if (!pCursor)
        return;

    // Set point to the previous node, so it is not moved.
    const SwNode& rNode = pCursor->GetPoint()->GetNode();
    m_oPaM.emplace(rNode, rNode, SwNodeOffset(0), SwNodeOffset(-1));
    m_nStartContent = pCursor->GetPoint()->GetContentIndex();
}

void SwPasteContext::forget() { m_oPaM.reset(); }

SwPasteContext::~SwPasteContext()
{
    try
    {
        if (m_rWrtShell.GetPasteListeners().getLength() == 0)
            return;

        beans::PropertyValue aPropertyValue;

        switch (m_rWrtShell.GetView().GetShellMode())
        {
            case ShellMode::Graphic:
            {
                SwFrameFormat* pFormat = m_rWrtShell.GetFlyFrameFormat();
                if (!pFormat)
                    return;

                aPropertyValue.Name = "TextGraphicObject";
                aPropertyValue.Value
                    <<= uno::Reference<text::XTextContent>(SwXTextGraphicObject::CreateXTextGraphicObject(pFormat->GetDoc(), pFormat));
                break;
            }

            default:
            {
                if (!m_oPaM)
                    return;

                SwPaM* pCursor = m_rWrtShell.GetCursor();
                if (!pCursor)
                    return;

                if (!pCursor->GetPoint()->GetNode().IsTextNode())
                    // Non-text was pasted.
                    return;

                // Update mark after paste.
                *m_oPaM->GetMark() = *pCursor->GetPoint();

                // Restore point.
                m_oPaM->GetPoint()->Adjust(SwNodeOffset(1));
                SwNode& rNode = m_oPaM->GetPointNode();
                if (!rNode.IsTextNode())
                    // Starting point is no longer text.
                    return;

                m_oPaM->GetPoint()->SetContent(m_nStartContent);

                aPropertyValue.Name = "TextRange";
                const rtl::Reference<SwXTextRange> xTextRange = SwXTextRange::CreateXTextRange(
                    m_oPaM->GetDoc(), *m_oPaM->GetPoint(), m_oPaM->GetMark());
                aPropertyValue.Value <<= uno::Reference<text::XTextRange>(xTextRange);
                break;
            }
        }

        if (aPropertyValue.Name.isEmpty())
            return;

        // Invoke the listeners.
        uno::Sequence<beans::PropertyValue> aEvent{ std::move(aPropertyValue) };
        m_rWrtShell.GetPasteListeners().notifyEach( &css::text::XPasteListener::notifyPasteEvent, aEvent );
    }
    catch (const uno::Exception& rException)
    {
        SAL_WARN("sw",
                 "SwPasteContext::~SwPasteContext: uncaught exception: " << rException.Message);
    }
}

bool SwTransferable::IsPaste( const SwWrtShell& rSh,
                              const TransferableDataHelper& rData )
{
    // Check the common case first: We can always paste our own data!
    // If _only_ the internal format can be pasted, this check will
    // yield 'true', while the one below would give a (wrong) result 'false'.

    bool bIsPaste = ( GetSwTransferable( rData ) != nullptr );

    // if it's not our own data, we need to have a closer look:
    if( ! bIsPaste )
    {
        // determine the proper paste action, and return true if we find one
        uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );

        SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
        sal_uInt16 nSourceOptions =
                    (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
                       SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
                       SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
                       SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
                                    ? EXCHG_IN_ACTION_COPY
                     : EXCHG_IN_ACTION_MOVE);

        SotClipboardFormatId nFormat;          // output param for GetExchangeAction
        sal_uInt8 nEventAction;    // output param for GetExchangeAction
        sal_uInt8 nAction = SotExchange::GetExchangeAction(
                                rData.GetDataFlavorExVector(),
                                nDestination,
                                nSourceOptions,             /* ?? */
                                EXCHG_IN_ACTION_DEFAULT,    /* ?? */
                                nFormat, nEventAction, SotClipboardFormatId::NONE,
                                lcl_getTransferPointer ( xTransferable ) );

        // if we find a suitable action, we can paste!
        bIsPaste = (EXCHG_INOUT_ACTION_NONE != nAction);
    }

    return bIsPaste;
}

void SwTransferable::SelectPasteFormat(const TransferableDataHelper& rData, sal_uInt8& nAction,
                                       SotClipboardFormatId& nFormat)
{
    if (nFormat != SotClipboardFormatId::RICHTEXT)
    {
        return;
    }

    if (!rData.HasFormat(SotClipboardFormatId::EMBED_SOURCE))
    {
        return;
    }

    if (!rData.HasFormat(SotClipboardFormatId::OBJECTDESCRIPTOR))
    {
        return;
    }

    TransferableObjectDescriptor aObjDesc;
    if (!rData.GetTransferableObjectDescriptor(SotClipboardFormatId::OBJECTDESCRIPTOR, aObjDesc))
    {
        return;
    }

    if (aObjDesc.maClassName != SvGlobalName(SO3_SW_CLASSID))
    {
        return;
    }

    // At this point we know that we paste from Writer to Writer and the clipboard has the content
    // in both RTF and ODF formats. Prefer ODF in this case.
    nAction = EXCHG_OUT_ACTION_INSERT_OLE;
    nFormat = SotClipboardFormatId::EMBED_SOURCE;
}

// get HTML indentation level by counting tabulator characters before the index
// (also index value -1 returns with 0)
static sal_Int32 lcl_getLevel(std::u16string_view sText, sal_Int32 nIdx)
{
    sal_Int32 nRet = 0;
    while ( nIdx-- > 0 && sText[nIdx] == '\t' )
    {
        nRet++;
    }
    return nRet;
}

bool SwTransferable::Paste(SwWrtShell& rSh, const TransferableDataHelper& rData, RndStdIds nAnchorType, bool bIgnoreComments, PasteTableType ePasteTable)
{
    SwPasteContext aPasteContext(rSh);

    sal_uInt8 nAction=0;
    SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
    SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
    SotExchangeActionFlags nActionFlags = SotExchangeActionFlags::NONE;
    bool bSingleCellTable = false;

    if( GetSwTransferable( rData ) )
    {
        nAction = EXCHG_OUT_ACTION_INSERT_PRIVATE;
    }
    else
    {
        sal_uInt16 nSourceOptions =
                    (( SotExchangeDest::DOC_TEXTFRAME == nDestination ||
                    SotExchangeDest::SWDOC_FREE_AREA == nDestination ||
                    SotExchangeDest::DOC_TEXTFRAME_WEB == nDestination ||
                    SotExchangeDest::SWDOC_FREE_AREA_WEB == nDestination )
                                    ? EXCHG_IN_ACTION_COPY
                                    : EXCHG_IN_ACTION_MOVE);
        uno::Reference<XTransferable> xTransferable( rData.GetXTransferable() );
        sal_uInt8 nEventAction;
        nAction = SotExchange::GetExchangeAction(
                                    rData.GetDataFlavorExVector(),
                                    nDestination,
                                    nSourceOptions,             /* ?? */
                                    EXCHG_IN_ACTION_DEFAULT,    /* ?? */
                                    nFormat, nEventAction, SotClipboardFormatId::NONE,
                                    lcl_getTransferPointer ( xTransferable ),
                                    &nActionFlags );
    }

    // when HTML is just an image don't generate new section
    if (rData.HasFormat(SotClipboardFormatId::HTML_SIMPLE) && rData.HasFormat(SotClipboardFormatId::HTML_NO_COMMENT)
        && rData.HasFormat(SotClipboardFormatId::BITMAP) && nFormat == SotClipboardFormatId::FILE_LIST)
        nFormat = SotClipboardFormatId::BITMAP;

    // tdf#37223 avoid non-native insertion of Calc worksheets in the following cases:
    // content of 1-cell worksheets are inserted as simple text using RTF format,
    // bigger worksheets within native (Writer) table cells are inserted as native tables,
    // ie. cell by cell instead of embedding the worksheet in a single cell of the Writer table
    if ( EXCHG_IN_ACTION_COPY == nAction && ( rData.HasFormat( SotClipboardFormatId::SYLK ) ||
                  rData.HasFormat( SotClipboardFormatId::SYLK_BIGCAPS ) ) )
    {
        // is it a 1-cell worksheet?
        OUString aExpand;
        if( rData.GetString( SotClipboardFormatId::STRING, aExpand ))
        {
            const sal_Int32 nNewlines{comphelper::string::getTokenCount(aExpand, '\n')};
            const sal_Int32 nRows = nNewlines ? nNewlines-1 : 0;
            if ( nRows == 1 )
            {
                const sal_Int32 nCols = comphelper::string::getTokenCount(o3tl::getToken(aExpand, 0, '\n'), '\t');
                if (nCols == 1)
                    bSingleCellTable = true;
            }
        }

        // convert the worksheet to a temporary native table using HTML format, and copy that into the original native table
        if (!bSingleCellTable && rData.HasFormat( SotClipboardFormatId::HTML ) &&
                        SwDoc::IsInTable(rSh.GetCursor()->GetPointNode()) != nullptr && rSh.DoesUndo())
        {
            SfxDispatcher* pDispatch = rSh.GetView().GetViewFrame().GetDispatcher();
            sal_uInt32 nLevel = 0;

            // within Writer table cells, inserting worksheets using HTML format results only plain text, not a native table,
            // so remove all outer nested tables temporary to get a working insertion point
            // (RTF format has no such problem, but that inserts the hidden rows of the original Calc worksheet, too)

            // For this, switch off change tracking temporarily, if needed
            RedlineFlags eOld = rSh.GetDoc()->getIDocumentRedlineAccess().GetRedlineFlags();
            if ( eOld & RedlineFlags::On )
                rSh.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eOld & ~RedlineFlags::On );

            UIName sPreviousTableName;
            do
            {
                // tdf#152245 add a limit to the loop, if it's not possible to delete the table
                const SwTableNode* pNode = rSh.GetCursor()->GetPointNode().FindTableNode();
                const UIName sTableName = pNode->GetTable().GetFrameFormat()->GetName();
                if ( sTableName == sPreviousTableName )
                    break;
                sPreviousTableName = sTableName;
                // insert a random character to redo the place of the insertion at the end
                pDispatch->Execute(FN_INSERT_NNBSP, SfxCallMode::SYNCHRON);
                pDispatch->Execute(FN_TABLE_DELETE_TABLE, SfxCallMode::SYNCHRON);
                nLevel++;
            } while (SwDoc::IsInTable(rSh.GetCursor()->GetPointNode()) != nullptr);

            // restore change tracking settings
            if ( eOld & RedlineFlags::On )
                rSh.GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags( eOld );

            if ( SwTransferable::PasteData( rData, rSh, EXCHG_OUT_ACTION_INSERT_STRING, nActionFlags, SotClipboardFormatId::HTML,
                                        nDestination, falsefalse, nullptr, 0, false, nAnchorType, bIgnoreComments, &aPasteContext, ePasteTable) )
            {
                bool bFoundTemporaryTable = false;
                pDispatch->Execute(FN_LINE_UP, SfxCallMode::SYNCHRON);
                if (SwDoc::IsInTable(rSh.GetCursor()->GetPointNode()) != nullptr)
                {
                    bFoundTemporaryTable = true;
                    pDispatch->Execute(FN_TABLE_SELECT_ALL, SfxCallMode::SYNCHRON);
                    pDispatch->Execute(SID_COPY, SfxCallMode::SYNCHRON);
                }
                for(sal_uInt32 a = 0; a < 1 + (nLevel * 2); a++)
                    pDispatch->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
                // clipboard content hasn't changed (limit potential infinite
                // recursion with the same non-native table, as was in tdf#138688)
                if (!bFoundTemporaryTable)
                    return false;
                if (ePasteTable == PasteTableType::PASTE_TABLE)
                    pDispatch->Execute(FN_PASTE_NESTED_TABLE, SfxCallMode::SYNCHRON);
                else if (ePasteTable == PasteTableType::PASTE_ROW)
                    pDispatch->Execute(FN_TABLE_PASTE_ROW_BEFORE, SfxCallMode::SYNCHRON);
                else if (ePasteTable == PasteTableType::PASTE_COLUMN)
                    pDispatch->Execute(FN_TABLE_PASTE_COL_BEFORE, SfxCallMode::SYNCHRON);
                else
                    pDispatch->Execute(SID_PASTE, SfxCallMode::SYNCHRON);
                return true;
            } else {
                for(sal_uInt32 a = 0; a < (nLevel * 2); a++)
                    pDispatch->Execute(SID_UNDO, SfxCallMode::SYNCHRON);
            }
        }
    }
    // insert clipboard content as new table rows/columns before the actual row/column instead of overwriting it
    else if ( (rSh.GetTableInsertMode() != SwTable::SEARCH_NONE || ePasteTable == PasteTableType::PASTE_ROW || ePasteTable == PasteTableType::PASTE_COLUMN) &&
        rData.HasFormat( SotClipboardFormatId::HTML ) &&
        SwDoc::IsInTable(rSh.GetCursor()->GetPointNode()) != nullptr )
    {
        OUString aExpand;
        sal_Int32 nIdx;
        bool bRowMode = rSh.GetTableInsertMode() == SwTable::SEARCH_ROW || ePasteTable == PasteTableType::PASTE_ROW;
        if( rData.GetString( SotClipboardFormatId::HTML, aExpand ) && (nIdx = aExpand.indexOf(")) > -1 )
        {
            // calculate table row/column count by analysing indentation of the HTML table extract

            // calculate indentation level of <table>, which is the base of the next calculations
            // (tdf#148791 table alignment can enlarge it using first level <center>, <div> or <dl>)
            sal_Int32 nTableLevel = lcl_getLevel(aExpand, nIdx);
            // table rows repeated heading use extra indentation, too:
            // <thead> is always used here, and the first table with <thead> is not nested,
            // if its indentation level is greater only by 1, than indentation level of the table
            bool bShifted = lcl_getLevel(aExpand, aExpand.indexOf(")) == nTableLevel + 1;
            // calculate count of selected rows or columns
            sal_Int32 nSelectedRowsOrCols = 0;
            const OUString sSearchRowOrCol = bRowMode ? u"
Messung V0.5
C=95 H=96 G=95

¤ Dauer der Verarbeitung: 0.21 Sekunden  (vorverarbeitet)  ¤

*© 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.