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 073072f0a3abacfe4f9cc920b8138d7abc84db70
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Aug 1 09:06:43 2023 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Aug 1 09:59:02 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.
    
    Change-Id: I74549e2ea8ca0d06a9e4814a58aaa8ca476263dc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155122
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

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 5b523067523a..f8faee3a1bcd 100644
--- a/sw/qa/core/doc/doc.cxx
+++ b/sw/qa/core/doc/doc.cxx
@@ -34,6 +34,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
@@ -482,6 +486,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 0b51fc65e46e..4ad364ea6afc 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>
@@ -5241,7 +5242,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