diff options
Diffstat (limited to 'sw/source/core/layout/tabfrm.cxx')
-rw-r--r-- | sw/source/core/layout/tabfrm.cxx | 87 |
1 files changed, 68 insertions, 19 deletions
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx index a3449bfaad1e..07857266045e 100644 --- a/sw/source/core/layout/tabfrm.cxx +++ b/sw/source/core/layout/tabfrm.cxx @@ -23,6 +23,7 @@ #include <viewimp.hxx> #include <fesh.hxx> #include <swtable.hxx> +#include <deletelistener.hxx> #include <dflyobj.hxx> #include <anchoreddrawobject.hxx> #include <fmtanchr.hxx> @@ -58,6 +59,7 @@ #include <DocumentSettingManager.hxx> #include <docary.hxx> #include <o3tl/make_unique.hxx> +#include <boost/optional.hpp> using namespace ::com::sun::star; @@ -1305,13 +1307,30 @@ bool SwTabFrame::Split( const SwTwips nCutPos, bool bTryToSplit, bool bTableRowK return bRet; } +namespace +{ + bool CanDeleteFollow(SwTabFrame *pFoll) + { + if (pFoll->IsJoinLocked()) + return false; + + if (pFoll->IsDeleteForbidden()) + { + SAL_WARN("sw.layout", "Delete Forbidden"); + return false; + } + + return true; + } +} + bool SwTabFrame::Join() { OSL_ENSURE( !HasFollowFlowLine(), "Joining follow flow line" ); SwTabFrame *pFoll = GetFollow(); - if (pFoll && !pFoll->IsJoinLocked()) + if (pFoll && CanDeleteFollow(pFoll)) { SwRectFnSet aRectFnSet(this); pFoll->Cut(); //Cut out first to avoid unnecessary notifications. @@ -1540,6 +1559,8 @@ static bool lcl_InnerCalcLayout( SwFrame *pFrame, if ( pFrame->IsLayoutFrame() && ( !_bOnlyRowsAndCells || pFrame->IsRowFrame() || pFrame->IsCellFrame() ) ) { + SwFrameDeleteGuard aDeleteGuard(pFrame); + // #130744# An invalid locked table frame will // not be calculated => It will not become valid => // Loop in lcl_RecalcRow(). Therefore we do not consider them for bRet. @@ -1770,6 +1791,14 @@ namespace { return bRet; } } + +// extern because static can't be friend +void FriendHackInvalidateRowFrame(SwFrameAreaDefinition & rRowFrame) +{ + // hilariously static_cast<SwTabFrame*>(GetLower()) would not require friend declaration, but it's UB... + rRowFrame.setFrameAreaPositionValid(false); +} + void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) { if ( IsJoinLocked() || StackHack::IsLocked() || StackHack::Count() > 50 ) @@ -1799,7 +1828,7 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) // is not locked. Otherwise, join will not be performed and this loop // will be endless. while ( GetNext() && GetNext() == GetFollow() && - !GetFollow()->IsJoinLocked() + CanDeleteFollow(GetFollow()) ) { if ( HasFollowFlowLine() ) @@ -1948,8 +1977,6 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) pAccess.reset(); m_bCalcLowers |= pLayout->Resize( pLayout->GetBrowseWidthByTabFrame( *this ) ); - pAccess = o3tl::make_unique<SwBorderAttrAccess>(SwFrame::GetCache(), this); - pAttrs = pAccess->Get(); } setFramePrintAreaValid(false); @@ -1961,6 +1988,10 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) { m_bCalcLowers = true; } + if (GetLower()) + { // it's possible that the rows already have valid pos - but it is surely wrong if the table's pos changed! + FriendHackInvalidateRowFrame(*GetLower()); + } } //We need to know the height of the first row, because the master needs @@ -1978,6 +2009,12 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) const long nOldPrtWidth = aRectFnSet.GetWidth(getFramePrintArea()); const long nOldFrameWidth = aRectFnSet.GetWidth(getFrameArea()); const Point aOldPrtPos = aRectFnSet.GetPos(getFramePrintArea()); + + if (!pAccess) + { + pAccess = o3tl::make_unique<SwBorderAttrAccess>(SwFrame::GetCache(), this); + pAttrs = pAccess->Get(); + } Format( getRootFrame()->GetCurrShell()->GetOut(), pAttrs ); SwHTMLTableLayout *pLayout = GetTable()->GetHTMLTableLayout(); @@ -1988,8 +2025,6 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) pAccess.reset(); m_bCalcLowers |= pLayout->Resize( pLayout->GetBrowseWidthByTabFrame( *this ) ); - pAccess = o3tl::make_unique<SwBorderAttrAccess>(SwFrame::GetCache(), this); - pAttrs = pAccess->Get(); } if ( aOldPrtPos != aRectFnSet.GetPos(getFramePrintArea()) ) aNotify.SetLowersComplete( false ); @@ -2017,12 +2052,18 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) } SwFootnoteBossFrame *pOldBoss = bFootnotesInDoc ? FindFootnoteBossFrame( true ) : nullptr; bool bReformat; + boost::optional<SfxDeleteListener> oDeleteListener; + if (pOldBoss) + oDeleteListener.emplace(*pOldBoss); + SwFrameDeleteGuard g(this); if ( MoveBwd( bReformat ) ) { + SAL_WARN_IF(oDeleteListener && oDeleteListener->WasDeleted(), "sw.layout", "SwFootnoteBossFrame unexpectedly deleted"); + aRectFnSet.Refresh(this); bMovedBwd = true; aNotify.SetLowersComplete( false ); - if ( bFootnotesInDoc ) + if (bFootnotesInDoc && !oDeleteListener->WasDeleted()) MoveLowerFootnotes( nullptr, pOldBoss, nullptr, true ); if ( bReformat || bKeep ) { @@ -2037,15 +2078,22 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) pAccess.reset(); m_bCalcLowers |= pHTMLLayout->Resize( pHTMLLayout->GetBrowseWidthByTabFrame( *this ) ); + } + + setFramePrintAreaValid(false); + if (!pAccess) + { pAccess = o3tl::make_unique<SwBorderAttrAccess>(SwFrame::GetCache(), this); pAttrs = pAccess->Get(); } - - setFramePrintAreaValid(false); Format( getRootFrame()->GetCurrShell()->GetOut(), pAttrs ); } + + pAccess.reset(); + lcl_RecalcTable( *this, nullptr, aNotify ); + m_bLowersFormatted = true; if ( bKeep && KEEPTAB ) { @@ -2209,11 +2257,18 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) // 6. There is no section change behind the table (see IsKeep) // 7. The last table row wants to keep with its next. const SwRowFrame* pLastRow = static_cast<const SwRowFrame*>(GetLastLower()); - if (pLastRow - && IsKeep(pAttrs->GetAttrSet().GetKeep(), GetBreakItem(), true) - && pLastRow->ShouldRowKeepWithNext()) + if (pLastRow) { - bFormat = true; + if (!pAccess) + { + pAccess = o3tl::make_unique<SwBorderAttrAccess>(SwFrame::GetCache(), this); + pAttrs = pAccess->Get(); + } + if (IsKeep(pAttrs->GetAttrSet().GetKeep(), GetBreakItem(), true) + && pLastRow->ShouldRowKeepWithNext()) + { + bFormat = true; + } } } @@ -2227,9 +2282,6 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) // is found, get its first content. const SwFrame* pTmpNxt = sw_FormatNextContentForKeep( this ); - pAccess = o3tl::make_unique<SwBorderAttrAccess>(SwFrame::GetCache(), this); - pAttrs = pAccess->Get(); - // The last row wants to keep with the frame behind the table. // Check if the next frame is on a different page and valid. // In this case we do a magic trick: @@ -2472,9 +2524,6 @@ void SwTabFrame::MakeAll(vcl::RenderContext* pRenderContext) GetFollow()->MakeAll(pRenderContext); - pAccess = o3tl::make_unique<SwBorderAttrAccess>(SwFrame::GetCache(), this); - pAttrs = pAccess->Get(); - GetFollow()->SetLowersFormatted(false); // #i43913# - lock follow table // to avoid its formatting during the format of |