sw/qa/core/doc/data/floating-table-dummy-text.docx      |binary
 sw/qa/core/doc/doc.cxx                                  |   33 ++++++++++++++++
 sw/source/core/doc/DocumentContentOperationsManager.cxx |   21 ++++++++++
 3 files changed, 54 insertions(+)

New commits:
commit d0ba58dfefb3929481486be9664eae255ef9f0c9
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Aug 1 09:06:43 2023 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Wed Aug 2 11:41:04 2023 +0200

    tdf#156260 sw floattable: avoid overlapping flys on anchor change
    
    Going to the end of the document, typing "dt" and F3 collapses the
    multi-page floating table into a single page, with overlapping text.
    
    In practice we insert a new paragraph before the "dt" one, insert the
    dummy text there and then re-anchor the floating table from the old
    paragraph to the new one. Such re-anchoring isn't really meant to be
    done with floating tables, which are always just anchored in the next
    paragraph in practice. An additional problem is that the amount of fly
    frames created depends on the position of the first fly frame, so if the
    anchor changes, we may need a different number of split fly frames.
    
    Fix the problem by not trying to reuse the old fly frames on anchor
    change: delete the old frames, change the anchor and finally create the
    new frames, which leads to correct layout with complicated logic trying
    to update the old fly chain to the new anchor.
    
    The original document still puts some dummy text on page 4 instead of
    starting it on page 5, that part is still unfixed.
    
    (cherry picked from commit 073072f0a3abacfe4f9cc920b8138d7abc84db70)
    
    Change-Id: I74549e2ea8ca0d06a9e4814a58aaa8ca476263dc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155208
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/qa/core/doc/data/floating-table-dummy-text.docx 
b/sw/qa/core/doc/data/floating-table-dummy-text.docx
new file mode 100644
index 000000000000..14de5a920a88
Binary files /dev/null and b/sw/qa/core/doc/data/floating-table-dummy-text.docx 
differ
diff --git a/sw/qa/core/doc/doc.cxx b/sw/qa/core/doc/doc.cxx
index c0c76d2c638e..e8a554e35d80 100644
--- a/sw/qa/core/doc/doc.cxx
+++ b/sw/qa/core/doc/doc.cxx
@@ -37,6 +37,10 @@
 #include <IDocumentRedlineAccess.hxx>
 #include <frmmgr.hxx>
 #include <formatflysplit.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <rootfrm.hxx>
+#include <pagefrm.hxx>
+#include <sortedobjs.hxx>
 
 /// Covers sw/source/core/doc/ fixes.
 class SwCoreDocTest : public SwModelTestBase
@@ -486,6 +490,35 @@ CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testSplitFlyChain)
     CPPUNIT_ASSERT_EQUAL(SwChainRet::IS_IN_CHAIN, eActual);
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreDocTest, testSplitExpandGlossary)
+{
+    // Given a document with a split fly (2 pages) and a 'dt' at the end:
+    createSwDoc("floating-table-dummy-text.docx");
+    SwWrtShell* pWrtShell = getSwDocShell()->GetWrtShell();
+    pWrtShell->SttEndDoc(/*bStt=*/false);
+
+    // When expanding 'dt' to an actual dummy text:
+    dispatchCommand(mxComponent, ".uno:ExpandGlossary", {});
+
+    // Then make sure the 2 fly frames stay on the 2 pages:
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
+    CPPUNIT_ASSERT(pPage1);
+    CPPUNIT_ASSERT(pPage1->GetSortedObjs());
+    const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 1
+    // - Actual  : 2
+    // i.e. both parts of the split fly chain were on page 1.
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
+    auto pPage2 = dynamic_cast<SwPageFrame*>(pPage1->GetNext());
+    CPPUNIT_ASSERT(pPage2);
+    CPPUNIT_ASSERT(pPage2->GetSortedObjs());
+    const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx 
b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index b1a14de36c3f..d467fd2c5789 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -70,6 +70,7 @@
 #include <fmtflcnt.hxx>
 #include <docedt.hxx>
 #include <frameformats.hxx>
+#include <formatflysplit.hxx>
 #include <o3tl/safeint.hxx>
 #include <sal/log.hxx>
 #include <unotools/charclass.hxx>
@@ -5254,7 +5255,27 @@ bool 
DocumentContentOperationsManager::CopyImplImpl(SwPaM& rPam, SwPosition& rPo
                 {
                     SwFormatAnchor anchor(*pAnchor);
                     anchor.SetAnchor( &startPosAtPara );
+
+                    bool bSplitFly = false;
+                    if (pFly->GetFlySplit().GetValue())
+                    {
+                        SwIterator<SwFrame, SwModify> aIter(*pFly);
+                        bSplitFly = aIter.First() && aIter.Next();
+                    }
+                    if (bSplitFly)
+                    {
+                        // This fly format has multiple frames, and we change 
the anchor. Remove the
+                        // old frames, which were based on the old anchor 
position.
+                        pFly->DelFrames();
+                    }
+
                     pFly->SetFormatAttr(anchor);
+
+                    if (bSplitFly)
+                    {
+                        // Re-create the frames now that the new anchor is set.
+                        pFly->MakeFrames();
+                    }
                 }
             }
         }

Reply via email to