tdf#160984 sw continuous endnotes: DOCX: export of <w:endnotePr> pos == sectEnd

In case a DOCX file is re-exported to Word and it collected endnotes at
section end, this setting was lost on save.

The relevant markup seems to be <w:endnotePr> -> <w:pos
w:val="sectEnd"/>, though that's a per-section setting in Writer, and is
a per-doc setting in Word.

Fix the problem by doing it similar to
DocxExport::WriteDocumentBackgroundFill(), which takes the first page
style in a similar case; here we take the first section format.

This is meant to be good enough for the DOCX editing case, where we know
all sections have the same endnote position properties anyway.

Change-Id: I95508296e31c9be34196bdc0da2177101647abf9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168187
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <[email protected]>
diff --git a/sw/qa/filter/ww8/ww8.cxx b/sw/qa/filter/ww8/ww8.cxx
index 4cbbfe5..0705653 100644
--- a/sw/qa/filter/ww8/ww8.cxx
+++ b/sw/qa/filter/ww8/ww8.cxx
@@ -32,6 +32,7 @@
#include <tabfrm.hxx>
#include <cntfrm.hxx>
#include <colfrm.hxx>
#include <fmtftntx.hxx>

namespace
{
@@ -564,6 +565,35 @@ CPPUNIT_TEST_FIXTURE(Test, testNullPointerDereference)
    createSwDoc("null-pointer-dereference.doc");
    CPPUNIT_ASSERT_EQUAL(6, getPages());
}

CPPUNIT_TEST_FIXTURE(Test, testEndnotesAtSectEnd)
{
    // 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 DOCX:
    save("Office Open XML Text");

    // Then make sure the endnote position is section end:
    xmlDocUniquePtr pXmlDoc = parseExport("word/settings.xml");
    OUString aPos = getXPath(pXmlDoc, "/w:settings/w:endnotePr/w:pos"_ostr, "val"_ostr);
    // Without the accompanying fix in place, this test would have failed with:
    // - XPath '/w:settings/w:endnotePr/w:pos' number of nodes is incorrect
    // i.e. the default position was used: document end.
    CPPUNIT_ASSERT_EQUAL(OUString("sectEnd"), aPos);
}
}

CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 1532ecf..971f27d 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -127,6 +127,7 @@
#include <docsh.hxx>
#include <docary.hxx>
#include <fmtclbl.hxx>
#include <fmtftntx.hxx>
#include <IDocumentSettingAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <grfatr.hxx>
@@ -8780,6 +8781,18 @@ void DocxAttributeOutput::WriteFootnoteEndnotePr( ::sax_fastparser::FSHelperPtr 
    const SwEndNoteInfo& info, int listtag )
{
    fs->startElementNS(XML_w, tag);

    SwSectionFormats& rSections = m_rExport.m_rDoc.GetSections();
    if (!rSections.empty())
    {
        SwSectionFormat* pFormat = rSections[0];
        bool bEndnAtEnd = pFormat->GetEndAtTextEnd().IsAtEnd();
        if (bEndnAtEnd)
        {
            fs->singleElementNS(XML_w, XML_pos, FSNS(XML_w, XML_val), "sectEnd");
        }
    }

    OString aCustomFormat;
    OString fmt = lcl_ConvertNumberingType(info.m_aFormat.GetNumberingType(), nullptr, aCustomFormat);
    if (!fmt.isEmpty() && aCustomFormat.isEmpty())
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
index b1da698..063cb02b 100644
--- a/sw/source/filter/ww8/docxattributeoutput.hxx
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -1109,7 +1109,7 @@ public:
    void FootnotesEndnotes( bool bFootnotes );

    /// writes the footnotePr/endnotePr (depending on tag) section
    static void WriteFootnoteEndnotePr( ::sax_fastparser::FSHelperPtr const & fs, int tag, const SwEndNoteInfo& info, int listtag );
    void WriteFootnoteEndnotePr( ::sax_fastparser::FSHelperPtr const & fs, int tag, const SwEndNoteInfo& info, int listtag );

    bool HasPostitFields() const;
    enum class hasProperties { no, yes };
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index adff573..622cc7b 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -1226,11 +1226,11 @@ void DocxExport::WriteSettings()

    // Has Footnotes
    if( m_pAttrOutput->HasFootnotes())
        DocxAttributeOutput::WriteFootnoteEndnotePr( pFS, XML_footnotePr, m_rDoc.GetFootnoteInfo(), XML_footnote );
        m_pAttrOutput->WriteFootnoteEndnotePr( pFS, XML_footnotePr, m_rDoc.GetFootnoteInfo(), XML_footnote );

    // Has Endnotes
    if( m_pAttrOutput->HasEndnotes())
        DocxAttributeOutput::WriteFootnoteEndnotePr( pFS, XML_endnotePr, m_rDoc.GetEndNoteInfo(), XML_endnote );
        m_pAttrOutput->WriteFootnoteEndnotePr( pFS, XML_endnotePr, m_rDoc.GetEndNoteInfo(), XML_endnote );

    // Has themeFontLang information
    uno::Reference< beans::XPropertySet > xPropSet( pDocShell->GetBaseModel(), uno::UNO_QUERY_THROW );