sw/qa/extras/rtfexport/data/tdf167512.rtf   |   11 ++++++++
 sw/qa/extras/rtfexport/rtfexport8.cxx       |   37 ++++++++++++++++++++++++++++
 sw/source/filter/ww8/rtfattributeoutput.cxx |    7 +----
 3 files changed, 50 insertions(+), 5 deletions(-)

New commits:
commit 64ce212034953d9f1fc242f7aa04ffabf0d96eea
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Jul 15 18:50:51 2025 +0500
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Jul 16 08:49:34 2025 +0200

    tdf#167512: don't avoid resetting paragraphs' properties in fly
    
    Commit 5bbc027d5dae3472223538b13933ff821e027737 (cws-vmiklos01.diff:
    Better RTF export filter, 2010-09-17) introduced RtfAttributeOutput
    and its StartParagraphProperties, where output of \pard\plain was
    skipped when in fly. The reason likely was, that at that time, text
    boxes were output using an "old-style" method, where text box was
    purely a paragraph-level formatting. This created a problem: list
    settings weren't reset for following paragraphs, so lists continued
    incorrectly.
    
    Commit d53dd70b15f0e3f7c8a05a93f8fcd70e1147c1f7 (sw: rework RTF
    export of text frames, 2013-04-12) reimplemented text box export to
    use a "new-style" frames (using \shp ... \shptxt markup). This made
    it possible to restore resetting of paragraph properties, without
    breaking text boxes. This is done here.
    
    Change-Id: Idaabece2a658845906463c942aad45a142f87633
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187920
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187933
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>

diff --git a/sw/qa/extras/rtfexport/data/tdf167512.rtf 
b/sw/qa/extras/rtfexport/data/tdf167512.rtf
new file mode 100644
index 000000000000..476eb388be68
--- /dev/null
+++ b/sw/qa/extras/rtfexport/data/tdf167512.rtf
@@ -0,0 +1,11 @@
+{ tf1
+{onttbl{0romancharset0prq2 Liberation Serif;}}
+{\*\listtable{\list\listtemplateid1{\listlevel\levelnfc23\leveljc0\levelfollow0{\leveltext
 \'01-}0}\listid1}}
+{\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}}
+{\shp{\*\shpinst\shpwr1\shpbypara\shpbyignore\shptop0\shpbottom1700\shpbxcolumn\shpbxignore\shpleft1000\shpright4000
+{\shptxt
+\pard0 AAA\par
+\pard0\ls1 BBB\par
+\pard0 CCC\par
+}}}
+\par }
\ No newline at end of file
diff --git a/sw/qa/extras/rtfexport/rtfexport8.cxx 
b/sw/qa/extras/rtfexport/rtfexport8.cxx
index e697dab465ce..7862a235292d 100644
--- a/sw/qa/extras/rtfexport/rtfexport8.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport8.cxx
@@ -735,6 +735,43 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf155835)
     }
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf167512)
+{
+    // Given a document with a text box with a paragraph in a list, followed 
by a paragraph not
+    // in a list:
+    createSwDoc("tdf167512.rtf");
+    {
+        CPPUNIT_ASSERT_EQUAL(1, getShapes());
+        auto xTextBox = getShape(1).queryThrow<text::XText>();
+        // First paragraph is not in list
+        auto xParagraph = getParagraphOfText(1, xTextBox, u"AAA"_ustr);
+        CPPUNIT_ASSERT(getProperty<OUString>(xParagraph, 
u"ListId"_ustr).isEmpty());
+        // Second paragraph is in list (its ListId is not empty)
+        xParagraph = getParagraphOfText(2, xTextBox, u"BBB"_ustr);
+        CPPUNIT_ASSERT(!getProperty<OUString>(xParagraph, 
u"ListId"_ustr).isEmpty());
+        // Third paragraph is not in list
+        xParagraph = getParagraphOfText(3, xTextBox, u"CCC"_ustr);
+        CPPUNIT_ASSERT(getProperty<OUString>(xParagraph, 
u"ListId"_ustr).isEmpty());
+    }
+    // Check export
+    saveAndReload(mpFilter);
+    {
+        CPPUNIT_ASSERT_EQUAL(1, getShapes());
+        auto xTextBox = getShape(1).queryThrow<text::XText>();
+        // First paragraph is not in list
+        auto xParagraph = getParagraphOfText(1, xTextBox, u"AAA"_ustr);
+        CPPUNIT_ASSERT(getProperty<OUString>(xParagraph, 
u"ListId"_ustr).isEmpty());
+        // Second paragraph is in list (its ListId is not empty)
+        xParagraph = getParagraphOfText(2, xTextBox, u"BBB"_ustr);
+        CPPUNIT_ASSERT(!getProperty<OUString>(xParagraph, 
u"ListId"_ustr).isEmpty());
+        // Third paragraph is not in list
+        xParagraph = getParagraphOfText(3, xTextBox, u"CCC"_ustr);
+        // Without the fix, this failed, because on export, the paragraph's 
properties weren't
+        // reset to defaults using \pard when starting next paragraph; so the 
list continued:
+        CPPUNIT_ASSERT(getProperty<OUString>(xParagraph, 
u"ListId"_ustr).isEmpty());
+    }
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx 
b/sw/source/filter/ww8/rtfattributeoutput.cxx
index bf7d99a628cb..01b92a9876db 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -383,11 +383,8 @@ void RtfAttributeOutput::SectionBreaks(const SwNode& rNode)
 
 void RtfAttributeOutput::StartParagraphProperties()
 {
-    OStringBuffer aPar;
-    if (!m_rExport.GetRTFFlySyntax())
-    {
-        aPar.append(OOO_STRING_SVTOOLS_RTF_PARD OOO_STRING_SVTOOLS_RTF_PLAIN " 
");
-    }
+    static constexpr std::string_view aPar(OOO_STRING_SVTOOLS_RTF_PARD 
OOO_STRING_SVTOOLS_RTF_PLAIN
+                                           " ");
     if (!m_bBufferSectionHeaders)
         m_rExport.Strm().WriteOString(aPar);
     else

Reply via email to