sw/qa/core/layout/flycnt.cxx     |   26 ++++++++++++++++++++++++++
 sw/source/core/layout/flycnt.cxx |   13 ++++++++++---
 sw/source/core/text/itratr.cxx   |    2 +-
 3 files changed, 37 insertions(+), 4 deletions(-)

New commits:
commit 247d76cd7a5626e182ab2b4a858224735860925c
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Apr 4 08:28:08 2023 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Thu Apr 20 08:12:00 2023 +0200

    sw floattable: fix removal of last follow fly with a start/middle one
    
    The bugdoc has 3 pages: each page has 1 row of a floating table.
    Deleting the last row deleted the last fly frame, but the text in the
    body didn't move from page 3 to page 2.
    
    It seems what happened was that the condition in
    SwTextFrame::HasNonLastSplitFlyDrawObj() was wrong, it always filtered
    for the master anchor, not for the relevant anchor. Once that's fixed,
    the other problem was that by the time SwRootFrame::DeleteEmptyFlys_()
    would invalidate the anchor, the follow/precede relationship is already
    unlinked for the to-be-deleted fly, so we can't find the correct anchor
    of the to-be-deleted fly.
    
    Fix the second problem by invalidating the anchor earlier, in
    SwFlyAtContentFrame::DelEmpty(), where the to-be-deleted fly is still
    part of the flow frame chain.
    
    With this, deleting the last row in the document results in deleting the
    entire page 3 and moving up the body text, as expected.
    
    (cherry picked from commit 96df0ad0da6e8972a828721dac6b4ba7c69eba85)
    
    Change-Id: I3303408cafabcc61abfffe6c355ec3874fff30a2
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150254
    Tested-by: Miklos Vajna <vmik...@collabora.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx
index 34e31371d346..85dae0e7cfab 100644
--- a/sw/qa/core/layout/flycnt.cxx
+++ b/sw/qa/core/layout/flycnt.cxx
@@ -629,6 +629,32 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFly1stRowDelete)
     // on page 2.
     CPPUNIT_ASSERT(!pPage1->GetNext());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFly3rdRowDelete)
+{
+    // Given a document with a floattable, split on 3 pages:
+    SwModelTestBase::FlySplitGuard aGuard;
+    createSwDoc("floattable-3pages.docx");
+
+    // When deleting the row of A3:
+    SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
+    pWrtShell->GotoTable("Table1");
+    pWrtShell->Down(/*bSelect=*/false);
+    pWrtShell->Down(/*bSelect=*/false);
+    SwTextNode* pTextNode = 
pWrtShell->GetCursor()->GetPointNode().GetTextNode();
+    // We delete the right row:
+    CPPUNIT_ASSERT_EQUAL(OUString("A3"), pTextNode->GetText());
+    pWrtShell->DeleteRow();
+
+    // Then make sure we only have 2 pages:
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
+    CPPUNIT_ASSERT(pPage1);
+    auto pPage2 = dynamic_cast<SwPageFrame*>(pPage1->GetNext());
+    // Without the accompanying fix in place, this test would have failed, 
page 3 was not deleted.
+    CPPUNIT_ASSERT(!pPage2->GetNext());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/flycnt.cxx b/sw/source/core/layout/flycnt.cxx
index ed7ee1467ef8..1185a980dbc3 100644
--- a/sw/source/core/layout/flycnt.cxx
+++ b/sw/source/core/layout/flycnt.cxx
@@ -1635,10 +1635,7 @@ void SwRootFrame::DeleteEmptyFlys_()
         if (!pFly->getFrameArea().HasArea() && !pFly->ContainsContent()
             && !pFly->IsDeleteForbidden())
         {
-            SwTextFrame* pFlyAnchor = pFly->FindAnchorCharFrame();
             SwFrame::DestroyFrame(pFly);
-            // So that JoinFrame() is called on the precede of the anchor if 
it has any.
-            pFlyAnchor->InvalidateSize();
         }
     }
 }
@@ -1655,6 +1652,16 @@ SwFlyAtContentFrame* SwFlyAtContentFrame::GetPrecede()
 
 void SwFlyAtContentFrame::DelEmpty()
 {
+    SwTextFrame* pAnchor = FindAnchorCharFrame();
+    if (pAnchor)
+    {
+        if (SwFlowFrame* pAnchorPrecede = pAnchor->GetPrecede())
+        {
+            // The anchor has a precede: invalidate it so that JoinFrame() is 
called on it.
+            pAnchorPrecede->GetFrame().InvalidateSize();
+        }
+    }
+
     SwFlyAtContentFrame* pMaster = IsFollow() ? GetPrecede() : nullptr;
     if (pMaster)
     {
diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx
index feddd1a2347f..794d1f590967 100644
--- a/sw/source/core/text/itratr.cxx
+++ b/sw/source/core/text/itratr.cxx
@@ -1507,7 +1507,7 @@ bool SwTextFrame::HasNonLastSplitFlyDrawObj() const
         // Nominally all flys are anchored in the master; see if this fly is 
effectively anchored in
         // us.
         SwTextFrame* pFlyAnchor = pFly->FindAnchorCharFrame();
-        if (pFlyAnchor != pAnchor)
+        if (pFlyAnchor != this)
         {
             continue;
         }

Reply via email to