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

Word can have per-section endnotes, but if endnotes are collected at the
end of the section vs document end is a per-document setting.

The DOC import already handles this in wwSectionManager::InsertSection()
when it constructs an SwFormatEndAtTextEnd with FTNEND_ATTXTEND.

Fix the problem by doing the same in writerfilter: in case settings.xml
wants at-section-end endnotes, set EndnoteIsCollectAtTextEnd to true
when applying section properties.

The export side still needs doing.

Change-Id: Ibad9c2d62a2945ee42877c849482feee60a50178
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168148
Reviewed-by: Miklos Vajna <[email protected]>
Tested-by: Jenkins
diff --git a/sw/qa/writerfilter/dmapper/SettingsTable.cxx b/sw/qa/writerfilter/dmapper/SettingsTable.cxx
index 503b28d..ef94a60 100644
--- a/sw/qa/writerfilter/dmapper/SettingsTable.cxx
+++ b/sw/qa/writerfilter/dmapper/SettingsTable.cxx
@@ -11,6 +11,7 @@

#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/qa/XDumper.hpp>
#include <com/sun/star/text/XTextDocument.hpp>

#include <test/xmldocptr.hxx>

@@ -87,6 +88,27 @@ CPPUNIT_TEST_FIXTURE(Test, testAddVerticalFrameOffsetsRTF)
    // i.e. table top should be ~2748, but was less, leading to an overlap.
    CPPUNIT_ASSERT_GREATER(nFlyBottom, nTableTop);
}

CPPUNIT_TEST_FIXTURE(Test, testEndnoteAtSectionEnd)
{
    // Given a document with at-section-end endnotes enabled:
    loadFromFile(u"endnote-at-section-end.docx");

    // Go to the second paragraph, which is inside Word's second section:
    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
    uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(),
                                                                  uno::UNO_QUERY);
    uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
    xParaEnum->nextElement();
    uno::Reference<beans::XPropertySet> xPara(xParaEnum->nextElement(), uno::UNO_QUERY);
    uno::Reference<beans::XPropertySet> xSection;
    xPara->getPropertyValue("TextSection") >>= xSection;
    bool bEndnoteIsCollectAtTextEnd = false;
    xSection->getPropertyValue("EndnoteIsCollectAtTextEnd") >>= bEndnoteIsCollectAtTextEnd;
    // Without the accompanying fix in place, this test would have failed, endnotes were always at
    // document end.
    CPPUNIT_ASSERT(bEndnoteIsCollectAtTextEnd);
}
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/writerfilter/dmapper/data/endnote-at-section-end.docx b/sw/qa/writerfilter/dmapper/data/endnote-at-section-end.docx
new file mode 100644
index 0000000..cf61262
--- /dev/null
+++ b/sw/qa/writerfilter/dmapper/data/endnote-at-section-end.docx
Binary files differ
diff --git a/sw/source/writerfilter/dmapper/PropertyMap.cxx b/sw/source/writerfilter/dmapper/PropertyMap.cxx
index f52d377..02951c7 100644
--- a/sw/source/writerfilter/dmapper/PropertyMap.cxx
+++ b/sw/source/writerfilter/dmapper/PropertyMap.cxx
@@ -74,6 +74,8 @@
#include <frozen/bits/elsa_std.h>
#include <frozen/unordered_set.h>

#include <unoprnms.hxx>

using namespace com::sun::star;

namespace writerfilter::dmapper {
@@ -756,7 +758,7 @@ void SectionPropertyMap::DontBalanceTextColumns()
    }
}

void SectionPropertyMap::ApplySectionProperties( const uno::Reference< beans::XPropertySet >& xSection, DomainMapper_Impl& /*rDM_Impl*/ )
void SectionPropertyMap::ApplySectionProperties( const uno::Reference< beans::XPropertySet >& xSection, DomainMapper_Impl& rDM_Impl )
{
    try
    {
@@ -765,6 +767,11 @@ void SectionPropertyMap::ApplySectionProperties( const uno::Reference< beans::XP
            std::optional< PropertyMap::Property > pProp = getProperty( PROP_WRITING_MODE );
            if ( pProp )
                xSection->setPropertyValue( "WritingMode", pProp->second );

            if (rDM_Impl.GetSettingsTable()->GetEndnoteIsCollectAtSectionEnd())
            {
                xSection->setPropertyValue(UNO_NAME_ENDNOTE_IS_COLLECT_AT_TEXT_END, uno::Any(true));
            }
        }
    }
    catch ( uno::Exception& )
diff --git a/sw/source/writerfilter/dmapper/SettingsTable.cxx b/sw/source/writerfilter/dmapper/SettingsTable.cxx
index 4d6fe6b..57f6566 100644
--- a/sw/source/writerfilter/dmapper/SettingsTable.cxx
+++ b/sw/source/writerfilter/dmapper/SettingsTable.cxx
@@ -120,6 +120,8 @@ struct SettingsTable_Impl
    bool m_bGutterAtTop = false;
    bool m_bDoNotBreakWrappedTables = false;
    bool m_bAllowTextAfterFloatingTableBreak = false;
    /// Endnotes at section end, not at document end.
    bool m_bEndnoteIsCollectAtSectionEnd = false;

    SettingsTable_Impl() :
      m_nDefaultTabStop( 720 ) //default is 1/2 in
@@ -438,6 +440,12 @@ void SettingsTable::lcl_sprm(Sprm& rSprm)
    case NS_ooxml::LN_CT_Compat_doNotBreakWrappedTables:
        m_pImpl->m_bDoNotBreakWrappedTables = nIntValue != 0;
        break;
    case NS_ooxml::LN_CT_EdnProps_pos:
        if (nIntValue == NS_ooxml::LN_Value_ST_EdnPos_sectEnd)
        {
            m_pImpl->m_bEndnoteIsCollectAtSectionEnd = true;
        }
        break;
    default:
    {
#ifdef DBG_UTIL
@@ -804,6 +812,11 @@ bool SettingsTable::GetGutterAtTop() const { return m_pImpl->m_bGutterAtTop; }

bool SettingsTable::GetRecordChanges() const { return m_pImpl->m_bRecordChanges; }

bool SettingsTable::GetEndnoteIsCollectAtSectionEnd() const
{
    return m_pImpl->m_bEndnoteIsCollectAtSectionEnd;
}

}//namespace dmapper
} //namespace writerfilter

diff --git a/sw/source/writerfilter/dmapper/SettingsTable.hxx b/sw/source/writerfilter/dmapper/SettingsTable.hxx
index df7cb96..c71f4bd 100644
--- a/sw/source/writerfilter/dmapper/SettingsTable.hxx
+++ b/sw/source/writerfilter/dmapper/SettingsTable.hxx
@@ -102,6 +102,8 @@ public:

    bool GetRecordChanges() const;

    bool GetEndnoteIsCollectAtSectionEnd() const;

private:
    // Properties
    virtual void lcl_attribute(Id Name, Value& val) override;