tdf#161083 sw continuous endnotes: fix layout with a section at doc end

Open the bugdoc, notice warnings like:

warn:legacy.osl:15059:15059:sw/source/core/layout/wsfrm.cxx:910: Frame tree is inconsistent.

Which means we try to insert the new section frame under body frame, but
the insert point is behind a frame which is not a direct child of the
body frame.

This went wrong in commit 6885dcd7ec7b82a946d8344bfc27a3e88eecc44a
(tdf#160984 sw continuous endnotes: switch to a section-based layout,
2024-05-14), where I didn't consider the case of having a continuous
section break at the Word doc end, which maps to a section frame before
the section frame of the endnotes in Writer.

Fix the problem by walking up the parent chain till we find the last
direct child of the body frame, which is typically not required, except
when having one or more (nested) section frames at the end of the
document.

Interestingly tdf#143456 had the same problem, which was the bugdoc to
trigger the revert of the old continuous endnotes code for DOCX in
eeda1b35a6e87d5349545464da33d997c52f15e3 (Revert "tdf#58521 DOCX import:
enable ContinuousEndnotes compat flag", 2021-08-10).

Change-Id: I664672b91087217008a42120e8201c39e2a0a423
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167691
Tested-by: Jenkins
Reviewed-by: Miklos Vajna <[email protected]>
diff --git a/sw/qa/core/layout/data/inline-endnote-and-section.odt b/sw/qa/core/layout/data/inline-endnote-and-section.odt
new file mode 100644
index 0000000..4518904f
--- /dev/null
+++ b/sw/qa/core/layout/data/inline-endnote-and-section.odt
Binary files differ
diff --git a/sw/qa/core/layout/ftnfrm.cxx b/sw/qa/core/layout/ftnfrm.cxx
index 71fd3fd..1cf3180 100644
--- a/sw/qa/core/layout/ftnfrm.cxx
+++ b/sw/qa/core/layout/ftnfrm.cxx
@@ -84,4 +84,22 @@ CPPUNIT_TEST_FIXTURE(Test, testInlineEndnoteAndFootnote)
    CPPUNIT_ASSERT_LESS(nFootnoteTop, nEndnoteTop);
}

CPPUNIT_TEST_FIXTURE(Test, testInlineEndnoteAndSection)
{
    // Given a document ending with a section, ContinuousEndnotes is true:
    createSwDoc("inline-endnote-and-section.odt");

    // When laying out that document:
    xmlDocUniquePtr pXmlDoc = parseLayoutDump();

    // Then make sure the endnote section is after the section at the end of the document, not
    // inside it:
    int nToplevelSections = countXPathNodes(pXmlDoc, "/root/page/body/section"_ostr);
    // Without the accompanying fix in place, this test would have failed with:
    // - Expected: 2
    // - Actual  : 1
    // and we even crashed on shutdown.
    CPPUNIT_ASSERT_EQUAL(2, nToplevelSections);
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx
index e03519e..b7851a1 100644
--- a/sw/source/core/layout/ftnfrm.cxx
+++ b/sw/source/core/layout/ftnfrm.cxx
@@ -1585,7 +1585,21 @@ void SwFootnoteBossFrame::AppendFootnote( SwContentFrame *pRef, SwTextFootnote *
            {
                SwSection* pSwSection = pDoc->GetEndNoteInfo().GetSwSection(*pDoc);
                pEndnoteSection = new SwSectionFrame(*pSwSection, pPage);
                pEndnoteSection->InsertBehind(pPage->FindBodyCont(), pPage->FindLastBodyContent());
                SwLayoutFrame* pParent = pPage->FindBodyCont();
                SwFrame* pBefore = pPage->FindLastBodyContent();
                while (pBefore)
                {
                    // Check if the last content frame is directly under the body frame or there is
                    // something in-between, e.g. a section frame.
                    if (pBefore->GetUpper() == pParent)
                    {
                        break;
                    }

                    // If so, insert behind the parent of the content frame, not inside the parent.
                    pBefore = pBefore->GetUpper();
                }
                pEndnoteSection->InsertBehind(pParent, pBefore);
                pEndnoteSection->Init();
                pEndnoteSection->SetEndNoteSection(true);
            }