[Libreoffice-commits] core.git: Branch 'distro/vector/vector-5.4' - offapi/com offapi/UnoApi_offapi.mk sw/inc sw/qa sw/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Thu Jan 24 16:26:55 UTC 2019


 offapi/UnoApi_offapi.mk                        |    2 
 offapi/com/sun/star/text/XPasteBroadcaster.idl |   42 ++++++++
 offapi/com/sun/star/text/XPasteListener.idl    |   42 ++++++++
 sw/inc/fesh.hxx                                |    4 
 sw/inc/unotxdoc.hxx                            |   10 +-
 sw/qa/extras/unowriter/unowriter.cxx           |   79 ++++++++++++++++
 sw/source/core/frmedt/fecopy.cxx               |    2 
 sw/source/core/frmedt/fews.cxx                 |   14 ++
 sw/source/uibase/dochdl/swdtflvr.cxx           |  119 +++++++++++++++++++++++--
 sw/source/uibase/inc/swdtflvr.hxx              |    6 -
 sw/source/uibase/uno/unotxdoc.cxx              |   17 +++
 11 files changed, 328 insertions(+), 9 deletions(-)

New commits:
commit d0629f03caa24407829144ec534df7d0d5790232
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Thu Jan 24 09:36:46 2019 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Jan 24 17:14:30 2019 +0100

    sw: make it possible to listen to paste events
    
    The use-case is that the user pastes content and custom postprocessing
    is necessary for the pasted content. This is not easy by default, since
    the cursor is at the end of the pasted content, so the start is not
    known -- even if you intercept the paste UNO command.
    
    Precisely tracking the start is possible when using the internal API,
    SwReader::Read() does something similar already to track the undo range.
    
    Only expose the text selection after paste (as a start), but design the
    API in a way so that other pasted content type (e.g. image) can be
    added in a backwards-compatible way later.
    
    Reviewed-on: https://gerrit.libreoffice.org/66807
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>
    Tested-by: Jenkins
    (cherry picked from commit e14fafaafb3500d65be9c1b69fcb86b31d36468c)
    
    Conflicts:
            sw/qa/extras/unowriter/unowriter.cxx
            sw/source/uibase/dochdl/swdtflvr.cxx
    
    Change-Id: If35bda4244cc417e4858124fb75f7608b95fc556

diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index f0e03f2808e1..9ad506bc44ed 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -3770,6 +3770,8 @@ $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/text,\
 	XPagePrintable \
 	XParagraphAppend \
 	XParagraphCursor \
+	XPasteBroadcaster \
+	XPasteListener \
 	XRedline \
 	XReferenceMarksSupplier \
 	XRelativeTextContentInsert \
