sw/qa/extras/rtfexport/data/tdf165564.odt       |binary
 sw/qa/extras/rtfexport/rtfexport8.cxx           |   15 +++++++++++++++
 sw/source/filter/ww8/attributeoutputbase.hxx    |    2 +-
 sw/source/filter/ww8/docxattributeoutput.cxx    |    3 ++-
 sw/source/filter/ww8/docxattributeoutput.hxx    |    2 +-
 sw/source/filter/ww8/rtfattributeoutput.cxx     |    7 ++++---
 sw/source/filter/ww8/rtfattributeoutput.hxx     |    4 ++--
 sw/source/filter/ww8/ww8atr.cxx                 |    3 ++-
 sw/source/filter/ww8/ww8attributeoutput.hxx     |    2 +-
 sw/source/writerfilter/dmapper/DomainMapper.cxx |    3 ++-
 10 files changed, 30 insertions(+), 11 deletions(-)

New commits:
commit 74eae2899cee3b8720ccd86fdedf3fccecdf8035
Author:     Oliver Specht <oliver.spe...@cib.de>
AuthorDate: Tue May 6 08:34:17 2025 +0200
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Thu May 8 17:18:39 2025 +0200

    tdf#165564 RTF:Fix export and import of footnotes/endnotes
    
    Removes additional spaces in export and wrong insertions of custom
    footnote/endnote symbols in import.
    
    Change-Id: I2e79e87a5b644b116a87602332e09cde89b64ba5
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/184979
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    Tested-by: Thorsten Behrens <thorsten.behr...@allotropia.de>

diff --git a/sw/qa/extras/rtfexport/data/tdf165564.odt 
b/sw/qa/extras/rtfexport/data/tdf165564.odt
new file mode 100644
index 000000000000..d849e1a115ff
Binary files /dev/null and b/sw/qa/extras/rtfexport/data/tdf165564.odt differ
diff --git a/sw/qa/extras/rtfexport/rtfexport8.cxx 
b/sw/qa/extras/rtfexport/rtfexport8.cxx
index 0538ac71ea28..6a2638e2c436 100644
--- a/sw/qa/extras/rtfexport/rtfexport8.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport8.cxx
@@ -609,6 +609,21 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf161878)
     saveAndReload(mpFilter);
     verify();
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testTdf165564)
+{
+    auto verify = [this]() {
+        auto para1 = getParagraph(1);
+        CPPUNIT_ASSERT_EQUAL(u"iXEndnote testiiY"_ustr, para1->getString());
+        auto para2 = getParagraph(2);
+        CPPUNIT_ASSERT_EQUAL(u"*1Footnote test2+"_ustr, para2->getString());
+    };
+    createSwDoc("tdf165564.odt");
+    verify();
+    saveAndReload(mpFilter);
+    verify();
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx 
b/sw/source/filter/ww8/attributeoutputbase.hxx
index a6845c56b633..8634b08b3e01 100644
--- a/sw/source/filter/ww8/attributeoutputbase.hxx
+++ b/sw/source/filter/ww8/attributeoutputbase.hxx
@@ -179,7 +179,7 @@ public:
     virtual void StartRunProperties() = 0;
 
     /// Called after we end outputting the attributes.
-    virtual void EndRunProperties( const SwRedlineData* pRedlineData ) = 0;
+    virtual bool EndRunProperties( const SwRedlineData* pRedlineData ) = 0;
 
     /// docx requires footnoteRef/endnoteRef tag at the beginning of each of 
them
     virtual bool FootnoteEndnoteRefTag() { return false; };
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx 
b/sw/source/filter/ww8/docxattributeoutput.cxx
index 5c16d48b2dff..268d20c2ad11 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -3609,7 +3609,7 @@ void DocxAttributeOutput::WriteCollectedRunProperties()
     m_aTextEffectsGrabBag.clear();
 }
 
-void DocxAttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData )
+bool DocxAttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData )
 {
     // Call the 'Redline' function. This will add redline (change-tracking) 
information that regards to run properties.
     // This includes changes like 'Bold', 'Underline', 'Strikethrough' etc.
@@ -3648,6 +3648,7 @@ void DocxAttributeOutput::EndRunProperties( const 
SwRedlineData* pRedlineData )
     WritePostponedOLE();
 
     WritePostponedActiveXControl(true);
+    return false;
 }
 
 void DocxAttributeOutput::GetSdtEndBefore(const SdrObject* pSdrObj)
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx 
b/sw/source/filter/ww8/docxattributeoutput.hxx
index d9cddce059c7..8ac2d3cabb73 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -232,7 +232,7 @@ public:
     virtual void StartRunProperties() override;
 
     /// Called after we end outputting the attributes.
-    virtual void EndRunProperties( const SwRedlineData* pRedlineData ) 
override;
+    virtual bool EndRunProperties( const SwRedlineData* pRedlineData ) 
override;
 
     virtual bool FootnoteEndnoteRefTag() override;
 
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx 
b/sw/source/filter/ww8/rtfattributeoutput.cxx
index 08b5d80a5d7d..6d307647a4fc 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -441,10 +441,11 @@ void RtfAttributeOutput::StartRunProperties()
     OSL_ENSURE(m_aStyles.getLength() == 0, "m_aStyles is not empty");
 }
 
