tdf#117228: crash in SfxItemSet::GetItemState...

(unsigned short, bool, SfxPoolItem const**) when pasting comment of closed document

Re-work commit 1b7a8277aa3e9f73ccdf15e933a1ee3b42849a44.

In the tiled rendering case, each view has its own clipboard,
but  not in desktop version which it has a shared clipboard each view.

Change-Id: I57b1ab81e4c141829dbad899330e5c22204c384a
Reviewed-on: https://gerrit.libreoffice.org/53922
Tested-by: Jenkins <ci@libreoffice.org>
Reviewed-by: Eike Rathke <erack@redhat.com>
diff --git a/sc/inc/scmod.hxx b/sc/inc/scmod.hxx
index 253c5cb..76e5124 100644
--- a/sc/inc/scmod.hxx
+++ b/sc/inc/scmod.hxx
@@ -29,6 +29,8 @@
#include "shellids.hxx"
#include <unotools/options.hxx>

#include <com/sun/star/datatransfer/XTransferable2.hpp>

#include <algorithm>
#include <vector>
#include <map>
@@ -80,7 +82,8 @@ class ScModule: public SfxModule, public SfxListener, public utl::ConfigurationL
    ScDragData*         m_pDragData;
    ScSelectionTransferObj* m_pSelTransfer;
    ScMessagePool*      m_pMessagePool;
    // there is no global InputHandler anymore, each View has its own
    css::uno::Reference<css::datatransfer::XTransferable2> m_xClipData; // Only used by Vba helper functions
    // there is no global InputHandler anymore, each View has it's own
    ScInputHandler*     m_pRefInputHandler;
    ScViewCfg*          m_pViewCfg;
    ScDocCfg*           m_pDocCfg;
@@ -172,6 +175,11 @@ public:
    void                SetPrintOptions ( const ScPrintOptions& rOpt );
    void                InsertEntryToLRUList(sal_uInt16 nFIndex);

    SC_DLLPUBLIC css::uno::Reference<css::datatransfer::XTransferable2>
        GetClipData() { return m_xClipData; }
    SC_DLLPUBLIC void SetClipData(
        const css::uno::Reference<css::datatransfer::XTransferable2>& xTransferable) { m_xClipData = xTransferable; }

    static void         GetSpellSettings( LanguageType& rDefLang, LanguageType& rCjkLang, LanguageType& rCtlLang,
                                          bool& rAutoSpell );
    static void         SetAutoSpellProperty( bool bSet );
diff --git a/sc/qa/unit/screenshots/screenshots.cxx b/sc/qa/unit/screenshots/screenshots.cxx
index 59a10ef..9eb753d 100644
--- a/sc/qa/unit/screenshots/screenshots.cxx
+++ b/sc/qa/unit/screenshots/screenshots.cxx
@@ -20,6 +20,7 @@
#include <osl/file.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/lokhelper.hxx>
#include <svl/srchitem.hxx>
#include <svx/numinf.hxx>
#include <vcl/pngwrite.hxx>
@@ -72,9 +73,11 @@ public:
    ScScreenshotTest();

    void testOpeningModalDialogs();
    void testMultiViewCopyPaste();

    CPPUNIT_TEST_SUITE(ScScreenshotTest);
    CPPUNIT_TEST(testOpeningModalDialogs);
    CPPUNIT_TEST(testMultiViewCopyPaste);
    CPPUNIT_TEST_SUITE_END();
};

@@ -286,6 +289,53 @@ void ScScreenshotTest::testOpeningModalDialogs()
    mxComponent.clear();
}

