sw/qa/extras/rtfexport/data/tdf165564.odt       |binary
 sw/qa/extras/rtfexport/rtfexport8.cxx           |   14 ++++++++++++++
 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, 29 insertions(+), 11 deletions(-)

New commits:
commit 90ce84a5dd371c804af19e97896a5e19a3ebf8ca
Author:     Oliver Specht <oliver.spe...@cib.de>
AuthorDate: Tue May 6 08:34:17 2025 +0200
Commit:     Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>
CommitDate: Thu May 8 11:38:05 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/+/184978
    Reviewed-by: Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>
    Tested-by: Jenkins

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 69717e0c5db2..17091665be20 100644
--- a/sw/qa/extras/rtfexport/rtfexport8.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport8.cxx
@@ -634,6 +634,20 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf161878)
     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 36027ee65ef7..66978890435b 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 98ea7864824d..899d6fdbf5dc 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -3692,7 +3692,7 @@ void DocxAttributeOutput::WriteCollectedRunProperties()
     }
 }
 
-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.
@@ -3731,6 +3731,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 a66ac7ed49f7..85ec8a4cff1b 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 f55efb729c73..646aabde12f2 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -446,10 +446,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)
@@ -3082,8 +3083,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 165223487da2..f743d44f147e 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 20f2f2542c32..a7818623f5d1 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -1193,7 +1193,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 );
 
@@ -1212,6 +1212,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 cad132763226..232d9be56bcf 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 ad32fb4fe2ef..a1018b9c65c1 100644
--- a/sw/source/writerfilter/dmapper/DomainMapper.cxx
+++ b/sw/source/writerfilter/dmapper/DomainMapper.cxx
@@ -4704,7 +4704,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