From 91b2239783dc716bd71ce7962bfd7e341dfe4175 Mon Sep 17 00:00:00 2001 From: László Németh Date: Tue, 7 May 2019 17:22:41 +0200 Subject: tdf#116501 fix freezing at embedded text tables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit by disabling their in-row splitting using loop control. Change-Id: Ibd93213fa0ce45458ce188de20da982e4abc17c5 Reviewed-on: https://gerrit.libreoffice.org/71920 Tested-by: Jenkins Reviewed-by: László Németh --- sw/qa/extras/layout/data/tdf116501.odt | Bin 0 -> 55357 bytes sw/qa/extras/layout/layout.cxx | 6 ++++++ sw/source/core/inc/layact.hxx | 5 +++++ sw/source/core/inc/tabfrm.hxx | 10 ++++++++++ sw/source/core/layout/layact.cxx | 21 ++++++++++++++++++++- sw/source/core/layout/tabfrm.cxx | 4 +++- 6 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 sw/qa/extras/layout/data/tdf116501.odt (limited to 'sw') diff --git a/sw/qa/extras/layout/data/tdf116501.odt b/sw/qa/extras/layout/data/tdf116501.odt new file mode 100644 index 000000000000..7d38b8be53c2 Binary files /dev/null and b/sw/qa/extras/layout/data/tdf116501.odt differ diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx index 381f9c0087b6..bb3aea800d0e 100644 --- a/sw/qa/extras/layout/layout.cxx +++ b/sw/qa/extras/layout/layout.cxx @@ -2965,6 +2965,12 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf123651) assertXPath(pXmlDoc, "//SwAnchoredDrawObject/bounds", "top", "7639"); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf116501) +{ + //just care it doesn't freeze + createDoc("tdf116501.odt"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/inc/layact.hxx b/sw/source/core/inc/layact.hxx index 8f5960837031..1253233778e6 100644 --- a/sw/source/core/inc/layact.hxx +++ b/sw/source/core/inc/layact.hxx @@ -95,6 +95,11 @@ class SwLayAction // OD 14.04.2003 #106346# - new flag for content formatting on interrupt. bool mbFormatContentOnInterrupt; + // for loop control by disabling in-row splitting within embedded tables + const SwPageFrame *m_pCurPage; + sal_uInt16 m_nTabLevel; // embedding level + sal_uInt32 m_nCallCount; // calling FormatLayoutTab on the same page + void PaintContent( const SwContentFrame *, const SwPageFrame *, const SwRect &rOldRect, long nOldBottom ); bool PaintWithoutFlys( const SwRect &, const SwContentFrame *, diff --git a/sw/source/core/inc/tabfrm.hxx b/sw/source/core/inc/tabfrm.hxx index 176396c6667a..cc57d46d8492 100644 --- a/sw/source/core/inc/tabfrm.hxx +++ b/sw/source/core/inc/tabfrm.hxx @@ -84,6 +84,8 @@ class SwTabFrame: public SwLayoutFrame, public SwFlowFrame bool m_bInRecalcLowerRow : 1; + bool m_bSplitRowDisabled : 1; // loop control + /** * Split() splits the Frame at the specified position: a Follow is * created and constructed and inserted directly after this. @@ -173,6 +175,14 @@ public: { m_bInRecalcLowerRow = bNew; } + bool IsSplitRowDisabled() const + { + return m_bSplitRowDisabled; + } + void SetSplitRowDisabled() + { + m_bSplitRowDisabled = true; + } // #i26945# bool IsConsiderObjsForMinCellHeight() const diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx index 8e02e75e9362..c58261786a6b 100644 --- a/sw/source/core/layout/layact.cxx +++ b/sw/source/core/layout/layact.cxx @@ -258,7 +258,10 @@ SwLayAction::SwLayAction( SwRootFrame *pRt, SwViewShellImp *pI ) : m_nStartTicks( std::clock() ), m_nInputType( VclInputFlags::NONE ), m_nEndPage( USHRT_MAX ), - m_nCheckPageNum( USHRT_MAX ) + m_nCheckPageNum( USHRT_MAX ), + m_pCurPage( nullptr ), + m_nTabLevel( 0 ), + m_nCallCount( 0 ) { m_bPaintExtraData = ::IsExtraData( m_pImp->GetShell()->GetDoc() ); m_bPaint = m_bComplete = m_bWaitAllowed = m_bCheckPages = true; @@ -286,6 +289,7 @@ void SwLayAction::Reset() m_bPaint = m_bComplete = m_bWaitAllowed = m_bCheckPages = true; m_bInput = m_bAgain = m_bNextCycle = m_bCalcLayout = m_bIdle = m_bReschedule = m_bUpdateExpFields = m_bBrowseActionStop = false; + m_pCurPage = nullptr; } bool SwLayAction::RemoveEmptyBrowserPages() @@ -1172,6 +1176,12 @@ bool SwLayAction::IsShortCut( SwPageFrame *&prPage ) // introduce support for vertical layout bool SwLayAction::FormatLayout( OutputDevice *pRenderContext, SwLayoutFrame *pLay, bool bAddRect ) { + // save page for loop control + if( pLay->IsPageFrame() && static_cast(pLay) != m_pCurPage ) + { + m_nCallCount = 0; + m_pCurPage = static_cast(pLay); + } OSL_ENSURE( !IsAgain(), "Attention to the invalid page." ); if ( IsAgain() ) return false; @@ -1351,7 +1361,16 @@ bool SwLayAction::FormatLayout( OutputDevice *pRenderContext, SwLayoutFrame *pLa if ( pLow->IsLayoutFrame() ) { if ( pLow->IsTabFrame() ) + { + // loop control for embedded tables + if ( m_nTabLevel > 0 && ++m_nCallCount > 50 ) { + static_cast(pLow)->SetSplitRowDisabled(); + } + + ++m_nTabLevel; bTabChanged |= FormatLayoutTab( static_cast(pLow), bAddRect ); + --m_nTabLevel; + } // Skip the ones already registered for deletion else if( !pLow->IsSctFrame() || static_cast(pLow)->GetSection() ) bChanged |= FormatLayout( pRenderContext, static_cast(pLow), bAddRect ); diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx index 060a8dcf6de3..a9667a964308 100644 --- a/sw/source/core/layout/tabfrm.cxx +++ b/sw/source/core/layout/tabfrm.cxx @@ -80,6 +80,7 @@ SwTabFrame::SwTabFrame( SwTable &rTab, SwFrame* pSib ) , m_bConsiderObjsForMinCellHeight(true) , m_bObjsDoesFit(true) , m_bInRecalcLowerRow(false) + , m_bSplitRowDisabled(false) { mbFixSize = false; //Don't fall for import filter again. mnFrameType = SwFrameType::Tab; @@ -118,6 +119,7 @@ SwTabFrame::SwTabFrame( SwTabFrame &rTab ) , m_bConsiderObjsForMinCellHeight(true) , m_bObjsDoesFit(true) , m_bInRecalcLowerRow(false) + , m_bSplitRowDisabled(false) { mbFixSize = false; //Don't fall for import filter again. mnFrameType = SwFrameType::Tab; @@ -1018,7 +1020,7 @@ bool SwTabFrame::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowK // table, or it will be set to false under certain // conditions that are not suitable for splitting // the row. - bool bSplitRowAllowed = pRow->IsRowSplitAllowed(); + bool bSplitRowAllowed = pRow->IsRowSplitAllowed() && !IsSplitRowDisabled(); // #i29438# // #i26945# - Floating screen objects no longer forbid -- cgit