-void RtfAttributeOutput::EndRunProperties(const SwRedlineData* 
/*pRedlineData*/)
+bool RtfAttributeOutput::EndRunProperties(const SwRedlineData* 
/*pRedlineData*/)
 {
     const OString aProperties = MoveCharacterProperties(true);
     m_aRun->append(aProperties);
+    return !aProperties.isEmpty();
 }
 
 OString RtfAttributeOutput::MoveCharacterProperties(bool aAutoWriteRtlLtr)
@@ -3073,8 +3074,8 @@ void RtfAttributeOutput::TextFootnote_Impl(const 
SwFormatFootnote& rFootnote)
     SAL_INFO("sw.rtf", __func__ << " start");
 
     m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_SUPER " ");
-    EndRunProperties(nullptr);
-    m_aRun->append(' ');
+    if (EndRunProperties(nullptr))
+        m_aRun->append(' ');
     WriteTextFootnoteNumStr(rFootnote);
     m_aRun->append("{" OOO_STRING_SVTOOLS_RTF_IGNORE 
OOO_STRING_SVTOOLS_RTF_FOOTNOTE);
     if (rFootnote.IsEndNote() || m_rExport.m_rDoc.GetFootnoteInfo().m_ePos == 
FTNPOS_CHAPTER)
diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx 
b/sw/source/filter/ww8/rtfattributeoutput.hxx
index 8ba84bed6055..37f2bd8f7ffc 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.hxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.hxx
@@ -82,8 +82,8 @@ public:
     /// Called before we start outputting the attributes.
     void StartRunProperties() override;
 
-    /// Called after we end outputting the attributes.
-    void EndRunProperties(const SwRedlineData* pRedlineData) override;
+    /// Called after we end outputting the attributes, returns true if 
commands were added.
+    bool EndRunProperties(const SwRedlineData* pRedlineData) override;
 
     /// Output text (inside a run).
     void RunText(const OUString& rText, rtl_TextEncoding eCharSet = 
RTL_TEXTENCODING_UTF8,
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index a9ec2d1983c5..f48d0da0e4c6 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -1184,7 +1184,7 @@ void WW8AttributeOutput::EndRun( const SwTextNode* 
/*pNode*/, sal_Int32 nPos, sa
     }
 }
 
-void WW8AttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData )
+bool WW8AttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData )
 {
     Redline( pRedlineData );
 
@@ -1203,6 +1203,7 @@ void WW8AttributeOutput::EndRunProperties( const 
SwRedlineData* pRedlineData )
                 m_rWW8Export.m_pO->size(), m_rWW8Export.m_pO->data() );
     }
     m_rWW8Export.m_pO->clear();
+    return false;
 }
 
 void WW8AttributeOutput::RunText( const OUString& rText, rtl_TextEncoding 
eCharSet, const OUString& /*rSymbolFont*/ )
diff --git a/sw/source/filter/ww8/ww8attributeoutput.hxx 
b/sw/source/filter/ww8/ww8attributeoutput.hxx
index a103cc4c11ce..70c34c28a92c 100644
--- a/sw/source/filter/ww8/ww8attributeoutput.hxx
+++ b/sw/source/filter/ww8/ww8attributeoutput.hxx
@@ -64,7 +64,7 @@ public:
     virtual void StartRunProperties() override;
 
     /// After we end outputting the attributes.
-    virtual void EndRunProperties( const SwRedlineData* pRedlineData ) 
override;
+    virtual bool EndRunProperties( const SwRedlineData* pRedlineData ) 
override;
 
     /// Output text.
     virtual void RunText( const OUString& rText, rtl_TextEncoding eCharSet = 
RTL_TEXTENCODING_UTF8, const OUString& rSymbolFont = OUString() ) override;
diff --git a/sw/source/writerfilter/dmapper/DomainMapper.cxx 
b/sw/source/writerfilter/dmapper/DomainMapper.cxx
index 4a06df0bbb18..cadde4f8a57d 100644
--- a/sw/source/writerfilter/dmapper/DomainMapper.cxx
+++ b/sw/source/writerfilter/dmapper/DomainMapper.cxx
@@ -4637,7 +4637,8 @@ void DomainMapper::lcl_utext(const sal_Unicode *const 
data_, size_t len)
                 pContext->GetFootnote()->setLabel( sText );
                 // tdf#141548 don't lose footnote/endnote text of the run with 
uFtnEdnRef
                 // (i.e. when footnoteRef/endnoteRef is followed by some text 
in the same run)
-                m_pImpl->appendTextPortion( sText, pContext );
+                if (!IsRTFImport())
+                    m_pImpl->appendTextPortion( sText, pContext );
             }
             else if (m_pImpl->IsOpenFieldCommand() && 
!m_pImpl->IsForceGenericFields())
             {

Reply via email to