sw/qa/extras/rtfexport/rtfexport8.cxx       |   31 +++++++++++++++
 sw/source/filter/ww8/rtfattributeoutput.cxx |   18 +++++++++
 sw/source/filter/ww8/rtfexport.cxx          |   55 ++++++++++++++++++++++++++--
 3 files changed, 102 insertions(+), 2 deletions(-)

New commits:
commit 937bdd08ee8ff9ce90db06fd463719ba8e9da996
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Jun 5 12:13:14 2024 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Jun 5 14:49:36 2024 +0200

    tdf#161417 RTF export: handle endnotes at section ends
    
    Similar to commit 566c7017a84e3d573de85a6d986b81d3f59de0fa (tdf#160984
    sw continuous endnotes: DOCX: export of <w:endnotePr> pos == sectEnd,
    2024-05-29), but this is RTF, not DOCX.
    
    Additional complexity is that it's not enough to just write endnotes
    (sect end) or enddoc (doc end) to export the position, also et and
    ndnhere needs writing, otherwise Word ignores this.
    
    Last bit is to ignore section formats which are not nullptr but are -1,
    ignore these in RtfAttributeOutput::SectionBreak(), similar to how
    DocxAttributeOutput::SectionBreak() does the same already.
    
    Change-Id: I2327c979d5af402eb15523d97149f6409fcf4adf
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168468
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/qa/extras/rtfexport/rtfexport8.cxx 
b/sw/qa/extras/rtfexport/rtfexport8.cxx
index 33219edcfe9d..347b39c68563 100644
--- a/sw/qa/extras/rtfexport/rtfexport8.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport8.cxx
@@ -39,6 +39,7 @@
 #include <frmmgr.hxx>
 #include <formatflysplit.hxx>
 #include <fmtwrapinfluenceonobjpos.hxx>
+#include <fmtftntx.hxx>
 
 using namespace css;
 
@@ -173,6 +174,36 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf158586_lostFrame)
     verify();
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testEndnotesAtSectEndRTF)
+{
+    // Given a document, endnotes at collected at section end:
+    createSwDoc();
+    {
+        SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
+        pWrtShell->SplitNode();
+        pWrtShell->Up(/*bSelect=*/false);
+        pWrtShell->Insert("x");
+        pWrtShell->Left(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, 
/*bBasicCall=*/false);
+        SwSectionData aSection(SectionType::Content, 
pWrtShell->GetUniqueSectionName());
+        pWrtShell->StartAction();
+        SfxItemSetFixed<RES_FTN_AT_TXTEND, RES_FRAMEDIR> 
aSet(pWrtShell->GetAttrPool());
+        aSet.Put(SwFormatEndAtTextEnd(FTNEND_ATTXTEND));
+        pWrtShell->InsertSection(aSection, &aSet);
+        pWrtShell->EndAction();
+        pWrtShell->InsertFootnote(OUString(), /*bEndNote=*/true);
+    }
+
+    // When saving to DOC:
+    saveAndReload(mpFilter);
+
+    // Then make sure the endnote position is section end:
+    SwDoc* pDoc = getSwDoc();
+    SwSectionFormats& rSections = pDoc->GetSections();
+    SwSectionFormat* pFormat = rSections[0];
+    // Without the accompanying fix in place, this test would have failed, 
endnotes were at doc end.
+    CPPUNIT_ASSERT(pFormat->GetEndAtTextEnd().IsAtEnd());
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testTdf158983)
 {
     auto verify = [this]() {
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx 
b/sw/source/filter/ww8/rtfattributeoutput.cxx
index 2c9f92aaa245..8721e2f0d99b 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -97,6 +97,7 @@
 #include "rtfexport.hxx"
 #include <IDocumentDeviceAccess.hxx>
 #include <sfx2/printer.hxx>
+#include <fmtftntx.hxx>
 
 using namespace ::com::sun::star;
 using namespace sw::util;
@@ -1367,6 +1368,23 @@ void RtfAttributeOutput::SectionBreak(sal_uInt8 nC, bool 
/*bBreakAfter*/,
                 m_rExport.SectionProperties(*pSectionInfo);
             break;
     }
+
+    // Endnotes included in the section:
+    if (!pSectionInfo)
+    {
+        return;
+    }
+    const SwSectionFormat* pSectionFormat = pSectionInfo->pSectionFormat;
+    if (!pSectionFormat || pSectionFormat == 
reinterpret_cast<SwSectionFormat*>(sal_IntPtr(-1)))
+    {
+        // MSWordExportBase::WriteText() can set the section format to -1, 
ignore.
+        return;
+    }
+    if (!pSectionFormat->GetEndAtTextEnd().IsAtEnd())
+    {
+        return;
+    }
+    m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_ENDNHERE);
 }
 
 void RtfAttributeOutput::StartSection()
