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);

Reply via email to