diff --git a/offapi/com/sun/star/text/XPasteBroadcaster.idl b/offapi/com/sun/star/text/XPasteBroadcaster.idl
new file mode 100644
index 000000000000..faddd99b6c34
--- /dev/null
+++ b/offapi/com/sun/star/text/XPasteBroadcaster.idl
@@ -0,0 +1,42 @@
+/* -*- 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/.
+ */
+#ifndef __com_sun_star_text_XPasteBroadcaster_idl__
+#define __com_sun_star_text_XPasteBroadcaster_idl__
+
+#include <com/sun/star/uno/XInterface.idl>
+#include <com/sun/star/text/XPasteListener.idl>
+
+module com { module sun { module star { module text {
+
+/** allows for adding/removing of paste event listeners.
+
+    @since LibreOffice 6.3
+*/
+interface XPasteBroadcaster : com::sun::star::uno::XInterface
+{
+    /** Adds an entry to the list of paste listeners.
+
+        @param xListener
+        The listener to be added.
+    */
+    void addPasteEventListener([in] com::sun::star::text::XPasteListener xListener);
+
+    /** Removes an entry to the list of paste listeners.
+
+        @param xListener
+        The listener to be removed.
+    */
+    void removePasteEventListener( [in] com::sun::star::text::XPasteListener xListener );
+};
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/offapi/com/sun/star/text/XPasteListener.idl b/offapi/com/sun/star/text/XPasteListener.idl
new file mode 100644
index 000000000000..ce5d663f4ccd
--- /dev/null
+++ b/offapi/com/sun/star/text/XPasteListener.idl
@@ -0,0 +1,42 @@
+/* -*- 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/.
+ *
+ */
+#ifndef __com_sun_star_text_XPasteListener_idl__
+#define __com_sun_star_text_XPasteListener_idl__
+
+#include <com/sun/star/beans/PropertyValue.idl>
+#include <com/sun/star/uno/XInterface.idl>
+
+module com { module sun { module star { module text {
+
+/**  used to notify listeners about paste events.
+
+    @since LibreOffice 6.3
+*/
+interface XPasteListener : com::sun::star::uno::XInterface
+{
+    /** Notifies the listener about paste events.
+
+        @param aEvent
+        The event containing details about the paste.
+
+        <p>The following keys may be used:
+        <ul>
+            <li>TextRange</li>
+        </ul></p>
+    */
+    void notifyPasteEvent([in] sequence< ::com::sun::star::beans::PropertyValue > aEvent);
+};
+
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/inc/fesh.hxx b/sw/inc/fesh.hxx
index cb7d75a1b827..8e04a276fc50 100644
--- a/sw/inc/fesh.hxx
+++ b/sw/inc/fesh.hxx
@@ -33,6 +33,7 @@
 #include <rtl/ustring.hxx>
 #include <svtools/embedhlp.hxx>
 #include <o3tl/typed_flags_set.hxx>
+#include <comphelper/interfacecontainer2.hxx>
 
 #include <vector>
 #include <memory>
@@ -205,6 +206,7 @@ private:
     std::unique_ptr<SdrDropMarkerOverlay> m_pChainTo;
     std::unique_ptr<SdrDropMarkerOverlay> m_pChainFrom;
     bool m_bCheckForOLEInCaption;
+    comphelper::OInterfaceContainerHelper2 m_aPasteListeners;
 
     SAL_DLLPRIVATE SwFlyFrame *FindFlyFrame( const css::uno::Reference < css::embed::XEmbeddedObject >&  ) const;
 
@@ -561,6 +563,8 @@ public:
     void Paste( SvStream& rStm, SwPasteSdr nAction, const Point* pPt );
     bool Paste( const Graphic &rGrf, const OUString& rURL );
 
+    comphelper::OInterfaceContainerHelper2& GetPasteListeners();
+
     bool IsAlignPossible() const;
     void SetCalcFieldValueHdl(Outliner* pOutliner);
 
diff --git a/sw/inc/unotxdoc.hxx b/sw/inc/unotxdoc.hxx
index ccbfb62589cd..f1e4212d3e52 100644
--- a/sw/inc/unotxdoc.hxx
+++ b/sw/inc/unotxdoc.hxx
@@ -70,6 +70,7 @@
 #include <vcl/event.hxx>
 #include <vcl/ITiledRenderable.hxx>
 #include <com/sun/star/tiledrendering/XTiledRenderable.hpp>
+#include <com/sun/star/text/XPasteBroadcaster.hpp>
 
 #include <unobaseclass.hxx>
 #include <viewopt.hxx>
@@ -122,7 +123,8 @@ typedef cppu::WeakImplHelper
     css::xforms::XFormsSupplier,
     css::text::XFlatParagraphIteratorProvider,
     css::document::XDocumentLanguages,
-    css::util::XCloneable
+    css::util::XCloneable,
+    css::text::XPasteBroadcaster
 >
 SwXTextDocumentBaseClass;
 
@@ -373,6 +375,12 @@ public:
     // css::util::XCloneable
     virtual css::uno::Reference< css::util::XCloneable > SAL_CALL createClone(  ) override;
 
+    // css::text::XPasteBroadcaster
+    void SAL_CALL addPasteEventListener(
+        const ::css::uno::Reference<::css::text::XPasteListener>& xListener) override;
+    void SAL_CALL removePasteEventListener(
+        const ::css::uno::Reference<::css::text::XPasteListener>& xListener) override;
+
     /// @see vcl::ITiledRenderable::paintTile().
     virtual void paintTile( VirtualDevice &rDevice,
                             int nOutputWidth,
diff --git a/sw/qa/extras/unowriter/unowriter.cxx b/sw/qa/extras/unowriter/unowriter.cxx
index f76dad1c5b71..afdc9bb16988 100644
--- a/sw/qa/extras/unowriter/unowriter.cxx
+++ b/sw/qa/extras/unowriter/unowriter.cxx
@@ -11,6 +11,7 @@
 #include <com/sun/star/awt/FontSlant.hpp>
 #include <wrtsh.hxx>
 #include <ndtxt.hxx>
+#include <swdtflvr.hxx>
 
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::uno;
@@ -19,6 +20,31 @@ using namespace ::com::sun::star::text;
 namespace
 {
 char const DATA_DIRECTORY[] = "/sw/qa/extras/unowriter/data/";
+
+/// Listener implementation for testPasteListener.
+class PasteListener : public cppu::WeakImplHelper<text::XPasteListener>
+{
+    OUString m_aString;
+
+public:
+    void SAL_CALL notifyPasteEvent(const uno::Sequence<beans::PropertyValue>& rEvent) override;
+
+    OUString& GetString();
+};
+
+void PasteListener::notifyPasteEvent(const uno::Sequence<beans::PropertyValue>& rEvent)
+{
+    comphelper::SequenceAsHashMap aMap(rEvent);
+    auto it = aMap.find("TextRange");
+    if (it != aMap.end())
+    {
+        auto xTextRange = it->second.get<uno::Reference<text::XTextRange>>();
+        if (xTextRange.is())
+            m_aString = xTextRange->getString();
+    }
+}
+
+OUString& PasteListener::GetString() { return m_aString; }
 }
 
 /// Test to assert UNO API call results of Writer.
@@ -28,11 +54,13 @@ public:
     void testDefaultCharStyle();
     void testSelectionInTableEnum();
     void testSelectionInTableEnumEnd();
+    void testPasteListener();
 
     CPPUNIT_TEST_SUITE(SwUnoWriter);
     CPPUNIT_TEST(testDefaultCharStyle);
     CPPUNIT_TEST(testSelectionInTableEnum);
     CPPUNIT_TEST(testSelectionInTableEnumEnd);
+    CPPUNIT_TEST(testPasteListener);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -137,6 +165,57 @@ void SwUnoWriter::testSelectionInTableEnumEnd()
     CPPUNIT_ASSERT(!xEnum->hasMoreElements());
 }
 
+void SwUnoWriter::testPasteListener()
+{
+    loadURL("private:factory/swriter", nullptr);
+
+    // Insert initial string.
+    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
+    uno::Reference<text::XSimpleText> xBodyText(xTextDocument->getText(), uno::UNO_QUERY);
+    xBodyText->insertString(xBodyText->getStart(), "ABCDEF", false);
+
+    // Add paste listener.
+    uno::Reference<text::XPasteBroadcaster> xBroadcaster(mxComponent, uno::UNO_QUERY);
+    uno::Reference<text::XPasteListener> xListener(new PasteListener);
+    auto pListener = static_cast<PasteListener*>(xListener.get());
+    xBroadcaster->addPasteEventListener(xListener);
+
+    // Cut "DE" and then paste it.
+    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+    SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
+    CPPUNIT_ASSERT(pWrtShell);
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 3, /*bBasicCall=*/false);
+    pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 2, /*bBasicCall=*/false);
+    rtl::Reference<SwTransferable> pTransfer = new SwTransferable(*pWrtShell);
+    pTransfer->Cut();
+    TransferableDataHelper aHelper(pTransfer.get());
+    SwTransferable::Paste(*pWrtShell, aHelper);
+    // Without working listener registration in place, this test would have
+    // failed with 'Expected: DE; Actual:', i.e. the paste listener was not
+    // invoked.
+    CPPUNIT_ASSERT_EQUAL(OUString("DE"), pListener->GetString());
+
+    // Make sure that paste did not overwrite anything.
+    CPPUNIT_ASSERT_EQUAL(OUString("ABCDEF"), xBodyText->getString());
+
+    // Paste again, this time overwriting "BC".
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 4, /*bBasicCall=*/false);
+    pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/true, 2, /*bBasicCall=*/false);
+    pListener->GetString().clear();
+    SwTransferable::Paste(*pWrtShell, aHelper);
+    CPPUNIT_ASSERT_EQUAL(OUString("DE"), pListener->GetString());
+
+    // Make sure that paste overwrote "BC".
+    CPPUNIT_ASSERT_EQUAL(OUString("ADEDEF"), xBodyText->getString());
+
+    // Deregister paste listener, make sure it's not invoked.
+    xBroadcaster->removePasteEventListener(xListener);
+    pListener->GetString().clear();
+    SwTransferable::Paste(*pWrtShell, aHelper);
+    CPPUNIT_ASSERT(pListener->GetString().isEmpty());
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SwUnoWriter);
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index ee988eb47c5b..2c20075f3032 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -1188,6 +1188,8 @@ bool SwFEShell::PastePages( SwFEShell& rToFill, sal_uInt16 nStartPage, sal_uInt1
     return true;
 }
 
+comphelper::OInterfaceContainerHelper2& SwFEShell::GetPasteListeners() { return m_aPasteListeners; }
+
 bool SwFEShell::GetDrawObjGraphic( SotClipboardFormatId nFormat, Graphic& rGrf ) const
 {
     OSL_ENSURE( Imp()->HasDrawView(), "GetDrawObjGraphic without DrawView?" );
diff --git a/sw/source/core/frmedt/fews.cxx b/sw/source/core/frmedt/fews.cxx
index 1208a71aa8cf..910ac69047fa 100644
--- a/sw/source/core/frmedt/fews.cxx
+++ b/sw/source/core/frmedt/fews.cxx
@@ -54,6 +54,18 @@
 
 using namespace com::sun::star;
 
+namespace
+{
+/**
+ * This mutex is only used for the paste listeners, where the solar mutex can't
+ * be used.
+ */
+osl::Mutex& GetPasteMutex()
+{
+    static osl::Mutex aMutex;
+    return aMutex;
+}
+}
 
 void SwFEShell::EndAllActionAndCall()
 {
@@ -686,12 +698,14 @@ sal_uInt16 SwFEShell::GetCurOutColNum() const
 SwFEShell::SwFEShell( SwDoc& rDoc, vcl::Window *pWindow, const SwViewOption *pOptions )
     : SwEditShell( rDoc, pWindow, pOptions )
     , m_bCheckForOLEInCaption(false)
+    , m_aPasteListeners(GetPasteMutex())
 {
 }
 
 SwFEShell::SwFEShell( SwEditShell& rShell, vcl::Window *pWindow )
     : SwEditShell( rShell, pWindow )
     , m_bCheckForOLEInCaption(false)
+    , m_aPasteListeners(GetPasteMutex())
 {
 }
 
diff --git a/sw/source/uibase/dochdl/swdtflvr.cxx b/sw/source/uibase/dochdl/swdtflvr.cxx
index 9d480675171b..5c732ae22c82 100644
--- a/sw/source/uibase/dochdl/swdtflvr.cxx
+++ b/sw/source/uibase/dochdl/swdtflvr.cxx
@@ -24,6 +24,7 @@
 #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>
@@ -124,6 +125,7 @@
 #include <swserv.hxx>
 #include <calbck.hxx>
 #include <fmtmeta.hxx>
+#include <unotextrange.hxx>
 
 #include <vcl/GraphicNativeTransform.hxx>
 #include <vcl/GraphicNativeMetadata.hxx>
@@ -179,17 +181,39 @@ public:
     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::unique_ptr<SwPaM> m_pPaM;
+    sal_Int32 m_nStartContent = 0;
+};
+
 // helper class for Action and Undo enclosing
 class SwTrnsfrActionAndUndo
 {
     SwWrtShell *pSh;
 public:
-    SwTrnsfrActionAndUndo( SwWrtShell *pS, bool bDelSel = false)
+    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()
@@ -1089,6 +1113,82 @@ static inline uno::Reference < XTransferable > * lcl_getTransferPointer ( uno::R
     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 SwNodeIndex& rNodeIndex = pCursor->GetPoint()->nNode;
+    m_pPaM.reset(new SwPaM(rNodeIndex, rNodeIndex, 0, -1));
+    m_nStartContent = pCursor->GetPoint()->nContent.GetIndex();
+}
+
+void SwPasteContext::forget() { m_pPaM.reset(nullptr); }
+
+SwPasteContext::~SwPasteContext()
+{
+    try
+    {
+        if (m_rWrtShell.GetPasteListeners().getLength() == 0)
+            return;
+
+        if (!m_pPaM)
+            return;
+
+        SwPaM* pCursor = m_rWrtShell.GetCursor();
+        if (!pCursor)
+            return;
+
+        if (!pCursor->GetPoint()->nNode.GetNode().IsTextNode())
+            // Non-text was pasted.
+            return;
+
+        // Update mark after paste.
+        *m_pPaM->GetMark() = *pCursor->GetPoint();
+
+        // Restore point.
+        ++m_pPaM->GetPoint()->nNode;
+        SwNode& rNode = m_pPaM->GetNode();
+        if (!rNode.IsTextNode())
+            // Starting point is no longer text.
+            return;
+
+        m_pPaM->GetPoint()->nContent.Assign(static_cast<SwContentNode*>(&rNode), m_nStartContent);
+
+        // Invoke the listeners.
+        beans::PropertyValue aPropertyValue;
+        aPropertyValue.Name = "TextRange";
+        const uno::Reference<text::XTextRange> xTextRange = SwXTextRange::CreateXTextRange(
+            *m_pPaM->GetDoc(), *m_pPaM->GetPoint(), m_pPaM->GetMark());
+        aPropertyValue.Value <<= xTextRange;
+        uno::Sequence<beans::PropertyValue> aEvent{ aPropertyValue };
+
+        comphelper::OInterfaceIteratorHelper2 it(m_rWrtShell.GetPasteListeners());
+        while (it.hasMoreElements())
+        {
+            uno::Reference<text::XPasteListener> xListener(it.next(), UNO_QUERY);
+            if (xListener.is())
+                xListener->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 )
 {
@@ -1132,6 +1232,8 @@ bool SwTransferable::IsPaste( const SwWrtShell& rSh,
 
 bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndStdIds nAnchorType)
 {
+    SwPasteContext aPasteContext(rSh);
+
     sal_uInt8 nEventAction, nAction=0;
     SotExchangeDest nDestination = SwTransferable::GetSotDestination( rSh );
     SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
@@ -1178,7 +1280,7 @@ bool SwTransferable::Paste(SwWrtShell& rSh, TransferableDataHelper& rData, RndSt
 
     return EXCHG_INOUT_ACTION_NONE != nAction &&
             SwTransferable::PasteData( rData, rSh, nAction, nActionFlags, nFormat,
-                                        nDestination, false, false, nullptr, 0, false, nAnchorType );
+                                        nDestination, false, false, nullptr, 0, false, nAnchorType, &aPasteContext );
 }
 
 bool SwTransferable::PasteData( TransferableDataHelper& rData,
@@ -1187,7 +1289,8 @@ bool SwTransferable::PasteData( TransferableDataHelper& rData,
                             SotExchangeDest nDestination, bool bIsPasteFormat,
                             bool bIsDefault,
                             const Point* pPt, sal_Int8 nDropAction,
-                            bool bPasteSelection, RndStdIds nAnchorType )
+                            bool bPasteSelection, RndStdIds nAnchorType,
+                            SwPasteContext* pContext )
 {
     SwWait aWait( *rSh.GetView().GetDocShell(), false );
     std::unique_ptr<SwTrnsfrActionAndUndo> pAction;
@@ -1246,7 +1349,7 @@ bool SwTransferable::PasteData( TransferableDataHelper& rData,
 
         if( bDelSel )
             // #i34830#
-            pAction.reset(new SwTrnsfrActionAndUndo( &rSh, true ));
+            pAction.reset(new SwTrnsfrActionAndUndo(&rSh, true, pContext));
     }
 
     SwTransferable *pTrans=nullptr, *pTunneledTrans=GetSwTransferable( rData );
@@ -1285,7 +1388,7 @@ bool SwTransferable::PasteData( TransferableDataHelper& rData,
             EXCHG_OUT_ACTION_INSERT_PRIVATE == nAction )
     {
         // then internal paste
-        bRet = pTunneledTrans->PrivatePaste( rSh );
+        bRet = pTunneledTrans->PrivatePaste(rSh, pContext);
     }
     else if( EXCHG_INOUT_ACTION_NONE != nAction )
     {
@@ -3232,7 +3335,7 @@ bool lcl_checkClassification(SwDoc* pSourceDoc, SwDoc* pDestinationDoc)
 
 }
 
-bool SwTransferable::PrivatePaste( SwWrtShell& rShell )
+bool SwTransferable::PrivatePaste(SwWrtShell& rShell, SwPasteContext* pContext)
 {
     // first, ask for the SelectionType, then action-bracketing !!!!
     // (otherwise it's not pasted into a TableSelection!!!)
@@ -3251,7 +3354,11 @@ bool SwTransferable::PrivatePaste( SwWrtShell& rShell )
     {
         bKillPaMs = true;
         rShell.SetRetainSelection( true );
+        if (pContext)
+            pContext->forget();
         rShell.DelRight();
+        if (pContext)
+            pContext->remember();
         // when a Fly was selected, a valid cursor position has to be found now
         // (parked Cursor!)
         if( ( SelectionType::Frame | SelectionType::Graphic |
diff --git a/sw/source/uibase/inc/swdtflvr.hxx b/sw/source/uibase/inc/swdtflvr.hxx
index c2f03e731f3b..0dbaf2dab666 100644
--- a/sw/source/uibase/inc/swdtflvr.hxx
+++ b/sw/source/uibase/inc/swdtflvr.hxx
@@ -38,6 +38,7 @@ class SwWrtShell;
 class SvxClipboardFormatItem;
 class SwFrameShell;
 class SwView_Impl;
+class SwPasteContext;
 enum class SwPasteSdr;
 
 enum class TransferBufferType : sal_uInt16
@@ -128,7 +129,7 @@ class SW_DLLPUBLIC SwTransferable : public TransferableHelper
 
     bool PrivateDrop( SwWrtShell& rSh, const Point& rDragPt, bool bMove,
                         bool bIsXSelection );
-    bool PrivatePaste( SwWrtShell& rShell );
+    bool PrivatePaste( SwWrtShell& rShell, SwPasteContext* pContext = nullptr );
 
     void SetDataForDragAndDrop( const Point& rSttPos );
 
@@ -176,7 +177,8 @@ public:
                           SotExchangeDest nDestination, bool bIsPasteFormat,
                           bool bIsDefault,
                           const Point* pDDPos = nullptr, sal_Int8 nDropAction = 0,
-                          bool bPasteSelection = false, RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA );
+                          bool bPasteSelection = false, RndStdIds nAnchorType = RndStdIds::FLY_AT_PARA,
+                          SwPasteContext* pContext = nullptr );
 
     static bool IsPasteSpecial( const SwWrtShell& rWrtShell,
                                 const TransferableDataHelper& );
diff --git a/sw/source/uibase/uno/unotxdoc.cxx b/sw/source/uibase/uno/unotxdoc.cxx
index 180c57b734cc..5a3db4080826 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3080,6 +3080,23 @@ uno::Reference< util::XCloneable > SwXTextDocument::createClone(  )
     return uno::Reference< util::XCloneable >( xNewModel, UNO_QUERY );
 }
 
+void SwXTextDocument::addPasteEventListener(const uno::Reference<text::XPasteListener>& xListener)
+{
+    SolarMutexGuard aGuard;
+
+    if (IsValid() && xListener.is())
+        pDocShell->GetWrtShell()->GetPasteListeners().addInterface(xListener);
+}
+
+void SwXTextDocument::removePasteEventListener(
+    const uno::Reference<text::XPasteListener>& xListener)
+{
+    SolarMutexGuard aGuard;
+
+    if (IsValid() && xListener.is())
+        pDocShell->GetWrtShell()->GetPasteListeners().removeInterface(xListener);
+}
+
 void SwXTextDocument::paintTile( VirtualDevice &rDevice,
                                  int nOutputWidth, int nOutputHeight,
                                  int nTilePosX, int nTilePosY,


More information about the Libreoffice-commits mailing list