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);