void ScScreenshotTest::testMultiViewCopyPaste()
{
    initialize();

    ScDocument& rDoc = mxDocSh->GetDocument();

    rDoc.SetString(ScAddress(0, 0, 0), "TestCopy1");
    rDoc.SetString(ScAddress(1, 0, 0), "TestCopy2");

    // view #1
    ScTabViewShell* pView1 = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
    CPPUNIT_ASSERT(pView1);

    // view #2
    SfxLokHelper::createView();
    ScTabViewShell* pView2 = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current());
    CPPUNIT_ASSERT(pView1 != pView2);
    {
        std::unique_ptr<SfxPoolItem> xItem1;
        std::unique_ptr<SfxPoolItem> xItem2;
        CPPUNIT_ASSERT(SfxItemState::DISABLED != pView1->GetViewFrame()->GetBindings().QueryState(SID_PASTE, xItem1));
        CPPUNIT_ASSERT(SfxItemState::DISABLED != pView2->GetViewFrame()->GetBindings().QueryState(SID_PASTE, xItem2));
    }

    // copy text view 1
    pView1->SetCursor(0, 0);
    pView1->GetViewFrame()->GetBindings().Execute(SID_COPY);

    // copy text view 2
    pView2->SetCursor(1, 0);
    pView2->GetViewFrame()->GetBindings().Execute(SID_COPY);

     // paste text view 1
    pView1->SetCursor(0, 1);
    pView1->GetViewFrame()->GetBindings().Execute(SID_PASTE);

    // paste text view 2
    pView2->SetCursor(1, 1);
    pView2->GetViewFrame()->GetBindings().Execute(SID_PASTE);

    CPPUNIT_ASSERT_EQUAL(OUString("TestCopy2"), rDoc.GetString(ScAddress(0, 1, 0)));
    CPPUNIT_ASSERT_EQUAL(OUString("TestCopy2"), rDoc.GetString(ScAddress(1, 1, 0)));

    mxComponent->dispose();
    mxComponent.clear();
}

CPPUNIT_TEST_SUITE_REGISTRATION(ScScreenshotTest);

CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 7bbf5cc..ba48bff 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -376,18 +376,6 @@ ScDocument::~ScDocument()
        pRefreshTimerControl.reset();
    }

    if (IsClipboardSource())
    {
        // Notes copied to the clipboard have a raw SdrCaptionObj pointer
        // copied from this document, forget it as it references this
        // document's drawing layer pages and what not, which otherwise when
        // pasting to another document after this document was destructed would
        // attempt to access non-existing data. Preserve the text data though.
        ScDocument* pClipDoc = ScModule::GetClipDoc();
        if (pClipDoc)
            pClipDoc->ClosingClipboardSource();
    }

    mxFormulaParserPool.reset();
    // Destroy the external ref mgr instance here because it has a timer
    // which needs to be stopped before the app closes.
diff --git a/sc/source/ui/app/drwtrans.cxx b/sc/source/ui/app/drwtrans.cxx
index 0f6d0d6..8d00e3f 100644
--- a/sc/source/ui/app/drwtrans.cxx
+++ b/sc/source/ui/app/drwtrans.cxx
@@ -236,16 +236,18 @@ ScDrawTransferObj::~ScDrawTransferObj()
    m_pDragSourceView.reset();
}

