sw/qa/extras/layout/data/LIBREOFFICE-UXTSOREL.rtf |binary
 sw/qa/extras/layout/layout.cxx                    |    9 +++
 sw/source/core/layout/objectformattertxtfrm.cxx   |   52 ++++++++++++++++------
 3 files changed, 47 insertions(+), 14 deletions(-)

New commits:
commit b845927ed4e3987a578b0c8ded46ddbc7833e7ff
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed Feb 23 16:45:31 2022 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Mar 2 13:31:12 2022 +0100

    sw: really prevent footnote frame against delete while it's moved
    
    This reverts commit fe5d3fbfe63fe8b433776bd3a0508dd712b868b0
    (on master only)
    
    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.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130544
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 3f569ffc9238e6bf2915e78bf21c844ca5f1270d)
    
    add a layout test to exercise UXTSOREL
    
    Change-Id: I57b29dd7d73c08bdbf227676c4ce9034aabf418a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130493
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    (cherry picked from commit 10d46c0498b89350645cf45e744a528d3d8f1ac1)
    
    Change-Id: I39487640322339fe4d511e845d9c6bced2ba9dad
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130831
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/extras/layout/data/LIBREOFFICE-UXTSOREL.rtf 
b/sw/qa/extras/layout/data/LIBREOFFICE-UXTSOREL.rtf
new file mode 100644
index 000000000000..1020269ae119
Binary files /dev/null and b/sw/qa/extras/layout/data/LIBREOFFICE-UXTSOREL.rtf 
differ
diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx
index 0c7a4dc13ff0..94edf650a359 100644
--- a/sw/qa/extras/layout/layout.cxx
+++ b/sw/qa/extras/layout/layout.cxx
@@ -2478,6 +2478,15 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testForcepoint75)
     createSwDoc(DATA_DIRECTORY, "forcepoint75-1.rtf");
 }
 
+// FIXME: apparently infinite loop on Mac
+#ifndef MACOSX
+//just care it doesn't crash/assert
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testUXTSOREL)
+{
+    createSwDoc(DATA_DIRECTORY, "LIBREOFFICE-UXTSOREL.rtf");
+}
+#endif
+
 //just care it doesn't crash/assert
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testForcepointFootnoteFrame)
 {
diff --git a/sw/source/core/layout/objectformattertxtfrm.cxx 
b/sw/source/core/layout/objectformattertxtfrm.cxx
index 26d503511064..d0fa8cf1be84 100644
--- a/sw/source/core/layout/objectformattertxtfrm.cxx
+++ b/sw/source/core/layout/objectformattertxtfrm.cxx
@@ -829,21 +829,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#
@@ -871,10 +896,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