summaryrefslogtreecommitdiffstats
path: root/sw/source/core/layout/tabfrm.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/layout/tabfrm.cxx')
-rw-r--r--sw/source/core/layout/tabfrm.cxx87
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