diff --git a/sw/source/filter/ww8/rtfexport.cxx 
b/sw/source/filter/ww8/rtfexport.cxx
index 8acd96461ac6..88a3086c6dfc 100644
--- a/sw/source/filter/ww8/rtfexport.cxx
+++ b/sw/source/filter/ww8/rtfexport.cxx
@@ -70,6 +70,9 @@
 #include <frmatr.hxx>
 #include <swtable.hxx>
 #include <IMark.hxx>
+#include <fmtftntx.hxx>
+#include <ftnidx.hxx>
+#include <txtftn.hxx>
 
 using namespace ::com::sun::star;
 
@@ -798,7 +801,8 @@ ErrCode RtfExport::ExportDocument_Impl()
     // enable it on a per-section basis. OTOH don't always enable it as it
     // breaks moving of drawings - so write it only in case there is really a
     // protected section in the document.
-    for (auto const& pSectionFormat : m_rDoc.GetSections())
+    SwSectionFormats& rSections = m_rDoc.GetSections();
+    for (auto const& pSectionFormat : rSections)
     {
         if (!pSectionFormat->IsInUndo() && 
pSectionFormat->GetProtect().IsContentProtected())
         {
@@ -968,8 +972,55 @@ ErrCode RtfExport::ExportDocument_Impl()
 
         const SwEndNoteInfo& rEndNoteInfo = m_rDoc.GetEndNoteInfo();
 
+        if (!rSections.empty())
+        {
+            SwSectionFormat* pFormat = rSections[0];
+            bool bEndnAtEnd = pFormat->GetEndAtTextEnd().IsAtEnd();
+            if (bEndnAtEnd)
+            {
+                // Endnotes at end of section.
+                Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_AENDNOTES);
+            }
+            else
+            {
+                // Endnotes at end of document.
+                Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_AENDDOC);
+            }
+        }
+
+        // Types of notes that are present in the document:
+        Strm().WriteOString(OOO_STRING_SVTOOLS_RTF_FET);
+        SwFootnoteIdxs& rFootnotes = m_rDoc.GetFootnoteIdxs();
+        bool bHasFootnote = false;
+        bool bHasEndnote = false;
+        for (const auto& pFootnote : rFootnotes)
+        {
+            if (pFootnote->GetFootnote().IsEndNote())
+            {
+                bHasEndnote = true;
+            }
+            else
+            {
+                bHasFootnote = true;
+            }
+
+            if (bHasFootnote && bHasEndnote)
+            {
+                break;
+            }
+        }
+        if (bHasFootnote && bHasEndnote)
+        {
+            // Both footnotes and endnotes.
+            Strm().WriteOString("2");
+        }
+        else if (bHasEndnote)
+        {
+            // Endnotes only.
+            Strm().WriteOString("1");
+        }
+
         Strm()
-            .WriteOString(OOO_STRING_SVTOOLS_RTF_AENDDOC)
             .WriteOString(OOO_STRING_SVTOOLS_RTF_AFTNRSTCONT)
             .WriteOString(OOO_STRING_SVTOOLS_RTF_AFTNSTART);
         Strm().WriteNumberAsString(rEndNoteInfo.m_nFootnoteOffset + 1);

Reply via email to