ScDrawTransferObj* ScDrawTransferObj::GetOwnClipboard( vcl::Window* pWin )
ScDrawTransferObj* ScDrawTransferObj::GetOwnClipboard(const uno::Reference<datatransfer::XTransferable2>& xTransferable)
{
    ScDrawTransferObj* pObj = nullptr;
    TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
    uno::Reference<XUnoTunnel> xTunnel( aDataHelper.GetTransferable(), uno::UNO_QUERY );
    if ( xTunnel.is() )
    if (xTransferable.is())
    {
        sal_Int64 nHandle = xTunnel->getSomething( getUnoTunnelId() );
        if ( nHandle )
            pObj = dynamic_cast<ScDrawTransferObj*>(reinterpret_cast<TransferableHelper*>( static_cast<sal_IntPtr>(nHandle) ));
        uno::Reference<XUnoTunnel> xTunnel( xTransferable, uno::UNO_QUERY );
        if ( xTunnel.is() )
        {
            sal_Int64 nHandle = xTunnel->getSomething( getUnoTunnelId() );
            if ( nHandle )
                pObj = dynamic_cast<ScDrawTransferObj*>(reinterpret_cast<TransferableHelper*>( static_cast<sal_IntPtr>(nHandle) ));
        }
    }

    return pObj;
diff --git a/sc/source/ui/app/scmod.cxx b/sc/source/ui/app/scmod.cxx
index dd096a5..fc81453 100644
--- a/sc/source/ui/app/scmod.cxx
+++ b/sc/source/ui/app/scmod.cxx
@@ -70,6 +70,7 @@
#include <com/sun/star/i18n/ScriptType.hpp>
#include <com/sun/star/linguistic2/XThesaurus.hpp>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/datatransfer/XTransferable2.hpp>

#include <scmod.hxx>
#include <global.hxx>
@@ -661,11 +662,28 @@ void ScModule::SetDragJump(
ScDocument* ScModule::GetClipDoc()
{
    // called from document
    vcl::Window* pWin = nullptr;
    if( ScTabViewShell* pViewShell = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() ))
        pWin = pViewShell->GetViewData().GetActiveWin();
    ScTabViewShell* pViewShell = nullptr;
    const ScTransferObj* pObj = nullptr;

    ScTransferObj* pObj = ScTransferObj::GetOwnClipboard( pWin );
    if ((pViewShell = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current())))
        pObj = ScTransferObj::GetOwnClipboard(pViewShell->GetClipData());
    else if ((pViewShell = dynamic_cast<ScTabViewShell*>(SfxViewShell::GetFirst())))
        pObj = ScTransferObj::GetOwnClipboard(pViewShell->GetClipData());
    else
    {
        css::uno::Reference<css::datatransfer::clipboard::XClipboard> xClipboard;

        if (SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst())
            xClipboard = pViewFrame->GetWindow().GetClipboard();

        if (xClipboard.is())
        {
            css::uno::Reference<css::datatransfer::XTransferable2> xTransferable(
                xClipboard->getContents(), css::uno::UNO_QUERY);
            pObj = ScTransferObj::GetOwnClipboard(xTransferable);
        }
    }

    if (pObj)
    {
        ScDocument* pDoc = pObj->GetDocument();
diff --git a/sc/source/ui/app/transobj.cxx b/sc/source/ui/app/transobj.cxx
index 37d37b9..febb079 100644
--- a/sc/source/ui/app/transobj.cxx
+++ b/sc/source/ui/app/transobj.cxx
@@ -24,6 +24,7 @@
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
#include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>

#include <unotools/tempfile.hxx>
#include <unotools/ucbstreamhelper.hxx>
@@ -33,8 +34,10 @@
#include <sot/storage.hxx>
#include <vcl/svapp.hxx>
#include <vcl/virdev.hxx>
#include <vcl/wrkwin.hxx>
#include <sfx2/app.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/viewfrm.hxx>

#include <transobj.hxx>
#include <patattr.hxx>
@@ -198,18 +201,11 @@ ScTransferObj::~ScTransferObj()

}

ScTransferObj* ScTransferObj::GetOwnClipboard( vcl::Window* pUIWin )
ScTransferObj* ScTransferObj::GetOwnClipboard(const uno::Reference<datatransfer::XTransferable2>& xTransferable)
{
    ScTransferObj* pObj = nullptr;
    uno::Reference<XTransferable> xTransferable;
    uno::Reference<datatransfer::clipboard::XClipboard> xClipboard;

    if( pUIWin )
        xClipboard = pUIWin->GetClipboard();

    if( xClipboard.is() )
    if (xTransferable.is())
    {
        xTransferable = xClipboard->getContents();
        uno::Reference<XUnoTunnel> xTunnel( xTransferable, uno::UNO_QUERY );
        if ( xTunnel.is() )
        {
diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx
index e83aad3..b814ddc 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -1018,6 +1018,20 @@ void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
        //  RegisterNewTargetNames doesn't exist any longer
        SfxGetpApp()->Broadcast(SfxHint( SfxHintId::ScDocNameChanged )); // Navigator
    }
    else if (rHint.GetId() == SfxHintId::Deinitializing)
    {
        if (aDocument.IsClipboardSource())
        {
            // Notes copied to the clipboard have a raw SdrCaptionObj pointer
            // copied from this document, forget it as it references this
            // document's drawing layer pages and what not, which otherwise when
            // pasting to another document after this document was destructed would
            // attempt to access non-existing data. Preserve the text data though.
            ScDocument* pClipDoc = ScModule::GetClipDoc();
            if (pClipDoc)
                pClipDoc->ClosingClipboardSource();
        }
    }
}

// Load contents for organizer
diff --git a/sc/source/ui/inc/drwtrans.hxx b/sc/source/ui/inc/drwtrans.hxx
index 7550575..e403e96 100644
--- a/sc/source/ui/inc/drwtrans.hxx
+++ b/sc/source/ui/inc/drwtrans.hxx
@@ -79,7 +79,7 @@ public:
                                        const css::datatransfer::DataFlavor& rFlavor ) override;
    virtual void        DragFinished( sal_Int8 nDropAction ) override;

    SdrModel*           GetModel()  { return m_pModel.get(); }
    SdrModel*           GetModel() const { return m_pModel.get(); }

    void                SetDrawPersist( const SfxObjectShellRef& rRef );
    void                SetDragSource( const ScDrawView* pView );
@@ -92,7 +92,7 @@ public:
    SdrView*            GetDragSourceView()             { return m_pDragSourceView.get(); }
    ScDragSrc           GetDragSourceFlags() const      { return m_nDragSourceFlags; }

    static ScDrawTransferObj* GetOwnClipboard( vcl::Window* );
    static ScDrawTransferObj* GetOwnClipboard(const css::uno::Reference<css::datatransfer::XTransferable2>&);

    virtual sal_Int64 SAL_CALL getSomething( const css::uno::Sequence< sal_Int8 >& rId ) override;
    static const css::uno::Sequence< sal_Int8 >& getUnoTunnelId();
diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx
index 8a89712..0c6bb6b 100644
--- a/sc/source/ui/inc/tabvwsh.hxx
+++ b/sc/source/ui/inc/tabvwsh.hxx
@@ -167,6 +167,9 @@ private:
    OUString   maName;
    OUString   maScope;

    // ClipData
    css::uno::Reference<css::datatransfer::XTransferable2>   m_xClipData;

private:
    void    Construct( TriState nForceDesignMode );

@@ -391,6 +394,9 @@ public:
    static void notifyAllViewsHeaderInvalidation(bool Columns, SCTAB nCurrentTabIndex);
    static bool isAnyEditViewInRange(bool bColumns, SCCOLROW nStart, SCCOLROW nEnd);
    css::uno::Reference<css::drawing::XShapes> getSelectedXShapes();

    css::uno::Reference<css::datatransfer::XTransferable2> GetClipData() { return m_xClipData; };
    void SetClipData(const css::uno::Reference<css::datatransfer::XTransferable2>& xTransferable) { m_xClipData = xTransferable; }
};

