desktop/qa/desktop_lib/test_desktop_lib.cxx |   20 ++++++++++++++++++++
 desktop/source/lib/init.cxx                 |    2 ++
 sfx2/sdi/sfx.sdi                            |    2 +-
 sw/source/uibase/shells/basesh.cxx          |    9 ++++++++-
 4 files changed, 31 insertions(+), 2 deletions(-)

New commits:
commit 0f371db55f5e22a37ea3b15fe998461c0b1873b1
Author:     Miklos Vajna <[email protected]>
AuthorDate: Mon Nov 17 09:13:49 2025 +0100
Commit:     Caolán McNamara <[email protected]>
CommitDate: Mon Nov 17 16:07:36 2025 +0100

    cool#13468 sw markdown paste: add UNO command parameter to skip the 
detection
    
    .uno:Paste tries to detect if the plain text content is really just
    plain text or markdown. There is no way to paste the clipboard content
    as plain text in a non-interactive way if the input looks like markdown.
    
    What happens is that .uno:Paste uses comphelper::IsMarkdownData() to
    guess if the input is markdown. This is fine in general, but if you want
    to paste "foo _bar_ baz" as-is, there is no .uno:Paste parameter to do
    so, you always get "foo <i>bar</i> baz".
    
    Fix the problem by adding a new SkipDetection parameter for .uno:Paste,
    while keeping the current behavior unchanged. The LOK API's doc_paste()
    function has an explicit mimetype parameter, so skip detection when
    using that API (a LOK client will use doc_setClipboard() when the user
    does a Ctrl-V, behavior there is unchanged).
    
    Note that an interactive way did exist previously: if you did paste
    special and selected plain text, that did work.
    
    Change-Id: I9888b1bf2322d3e1eeb32ffc8c8d08490b8eaa2c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194091
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Tested-by: Caolán McNamara <[email protected]>
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx 
b/desktop/qa/desktop_lib/test_desktop_lib.cxx
index 0186e9ba9e4e..62d20d72a668 100644
--- a/desktop/qa/desktop_lib/test_desktop_lib.cxx
+++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx
@@ -761,6 +761,26 @@ void DesktopLOKTest::testPasteWriter()
     // Without the accompanying fix in place, this test would have failed, as 
we had a comment
     // between "foo" and "baz".
     CPPUNIT_ASSERT(!xTextPortionEnumeration->hasMoreElements());
+
+    // Overwrite the doc contents with an explicitly plain text paste.
+    pDocument->pClass->postUnoCommand(pDocument, ".uno:SelectAll", nullptr, 
false);
+    Scheduler::ProcessEventsToIdle();
+    OString aPlainText("foo _bar_ baz"_ostr);
+    CPPUNIT_ASSERT(pDocument->pClass->paste(pDocument, "text/plain", 
aPlainText.getStr(),
+                                            aPlainText.getLength()));
+
+    // Check if '_bar_' was pasted as-is.
+    xParagraphEnumeration = xParagraphEnumerationAccess->createEnumeration();
+    xParagraph.set(xParagraphEnumeration->nextElement(), uno::UNO_QUERY);
+    xTextPortionEnumeration = xParagraph->createEnumeration();
+    uno::Reference<text::XTextRange> 
xTextPortionRange(xTextPortionEnumeration->nextElement(),
+                                                       uno::UNO_QUERY);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: foo _bar_ baz
+    // - Actual  : foo
+    // i.e. the text/plain input was parsed as markdown, while that should not 
happen when
+    // specifying the text/plain mimetype explicitly (and not text/markdown).
+    CPPUNIT_ASSERT_EQUAL(u"foo _bar_ baz"_ustr, 
xTextPortionRange->getString());
 }
 
 void DesktopLOKTest::testPasteWriterJPEG()
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index db1a475f24df..1adcb0c40f59 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -6296,6 +6296,8 @@ static bool doc_paste(LibreOfficeKitDocument* pThis, 
const char* pMimeType, cons
     {
         {"AnchorType", 
uno::Any(static_cast<sal_uInt16>(css::text::TextContentAnchorType_AS_CHARACTER))},
         {"IgnoreComments", uno::Any(true)},
+        // The MIME type is specified explicitly, don't guess.
+        {"SkipDetection", uno::Any(true)},
     }));
     if (!comphelper::dispatchCommand(u".uno:Paste"_ustr, aPropertyValues))
     {
diff --git a/sfx2/sdi/sfx.sdi b/sfx2/sdi/sfx.sdi
index 386384759574..a752fa601673 100644
--- a/sfx2/sdi/sfx.sdi
+++ b/sfx2/sdi/sfx.sdi
@@ -3168,7 +3168,7 @@ SfxTemplateItem ParaStyle SID_STYLE_FAMILY2
 
 
 SfxVoidItem Paste SID_PASTE
-(SfxUInt16Item AnchorType FN_PARAM_1, SfxBoolItem IgnoreComments FN_PARAM_2)
+(SfxUInt16Item AnchorType FN_PARAM_1, SfxBoolItem IgnoreComments FN_PARAM_2, 
SfxBoolItem SkipDetection FN_PARAM_3)
 [
     AutoUpdate = FALSE,
     FastCall = TRUE,
diff --git a/sw/source/uibase/shells/basesh.cxx 
b/sw/source/uibase/shells/basesh.cxx
index 419e9bfa9967..80fbf76879f6 100644
--- a/sw/source/uibase/shells/basesh.cxx
+++ b/sw/source/uibase/shells/basesh.cxx
@@ -376,7 +376,14 @@ void SwBaseShell::ExecClpbrd(SfxRequest &rReq)
                     const SfxBoolItem* pIgnoreComments = 
rReq.GetArg<SfxBoolItem>(FN_PARAM_2);
                     if (pIgnoreComments)
                         bIgnoreComments = pIgnoreComments->GetValue();
-                    SwTransferable::Paste(rSh, aDataHelper, nAnchorType, 
bIgnoreComments, ePasteTable, true);
+
+                    // See if detection should be used.
+                    bool bSkipDetection = false;
+                    const SfxBoolItem* pSkipDetection = 
rReq.GetArg<SfxBoolItem>(FN_PARAM_3);
+                    if (pSkipDetection)
+                        bSkipDetection = pSkipDetection->GetValue();
+
+                    SwTransferable::Paste(rSh, aDataHelper, nAnchorType, 
bIgnoreComments, ePasteTable, !bSkipDetection);
 
                     if( rSh.IsFrameSelected() || rSh.IsObjSelected() )
                         rSh.EnterSelFrameMode();

Reply via email to