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 3f2d0414686a8f9a042413c47c4c8ffa5d61f436 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Mon May 27 09:41:18 2024 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Mon May 27 11:27:34 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. Change-Id: I9a21cbccb5a088314520c7ade55dbdf9966d1265 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168084 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins 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 548d8228063e..bb35d1c1025c 100644 --- a/sw/source/core/layout/ftnfrm.cxx +++ b/sw/source/core/layout/ftnfrm.cxx @@ -1626,7 +1626,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);