#endif
diff --git a/sc/source/ui/inc/transobj.hxx b/sc/source/ui/inc/transobj.hxx
index 11f218a..ced505c 100644
--- a/sc/source/ui/inc/transobj.hxx
+++ b/sc/source/ui/inc/transobj.hxx
@@ -78,7 +78,7 @@ public:
                                        const css::datatransfer::DataFlavor& rFlavor ) override;
    virtual void        DragFinished( sal_Int8 nDropAction ) override;

    ScDocument*         GetDocument()           { return m_pDoc; }        // owned by ScTransferObj
    ScDocument*         GetDocument() const     { return m_pDoc; }        // owned by ScTransferObj
    const ScRange&      GetRange() const        { return m_aBlock; }
    SCROW               GetNonFilteredRows() const { return m_nNonFiltered; }
    SCCOL               GetDragHandleX() const  { return m_nDragHandleX; }
@@ -103,7 +103,7 @@ public:
    void                SetDragWasInternal();
    SC_DLLPUBLIC void   SetUseInApi( bool bSet );

    static SC_DLLPUBLIC ScTransferObj* GetOwnClipboard( vcl::Window* pUIWin );
    static  SC_DLLPUBLIC ScTransferObj* GetOwnClipboard(const css::uno::Reference<css::datatransfer::XTransferable2>&);

    static SfxObjectShell*  SetDrawClipDoc( bool bAnyOle );     // update ScGlobal::xDrawClipDocShellRef
    virtual sal_Int64 SAL_CALL getSomething( const com::sun::star::uno::Sequence< sal_Int8 >& rId ) override;
