From d273bcc4cf992dd05ac2b784bedff698f10cd5de Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Thu, 31 Aug 2017 11:51:53 +0200 Subject: tdf#112109 sw: split section frames inside table cells, ignore nested tables Commit f8a76d218305a56d15b82b9dac4fafa558872780 (tdf#108524 sw: split section frames inside table cells, non-split text frames, 2017-07-06) added support for moving text frame masters to a next page inside section-in-table frames. But the code in SwFrame::GetNextSctLeaf() responsible for this is not up to nested tables, so don't try to split sections in this case. Otherwise we'll end up with frames which are marked as "in table", but don't actually have have table frame parents, so we crash in SwFrame::IsFootnoteAllowed() which assumes being in a table means a table frame parent. Reviewed-on: https://gerrit.libreoffice.org/41748 Tested-by: Jenkins Reviewed-by: Miklos Vajna (cherry picked from commit 3d1bb76ebf5c51141018cfd76eccdb63472de8de) Conflicts: sw/qa/extras/uiwriter/uiwriter.cxx Change-Id: Iff19a4eda21a4dbfb9562dea7af8ec6767d47873 --- sw/qa/extras/uiwriter/data/tdf112109.fodt | 170 ++++++++++++++++++++++++++++++ sw/qa/extras/uiwriter/uiwriter.cxx | 10 ++ sw/source/core/layout/sectfrm.cxx | 34 ++++-- 3 files changed, 207 insertions(+), 7 deletions(-) create mode 100644 sw/qa/extras/uiwriter/data/tdf112109.fodt diff --git a/sw/qa/extras/uiwriter/data/tdf112109.fodt b/sw/qa/extras/uiwriter/data/tdf112109.fodt new file mode 100644 index 000000000000..507873fc9063 --- /dev/null +++ b/sw/qa/extras/uiwriter/data/tdf112109.fodt @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Table1.A1 + + + + + + + + + + + + + + Table2.A1, para 1 + Table2.A1, para 2 + + + + + Table2.B1 + + + + + Table2.C1 + + + + + Table2.D1 + + + + + + + Table2.A2 + + + + + Table2.B2 + + + + + Table2.C2 + + + + + Table2.D2 + + + + + + + + + + + + diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx index c23c0e825d27..c9753a8f712c 100644 --- a/sw/qa/extras/uiwriter/uiwriter.cxx +++ b/sw/qa/extras/uiwriter/uiwriter.cxx @@ -204,6 +204,7 @@ public: void testTableInSection(); void testTableInNestedSection(); void testTableInSectionInTable(); + void testSectionInTableInTable(); void testLinesInSectionInTable(); void testLinesMoveBackwardsInSectionInTable(); @@ -314,6 +315,7 @@ public: CPPUNIT_TEST(testTableInNestedSection); CPPUNIT_TEST(testLinesInSectionInTable); CPPUNIT_TEST(testTableInSectionInTable); + CPPUNIT_TEST(testSectionInTableInTable); CPPUNIT_TEST(testLinesMoveBackwardsInSectionInTable); CPPUNIT_TEST_SUITE_END(); @@ -3830,6 +3832,14 @@ void SwUiWriterTest::testTableInSectionInTable() createDoc("i95698.odt"); } +void SwUiWriterTest::testSectionInTableInTable() +{ + // The document has a nested table, containing a multi-line section at a + // page boundary. + // This crashed the layout later in SwFrame::IsFootnoteAllowed(). + createDoc("tdf112109.fodt"); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/core/layout/sectfrm.cxx b/sw/source/core/layout/sectfrm.cxx index dcf60c14df3c..8ae220e84272 100644 --- a/sw/source/core/layout/sectfrm.cxx +++ b/sw/source/core/layout/sectfrm.cxx @@ -590,7 +590,7 @@ namespace } /// Checks if pFrame is in a table, which itself is in a section. - bool IsInTableInSection(const SwFrame* pFrame) + bool IsFrameInTableInSection(const SwFrame* pFrame) { if (!pFrame->IsInTab()) return false; @@ -598,6 +598,26 @@ namespace // The frame is in a table, see if the table is in a section. return pFrame->FindTabFrame()->IsInSct(); } + + /// Checks if pFrame is in a table, which itself is in a table. + bool IsFrameInTableInTable(const SwFrame* pFrame) + { + if (!pFrame->IsInTab()) + return false; + + // The frame is in a table, see if the inner table is in an outer + // table. + bool bNested = false; + if (const SwFrame* pUpper = pFrame->FindTabFrame()->GetUpper()) + bNested = pUpper->IsInTab(); + return bNested; + } + + /// Checks if pFrame has a parent that can contain a split section frame. + bool CanContainSplitSection(const SwFrame* pFrame) + { + return !IsFrameInTableInSection(pFrame) && !IsFrameInTableInTable(pFrame); + } } void SwSectionFrame::MoveContentAndDelete( SwSectionFrame* pDel, bool bSave ) @@ -1452,7 +1472,7 @@ SwLayoutFrame *SwFrame::GetNextSctLeaf( MakePageType eMakePage ) return static_cast(static_cast(GetUpper()->GetUpper()->GetNext())->Lower()); // Inside a table-in-section, or sections of headers/footers, there can be only // one column shift be made, one of the above shortcuts should have applied! - if( IsInTableInSection(GetUpper()) || FindFooterOrHeader() ) + if( !CanContainSplitSection(GetUpper()) || FindFooterOrHeader() ) return nullptr; SwSectionFrame *pSect = FindSctFrame(); @@ -1515,7 +1535,7 @@ SwLayoutFrame *SwFrame::GetNextSctLeaf( MakePageType eMakePage ) SwLayoutFrame *pLayLeaf; SwLayoutFrame* pCellLeaf = nullptr; - if (IsInTab() && !IsInTableInSection(this)) + if (IsInTab() && CanContainSplitSection(this)) { // We are in a table (which is itself not in a section), see if there // is a follow cell frame created already. @@ -1535,7 +1555,7 @@ SwLayoutFrame *SwFrame::GetNextSctLeaf( MakePageType eMakePage ) SwContentFrame* pTmpCnt = static_cast(this)->FindLastContent(); pLayLeaf = pTmpCnt ? pTmpCnt->GetUpper() : nullptr; } - else if (pCellLeaf && !IsInTableInSection(this)) + else if (pCellLeaf && CanContainSplitSection(this)) { // This frame is in a table-not-in-section, its follow should be // inserted under the follow of the frame's cell. @@ -1727,7 +1747,7 @@ SwLayoutFrame *SwFrame::GetPrevSctLeaf( MakePageType ) SwFlowFrame::SetMoveBwdJump( true ); SwSectionFrame *pSect = FindSctFrame(); - if (!pCol && pSect && IsInTab() && !IsInTableInSection(this)) + if (!pCol && pSect && IsInTab() && CanContainSplitSection(this)) { // We don't have a previous section yet, and we're in a // section-in-table. @@ -2174,8 +2194,8 @@ bool SwSectionFrame::MoveAllowed( const SwFrame* pFrame) const return false; // Now it has to be examined whether there is a layout sheet wherein // a section Follow can be created - if( IsInTableInSection(this) || ( !IsInDocBody() && FindFooterOrHeader() ) ) - return false; // It doesn't work in table-in-sections/headers/footers + if( !CanContainSplitSection(this) || ( !IsInDocBody() && FindFooterOrHeader() ) ) + return false; // It doesn't work in table-in-sections/nested tables/headers/footers if( IsInFly() ) // In column based or chained frames return nullptr != const_cast(static_cast(GetUpper()))->GetNextLeaf( MAKEPAGE_NONE ); return true; -- cgit v1.2.3