sw/source/core/inc/ftnboss.hxx | 6 -- sw/source/core/layout/ftnfrm.cxx | 16 +----- sw/source/core/layout/objectformattertxtfrm.cxx | 62 +++++++++++++++--------- 3 files changed, 44 insertions(+), 40 deletions(-)
New commits: commit 3f569ffc9238e6bf2915e78bf21c844ca5f1270d Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Fri Feb 25 22:07:10 2022 +0100 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Wed Mar 2 10:52:10 2022 +0100 sw: really prevent footnote frame against delete while it's moved This reverts commit fe5d3fbfe63fe8b433776bd3a0508dd712b868b0 It turns out that checking a single column's IsMovingFootnotes() is not enough - as frames can move both forwards and backwards the entire chain of columns would need to be checked. (Most callers of MoveLowerFootnotes() move forwards, but one place in tabfrm.cxx moves from a follow to master.) But it turns out that this is probably the wrong way in any case: most likely the intention in FormatAnchorFrameAndItsPrevs() is to format previous frames in the same layout environment, so if there is a section or column inside a footnote then this upper should be formatted, while if the footnote is inside a section or column this upper should not be formatted; this should make calls during MoveFootnotes_() safe as it should prevent the formatting of frames in the footnote boss moving a footnote that is already being moved. So tweak the fix in commit fa1bcc22921941b2cd8a0b32fe0d15655d12d607 a little to make it more general. Also it was previously possible that for a section with columns, both the section branch and the column branch was taken, which seems supperfluous. Change-Id: I39487640322339fe4d511e845d9c6bced2ba9dad Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130544 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/sw/source/core/inc/ftnboss.hxx b/sw/source/core/inc/ftnboss.hxx index 70d7f380e291..3ee7859bf8f3 100644 --- a/sw/source/core/inc/ftnboss.hxx +++ b/sw/source/core/inc/ftnboss.hxx @@ -54,7 +54,6 @@ class SAL_DLLPUBLIC_RTTI SwFootnoteBossFrame: public SwLayoutFrame // max. height of the footnote container on this page SwTwips m_nMaxFootnoteHeight; - bool m_isMovingFootnotes = false; SwFootnoteContFrame *MakeFootnoteCont(); SwFootnoteFrame *FindFirstFootnote(); @@ -107,13 +106,10 @@ public: SwFootnoteBossFrame* _pOld, SwFootnoteFrames& _rFootnoteArr, const bool _bCollectOnlyPreviousFootnotes = false ); - void MoveFootnotes_( SwFootnoteFrames &rFootnoteArr, bool bCalc = false, - SwFootnoteBossFrame * pOldBoss = nullptr); + void MoveFootnotes_( SwFootnoteFrames &rFootnoteArr, bool bCalc = false ); void MoveFootnotes( const SwContentFrame *pSrc, SwContentFrame *pDest, SwTextFootnote const *pAttr ); - bool IsMovingFootnotes() const { return m_isMovingFootnotes; } - // should AdjustNeighbourhood be called (or Grow/Shrink)? SwNeighbourAdjust NeighbourhoodAdjustment() const { return IsPageFrame() ? SwNeighbourAdjust::OnlyAdjust : NeighbourhoodAdjustment_(); } diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx index ce94ad214509..a01c0c8bc4f0 100644 --- a/sw/source/core/layout/ftnfrm.cxx +++ b/sw/source/core/layout/ftnfrm.cxx @@ -36,7 +36,6 @@ #include <ndindex.hxx> #include <pam.hxx> #include <ndtxt.hxx> -#include <comphelper/flagguard.hxx> #include <osl/diagnose.h> #include <sal/log.hxx> #include <IDocumentSettingAccess.hxx> @@ -1955,8 +1954,7 @@ void SwFootnoteBossFrame::CollectFootnotes_( const SwContentFrame* _pRef, while ( _pFootnote ); } -void SwFootnoteBossFrame::MoveFootnotes_(SwFootnoteFrames &rFootnoteArr, - bool bCalc, SwFootnoteBossFrame *const pOldBoss) +void SwFootnoteBossFrame::MoveFootnotes_( SwFootnoteFrames &rFootnoteArr, bool bCalc ) { // All footnotes referenced by pRef need to be moved // to a new position (based on the new column/page) @@ -1964,12 +1962,6 @@ void SwFootnoteBossFrame::MoveFootnotes_(SwFootnoteFrames &rFootnoteArr, const sal_uInt16 nMyCol = lcl_ColumnNum( this ); SwRectFnSet aRectFnSet(this); - ::std::optional<::comphelper::FlagGuard> g; - if (pOldBoss) - { - g.emplace(pOldBoss->m_isMovingFootnotes); - } - // #i21478# - keep last inserted footnote in order to // format the content of the following one. SwFootnoteFrame* pLastInsertedFootnote = nullptr; @@ -2196,7 +2188,7 @@ void SwFootnoteBossFrame::MoveFootnotes( const SwContentFrame *pSrc, SwContentFr if ( aFootnoteArr.empty() ) return; - pDestBoss->MoveFootnotes_(aFootnoteArr, true, this); + pDestBoss->MoveFootnotes_( aFootnoteArr, true ); SwPageFrame* pSrcPage = FindPageFrame(); SwPageFrame* pDestPage = pDestBoss->FindPageFrame(); // update FootnoteNum only at page change @@ -2727,11 +2719,11 @@ bool SwLayoutFrame::MoveLowerFootnotes( SwContentFrame *pStart, SwFootnoteBossFr if ( !aFootnoteArr.empty() || pFootnoteArr ) { if( !aFootnoteArr.empty() ) - pNewBoss->MoveFootnotes_(aFootnoteArr, true, pOldBoss); + pNewBoss->MoveFootnotes_( aFootnoteArr, true ); if( pFootnoteArr ) { assert(pNewChief); - static_cast<SwFootnoteBossFrame*>(pNewChief)->MoveFootnotes_(*pFootnoteArr, true, pOldBoss); + static_cast<SwFootnoteBossFrame*>(pNewChief)->MoveFootnotes_( *pFootnoteArr, true ); pFootnoteArr.reset(); } bMoved = true; diff --git a/sw/source/core/layout/objectformattertxtfrm.cxx b/sw/source/core/layout/objectformattertxtfrm.cxx index 72ff9ed863eb..1053e84d2421 100644 --- a/sw/source/core/layout/objectformattertxtfrm.cxx +++ b/sw/source/core/layout/objectformattertxtfrm.cxx @@ -799,16 +799,8 @@ static void lcl_FormatContentOfLayoutFrame( SwLayoutFrame* pLayFrame, { SwFrameDeleteGuard aCrudeHack(pLowerFrame); // ??? any issue setting this for non-footnote frames? // prevent moving footnotes by formatting if they are already being moved - if (pLowerFrame->IsFootnoteBossFrame() && - static_cast<SwFootnoteBossFrame const*>(pLowerFrame)->IsMovingFootnotes()) - { - SAL_INFO("sw.layout", "suppressing layout of footnote boss frame during moving footnotes"); - } - else - { - lcl_FormatContentOfLayoutFrame( static_cast<SwLayoutFrame*>(pLowerFrame), + lcl_FormatContentOfLayoutFrame( static_cast<SwLayoutFrame*>(pLowerFrame), pLastLowerFrame ); - } } else pLowerFrame->Calc(pLowerFrame->getRootFrame()->GetCurrShell()->GetOut()); @@ -838,21 +830,46 @@ void SwObjectFormatterTextFrame::FormatAnchorFrameAndItsPrevs( SwTextFrame& _rAn // for follow text frames. if ( !_rAnchorTextFrame.IsFollow() ) { + // In case the anchor frame is in a column or section, format its + // previous frames first - but don't jump out of the current layout + // environment, e.g. from footnotes into the footnote boss. + SwFrame * pSectFrame(nullptr); + SwFrame * pColFrameOfAnchor(nullptr); + for (SwFrame* pUpper = _rAnchorTextFrame.GetUpper(); + pUpper != nullptr; pUpper = pUpper->GetUpper()) + { + if (pUpper->IsCellFrame()) + { + break; // apparently nothing to be done? + } + if (pUpper->IsFootnoteFrame()) + { + SAL_INFO_IF(pColFrameOfAnchor == nullptr && pUpper->FindColFrame(), + "sw.layout", "tdf#122894 skipping column for footnote in column"); + break; // stop: prevent crash in case footnotes are being moved + } + if (pUpper->IsSctFrame()) + { + pColFrameOfAnchor = nullptr; + pSectFrame = pUpper; + break; + } + if (pColFrameOfAnchor != nullptr) + { // parent of column not a section frame => column not in section + break; + } + if (pUpper->IsColumnFrame()) + { + pColFrameOfAnchor = pUpper; + } + } + // if anchor frame is directly inside a section, format this section and // its previous frames. // Note: It's a very simple format without formatting objects. - if ( _rAnchorTextFrame.IsInSct() ) + if (pSectFrame) { - SwFrame* pSectFrame = _rAnchorTextFrame.GetUpper(); - while ( pSectFrame ) - { - if ( pSectFrame->IsSctFrame() || pSectFrame->IsCellFrame() ) - { - break; - } - pSectFrame = pSectFrame->GetUpper(); - } - if ( pSectFrame && pSectFrame->IsSctFrame() ) + assert(pSectFrame->IsSctFrame()); { SwFrameDeleteGuard aDeleteGuard(&_rAnchorTextFrame); // #i44049# @@ -880,10 +897,9 @@ void SwObjectFormatterTextFrame::FormatAnchorFrameAndItsPrevs( SwTextFrame& _rAn // #i40140# - if anchor frame is inside a column, // format the content of the previous columns. // Note: It's a very simple format without formatting objects. - SwFrame* pColFrameOfAnchor = _rAnchorTextFrame.FindColFrame(); - SAL_WARN_IF(pColFrameOfAnchor && _rAnchorTextFrame.IsInFootnote(), "sw.layout", "tdf#122894 skipping anchor in column in footnote"); - if (pColFrameOfAnchor && !_rAnchorTextFrame.IsInFootnote()) + if (pColFrameOfAnchor) { + assert(pColFrameOfAnchor->IsColumnFrame()); // #i44049# _rAnchorTextFrame.LockJoin(); SwFrameDeleteGuard aDeleteGuard(&_rAnchorTextFrame);