diff --git a/sc/source/ui/undo/undoblk.cxx b/sc/source/ui/undo/undoblk.cxx
index 20632b5..107fe23 100644
--- a/sc/source/ui/undo/undoblk.cxx
+++ b/sc/source/ui/undo/undoblk.cxx
@@ -1132,7 +1132,7 @@ void ScUndoPaste::Repeat(SfxRepeatTarget& rTarget)
    {
        ScTabViewShell* pViewSh = static_cast<ScTabViewTarget&>(rTarget).GetViewShell();
        // keep a reference in case the clipboard is changed during PasteFromClip
        rtl::Reference<ScTransferObj> pOwnClip = ScTransferObj::GetOwnClipboard( pViewSh->GetActiveWin() );
        const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(pViewSh->GetClipData());
        if (pOwnClip)
        {
            pViewSh->PasteFromClip( nFlags, pOwnClip->GetDocument(),
diff --git a/sc/source/ui/vba/excelvbahelper.cxx b/sc/source/ui/vba/excelvbahelper.cxx
index 8dcb6e9..e4cb64b 100644
--- a/sc/source/ui/vba/excelvbahelper.cxx
+++ b/sc/source/ui/vba/excelvbahelper.cxx
@@ -170,9 +170,13 @@ implnCopy( const uno::Reference< frame::XModel>& xModel )
        pViewShell->CopyToClip(nullptr,false,false,true);

        // mark the copied transfer object so it is used in ScVbaRange::Insert
        ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( pViewShell->GetViewData().GetActiveWin() );
        uno::Reference<datatransfer::XTransferable2> xTransferable(pViewShell->GetClipData());
        ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard(xTransferable);
        if (pClipObj)
        {
            pClipObj->SetUseInApi( true );
            SC_MOD()->SetClipData(xTransferable);
        }
    }
}

@@ -185,9 +189,13 @@ implnCut( const uno::Reference< frame::XModel>& xModel )
        pViewShell->CutToClip();

        // mark the copied transfer object so it is used in ScVbaRange::Insert
        ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( pViewShell->GetViewData().GetActiveWin() );
        uno::Reference<datatransfer::XTransferable2> xTransferable(pViewShell->GetClipData());
        ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard(xTransferable);
        if (pClipObj)
        {
            pClipObj->SetUseInApi( true );
            SC_MOD()->SetClipData(xTransferable);
        }
    }
}

