sw/qa/core/layout/data/inline-endnote-section-delete.docx |binary sw/qa/core/layout/ftnfrm.cxx | 31 ++++++++++++++ sw/source/core/layout/ftnfrm.cxx | 4 + 3 files changed, 34 insertions(+), 1 deletion(-)
New commits: commit ba0f1432e2162d32103e20d2030cf79b3dd4e2f7 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon May 27 09:41:18 2024 +0200 Commit: Caolán McNamara <caolan.mcnam...@collabora.com> CommitDate: Mon May 27 14:31:05 2024 +0200 tdf#160984 sw continuous endnotes: fix crash on loading forum-mso-en-7731.docx Regression from commit 1ae5ea3f78cca11ba18f2dd1a06f875263336a3b (tdf#160984 sw continuous endnotes: enable DOCX import, 2024-05-21), the bugdoc crashed in SwSectionFrame::GetEndSectFormat_(). What seems to happen is that the first endnote is added to page 1, then more content is inserted, so the endnote is moved to page 2, which leaves an empty endnote section on page 1, which is marked for deletion in SwSectionFrame::MakeAll(), and will be deleted in SwRootFrame::DeleteEmptySct_(). At some point (after marking for deletion, before deletion) SwFootnoteBossFrame::AppendFootnote() tries to find the first endnote section in the layout, and finds this section, but it crashes because there is no SwSection attached to it, as marking for deletion in SwSectionFrame::DelEmpty() clears that. Fix the problem by ignoring to-be-deleted sections in SwFootnoteBossFrame::AppendFootnote(): this way a new, usable section will be created and the to-be-deleted section go away as the layout finishes. An alternative would be to check for SwSectionFrame::GetSection() earlier, as we iterate on pages (hoping that this way we find a later page that has a not-dead endnote section), but that leads to 6 pages instead of 4 pages for the bugdoc, so don't go that way. (cherry picked from commit 3f2d0414686a8f9a042413c47c4c8ffa5d61f436) Change-Id: I9a21cbccb5a088314520c7ade55dbdf9966d1265 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168099 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> diff --git a/sw/qa/core/layout/data/inline-endnote-section-delete.docx b/sw/qa/core/layout/data/inline-endnote-section-delete.docx new file mode 100644 index 000000000000..bf3d3e60d890 Binary files /dev/null and b/sw/qa/core/layout/data/inline-endnote-section-delete.docx differ diff --git a/sw/qa/core/layout/ftnfrm.cxx b/sw/qa/core/layout/ftnfrm.cxx index a7640e26ca9a..98387be6a983 100644 --- a/sw/qa/core/layout/ftnfrm.cxx +++ b/sw/qa/core/layout/ftnfrm.cxx @@ -17,6 +17,8 @@ #include <rootfrm.hxx> #include <view.hxx> #include <wrtsh.hxx> +#include <bodyfrm.hxx> +#include <sectfrm.hxx> /// Covers sw/source/core/layout/ftnfrm.cxx fixes. class Test : public SwModelTestBase @@ -122,4 +124,33 @@ CPPUNIT_TEST_FIXTURE(Test, testInlineEndnotePosition) CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(269), nEndnoteContTopMargin); } +CPPUNIT_TEST_FIXTURE(Test, testInlineEndnoteSectionDelete) +{ + // Given a document, ContinuousEndnotes is true, 3 pages, endnodes start on page 2: + // When laying out that document: + createSwDoc("inline-endnote-section-delete.docx"); + + // First page: just body text: + SwDoc* pDoc = getSwDoc(); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + auto pPage = pLayout->Lower()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage->GetLower()->IsBodyFrame()); + auto pBodyFrame = static_cast<SwBodyFrame*>(pPage->GetLower()); + CPPUNIT_ASSERT(!pBodyFrame->GetLastLower()->IsSctFrame()); + // Second page: ends with endnotes: + pPage = pPage->GetNext()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage->GetLower()->IsBodyFrame()); + pBodyFrame = static_cast<SwBodyFrame*>(pPage->GetLower()); + CPPUNIT_ASSERT(pBodyFrame->GetLastLower()->IsSctFrame()); + auto pSection = static_cast<SwSectionFrame*>(pBodyFrame->GetLastLower()); + CPPUNIT_ASSERT(pSection->IsEndNoteSection()); + // Third page: just endnotes: + pPage = pPage->GetNext()->DynCastPageFrame(); + CPPUNIT_ASSERT(pPage->GetLower()->IsBodyFrame()); + pBodyFrame = static_cast<SwBodyFrame*>(pPage->GetLower()); + CPPUNIT_ASSERT(pBodyFrame->GetLower()->IsSctFrame()); + pSection = static_cast<SwSectionFrame*>(pBodyFrame->GetLower()); + CPPUNIT_ASSERT(pSection->IsEndNoteSection()); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx index 46312f9f4e89..1c6b221cf511 100644 --- a/sw/source/core/layout/ftnfrm.cxx +++ b/sw/source/core/layout/ftnfrm.cxx @@ -1601,7 +1601,9 @@ void SwFootnoteBossFrame::AppendFootnote( SwContentFrame *pRef, SwTextFootnote * pEndnoteSection = pPage->GetEndNoteSection(); } // If there are no endnotes sections yet, create one at the end of the document. - if (!pEndnoteSection) + // Ignore sections which are already marked for deletion, they don't have an SwSection + // anymore, so not usable for us. + if (!pEndnoteSection || !pEndnoteSection->GetSection()) { SwSection* pSwSection = pDoc->GetEndNoteInfo().GetSwSection(*pDoc); pEndnoteSection = new SwSectionFrame(*pSwSection, pPage);