@@ -202,7 +210,7 @@ void implnPasteSpecial( const uno::Reference< frame::XModel>& xModel, InsertDele
        vcl::Window* pWin = rView.GetActiveWin();
        if (pWin)
        {
            ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
            const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(SC_MOD()->GetClipData());
            ScDocument* pDoc = nullptr;
            if ( pOwnClip )
                pDoc = pOwnClip->GetDocument();
diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx
index 869f40a..2ad45a3 100644
--- a/sc/source/ui/vba/vbarange.cxx
+++ b/sc/source/ui/vba/vbarange.cxx
@@ -4681,11 +4681,7 @@ ScVbaRange::Insert( const uno::Any& Shift, const uno::Any& /*CopyOrigin*/ )

    // Paste from clipboard only if the clipboard content was copied via VBA, and not already pasted via VBA again.
    // "Insert" behavior should not depend on random clipboard content previously copied by the user.
    vcl::Window* pWin = nullptr;
    if(ScTabViewShell* pViewShell = excel::getBestViewShell( getUnoModel() ))
        pWin = pViewShell->GetViewData().GetActiveWin();

    ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard( pWin );
    const ScTransferObj* pClipObj = ScTransferObj::GetOwnClipboard(SC_MOD()->GetClipData());
    if ( pClipObj && pClipObj->GetUseInApi() )
    {
        // After the insert ( this range ) actually has moved
diff --git a/sc/source/ui/view/cellsh.cxx b/sc/source/ui/view/cellsh.cxx
index 9e54600..c247fdbf 100644
--- a/sc/source/ui/view/cellsh.cxx
+++ b/sc/source/ui/view/cellsh.cxx
@@ -447,7 +447,7 @@ static bool lcl_TestFormat( SvxClipboardFormatItem& rFormats, const Transferable
void ScCellShell::GetPossibleClipboardFormats( SvxClipboardFormatItem& rFormats )
{
    vcl::Window* pWin = GetViewData()->GetActiveWin();
    bool bDraw = ScDrawTransferObj::GetOwnClipboard( pWin ) != nullptr;
    bool bDraw = ScDrawTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) != nullptr;

    TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );

@@ -478,10 +478,10 @@ void ScCellShell::GetPossibleClipboardFormats( SvxClipboardFormatItem& rFormats 

//  insert, insert contents

static bool lcl_IsCellPastePossible( const TransferableDataHelper& rData, vcl::Window* pWin )
static bool lcl_IsCellPastePossible( const TransferableDataHelper& rData, ScTabViewShell* pViewShell )
{
    bool bPossible = false;
    if ( ScTransferObj::GetOwnClipboard( pWin ) || ScDrawTransferObj::GetOwnClipboard( pWin ) )
    if ( ScTransferObj::GetOwnClipboard(pViewShell->GetClipData()) || ScDrawTransferObj::GetOwnClipboard(pViewShell->GetClipData()) )
        bPossible = true;
    else
    {
@@ -520,7 +520,19 @@ bool ScCellShell::HasClipboardFormat( SotClipboardFormatId nFormatId )

IMPL_LINK( ScCellShell, ClipboardChanged, TransferableDataHelper*, pDataHelper, void )
{
    bPastePossible = lcl_IsCellPastePossible( *pDataHelper, GetViewData()->GetActiveWin() );
    ScTabViewShell* pViewShell = GetViewData()->GetViewShell();
    css::uno::Reference<css::datatransfer::XTransferable2> xOldTransfer(pViewShell->GetClipData());
    css::uno::Reference<css::datatransfer::XTransferable2> xNewTransfer(pDataHelper->GetXTransferable(), css::uno::UNO_QUERY);

    if ( xNewTransfer.get() != xOldTransfer.get() )
    {
        if ( ScTransferObj::GetOwnClipboard(xNewTransfer) || ScDrawTransferObj::GetOwnClipboard(xNewTransfer) )
            pViewShell->SetClipData(xNewTransfer);
        else
            pViewShell->SetClipData(css::uno::Reference<css::datatransfer::XTransferable2>());
    }

    bPastePossible = lcl_IsCellPastePossible( *pDataHelper, pViewShell );

    SfxBindings& rBindings = GetViewData()->GetBindings();
    rBindings.Invalidate( SID_PASTE );
@@ -555,7 +567,7 @@ bool checkDestRanges(ScViewData& rViewData)
    if (!pWin)
        return false;

    ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(pWin);
    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(rViewData.GetViewShell()->GetClipData());
    if (!pOwnClip)
        // If it's not a Calc document, we won't be picky.
        return true;
@@ -594,7 +606,7 @@ void ScCellShell::GetClipState( SfxItemSet& rSet )

        // get initial state
        TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
        bPastePossible = lcl_IsCellPastePossible( aDataHelper, pWin );
        bPastePossible = lcl_IsCellPastePossible( aDataHelper, GetViewData()->GetViewShell() );
    }

    bool bDisable = !bPastePossible;
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index 896465c..feb677e 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -1312,9 +1312,8 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )

                if ( nFormat != SotClipboardFormatId::NONE )
                {
                    vcl::Window* pWin = GetViewData()->GetActiveWin();
                    bool bCells = ( ScTransferObj::GetOwnClipboard( pWin ) != nullptr );
                    bool bDraw = ( ScDrawTransferObj::GetOwnClipboard( pWin ) != nullptr );
                    bool bCells = ( ScTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) != nullptr );
                    bool bDraw = ( ScDrawTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) != nullptr );
                    bool bOle = ( nFormat == SotClipboardFormatId::EMBED_SOURCE );

                    if ( bCells && bOle )
@@ -1338,11 +1337,10 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
                ScPasteFunc nFunction = ScPasteFunc::NONE;
                InsCellCmd eMoveMode = INS_NONE;

                vcl::Window* pWin = GetViewData()->GetActiveWin();
                ScDocument* pDoc = GetViewData()->GetDocument();
                bool bOtherDoc = !pDoc->IsClipboardSource();
                // keep a reference in case the clipboard is changed during dialog or PasteFromClip
                rtl::Reference<ScTransferObj> pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
                const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData());
                if ( pOwnClip )
                {
                    bool bSkipEmpty = false;
@@ -1497,8 +1495,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
        case SID_PASTE_ONLY_TEXT:
        case SID_PASTE_ONLY_FORMULA:
        {
            vcl::Window* pWin = GetViewData()->GetActiveWin();
            if ( ScTransferObj::GetOwnClipboard( pWin ) )  // own cell data
            if ( ScTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) )  // own cell data
            {
                rReq.SetSlot( FID_INS_CELL_CONTENTS );
                OUString aFlags;
@@ -1533,7 +1530,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
                    bool bRet=true;
                    {
                        WaitObject aWait( GetViewData()->GetDialogParent() );
                        bool bDraw = ( ScDrawTransferObj::GetOwnClipboard( pWin ) != nullptr );
                        bool bDraw = ( ScDrawTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) != nullptr );
                        if ( bDraw && nFormat == SotClipboardFormatId::EMBED_SOURCE )
                            pTabViewShell->PasteDraw();
                        else
@@ -1552,7 +1549,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )

                if ( !pItem )
                {
                    if ( ScTransferObj::GetOwnClipboard( pWin ) )  // own cell data
                    if ( ScTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) )  // own cell data
                    {
                        rReq.SetSlot( FID_INS_CELL_CONTENTS );
                        ExecuteSlot( rReq, GetInterface() );
@@ -1560,7 +1557,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq )
                    }
                    else                                    // draw objects or external data
                    {
                        bool bDraw = ( ScDrawTransferObj::GetOwnClipboard( pWin ) != nullptr );
                        bool bDraw = ( ScDrawTransferObj::GetOwnClipboard(GetViewData()->GetViewShell()->GetClipData()) != nullptr );

                        SvxClipboardFormatItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS );
                        GetPossibleClipboardFormats( aFormats );
diff --git a/sc/source/ui/view/cliputil.cxx b/sc/source/ui/view/cliputil.cxx
index f3cd331..254352d 100644
--- a/sc/source/ui/view/cliputil.cxx
+++ b/sc/source/ui/view/cliputil.cxx
@@ -46,8 +46,7 @@ bool lcl_checkClassification(ScDocument* pSourceDoc, const ScDocument* pDestinat

void ScClipUtil::PasteFromClipboard( ScViewData* pViewData, ScTabViewShell* pTabViewShell, bool bShowDialog )
{
    vcl::Window* pWin = pViewData->GetActiveWin();
    ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(pTabViewShell->GetClipData());
    ScDocument* pThisDoc = pViewData->GetDocument();
    ScDPObject* pDPObj = pThisDoc->GetDPAtCursor( pViewData->GetCurX(),
                         pViewData->GetCurY(), pViewData->GetTabNo() );
diff --git a/sc/source/ui/view/drawvie4.cxx b/sc/source/ui/view/drawvie4.cxx
index 83fcb40..2a6aec9 100644
--- a/sc/source/ui/view/drawvie4.cxx
+++ b/sc/source/ui/view/drawvie4.cxx
@@ -42,6 +42,7 @@
#include <chartarr.hxx>
#include <gridwin.hxx>
#include <userdat.hxx>
#include <tabvwsh.hxx>

#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
#include <com/sun/star/embed/Aspects.hpp>
@@ -370,13 +371,15 @@ void ScDrawView::DoCopy()
    aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
    // maSize is set in ScDrawTransferObj ctor

    rtl::Reference<ScDrawTransferObj> pTransferObj = new ScDrawTransferObj( pModel, pDocSh, aObjDesc );
    ScDrawTransferObj* pTransferObj = new ScDrawTransferObj( pModel, pDocSh, aObjDesc );
    uno::Reference<css::datatransfer::XTransferable2> xTransferObj = pTransferObj;

    if ( ScGlobal::xDrawClipDocShellRef.is() )
    {
        pTransferObj->SetDrawPersist( ScGlobal::xDrawClipDocShellRef.get() );    // keep persist for ole objects alive
    }

    pViewData->GetViewShell()->SetClipData(xTransferObj); // internal clipboard
    pTransferObj->CopyToClipboard( pViewData->GetActiveWin() );     // system clipboard
}

diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx
index 64f8012..96a3f7e 100644
--- a/sc/source/ui/view/gridwin.cxx
+++ b/sc/source/ui/view/gridwin.cxx
@@ -5738,7 +5738,7 @@ void ScGridWindow::UpdateCopySourceOverlay()
    rtl::Reference<sdr::overlay::OverlayManager> xOverlayManager = getOverlayManager();
    if (!xOverlayManager.is())
        return;
    ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard( pViewData->GetActiveWin() );
    const ScTransferObj* pTransObj = ScTransferObj::GetOwnClipboard(pViewData->GetViewShell()->GetClipData());
    if (!pTransObj)
        return;
    ScDocument* pClipDoc = pTransObj->GetDocument();
diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx
index e80d79d..3cfccc5 100644
--- a/sc/source/ui/view/viewfun3.cxx
+++ b/sc/source/ui/view/viewfun3.cxx
@@ -272,13 +272,15 @@ bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, const ScRangeList& rRanges, b
                aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
                // maSize is set in ScTransferObj ctor

                rtl::Reference<ScTransferObj> pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
                ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
                uno::Reference<css::datatransfer::XTransferable2> xTransferObj = pTransferObj;
                if ( ScGlobal::xDrawClipDocShellRef.is() )
                {
                    SfxObjectShellRef aPersistRef( ScGlobal::xDrawClipDocShellRef.get() );
                    pTransferObj->SetDrawPersist( aPersistRef );// keep persist for ole objects alive

                }
                GetViewData().GetViewShell()->SetClipData(xTransferObj);
                pTransferObj->CopyToClipboard( GetActiveWin() );
            }

@@ -378,14 +380,14 @@ bool ScViewFunc::CopyToClip( ScDocument* pClipDoc, const ScRangeList& rRanges, b
                aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
                // maSize is set in ScTransferObj ctor

                rtl::Reference<ScTransferObj> pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );

                ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );
                uno::Reference<css::datatransfer::XTransferable2> xTransferObj = pTransferObj;
                if ( ScGlobal::xDrawClipDocShellRef.is() )
                {
                    SfxObjectShellRef aPersistRef( ScGlobal::xDrawClipDocShellRef.get() );
                    pTransferObj->SetDrawPersist( aPersistRef );    // keep persist for ole objects alive
                }

                GetViewData().GetViewShell()->SetClipData(xTransferObj);
                pTransferObj->CopyToClipboard( GetActiveWin() );    // system clipboard
            }

@@ -447,7 +449,7 @@ void ScViewFunc::PasteDraw()
    vcl::Window* pWin = GetActiveWin();
    Point aPos = pWin->PixelToLogic( rViewData.GetScrPos( nPosX, nPosY,
                                     rViewData.GetActivePart() ) );
    ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
    const ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard(GetViewData().GetViewShell()->GetClipData());
    if (pDrawClip)
    {
        OUString aSrcShellID = pDrawClip->GetShellID();
@@ -461,9 +463,9 @@ void ScViewFunc::PasteFromSystem()
    UpdateInputLine();

    vcl::Window* pWin = GetActiveWin();
    ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(GetViewData().GetViewShell()->GetClipData());
    // keep a reference in case the clipboard is changed during PasteFromClip
    rtl::Reference<ScDrawTransferObj> pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
    const ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard(GetViewData().GetViewShell()->GetClipData());
    if (pOwnClip)
    {
        PasteFromClip( InsertDeleteFlags::ALL, pOwnClip->GetDocument(),
@@ -706,7 +708,7 @@ bool ScViewFunc::PasteFromSystem( SotClipboardFormatId nFormatId, bool bApi )
    bool bRet = true;
    vcl::Window* pWin = GetActiveWin();
    // keep a reference in case the clipboard is changed during PasteFromClip
    rtl::Reference<ScTransferObj> pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
    const ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard(GetViewData().GetViewShell()->GetClipData());
    if ( nFormatId == SotClipboardFormatId::NONE && pOwnClip )
    {
        PasteFromClip( InsertDeleteFlags::ALL, pOwnClip->GetDocument(),
diff --git a/sc/source/ui/view/viewfun7.cxx b/sc/source/ui/view/viewfun7.cxx
index 8bc1078..b264ac3 100644
--- a/sc/source/ui/view/viewfun7.cxx
+++ b/sc/source/ui/view/viewfun7.cxx
@@ -252,9 +252,8 @@ void ScViewFunc::PasteDraw( const Point& rLogicPos, SdrModel* pModel,

        ScDocument* pDocument = GetViewData().GetDocument();
        ScDocShell* pDocShell = GetViewData().GetDocShell();
        vcl::Window* pWin = GetViewData().GetActiveWin();
        ScModelObj* pModelObj = ( pDocShell ? ScModelObj::getImplementation( pDocShell->GetModel() ) : nullptr );
        ScDrawTransferObj* pTransferObj = ScDrawTransferObj::GetOwnClipboard( pWin );
        const ScDrawTransferObj* pTransferObj = ScDrawTransferObj::GetOwnClipboard(GetViewData().GetViewShell()->GetClipData());
        if ( pDocument && pPage && pModelObj && ( pTransferObj || pDrawTrans ) )
        {
            const ScRangeListVector& rProtectedChartRangesVector(