sw/qa/core/text/data/floattable-heading-split.docx |binary
 sw/qa/core/text/widorp.cxx                         |   22 +++++++++++++++++++++
 sw/source/core/text/widorp.cxx                     |    8 +++++++
 3 files changed, 30 insertions(+)

New commits:
commit b8009818d619bff16d19a0f589a733f78a46ec0b
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Mon Jul 14 09:28:52 2025 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Mon Jul 14 11:18:28 2025 +0200

    tdf#167222 sw floattable: allow split of fly and its keep-together anchor 
text
    
    Regression from commit 3eb6d764b3023500f2299d36bf1860bc8e67db9f (DOCX
    import: floating table with negative top margin has to be a fly frame,
    2022-01-21), open the bugdoc, notice that the floating table should be
    at the end of page 1 but is at the start of page 2.
    
    This happens because in general keep-together means no split should
    happen for all anchored objects and lines of a text frame, but Word
    allows floating tables to be split from the next regular paragraph in
    the document.
    
    Fix the problem by building on top of the work done in commit
    2d0a4ef1d83b8de6cb133970c2c35ae706fb058e (sw floattable: fix negative
    vertical offset handling on page boundary, 2023-06-20), which makes this
    split to "floating table" and "anchor text" pieces possible, but that
    didn't help here, since the anchor text node happened to be a heading,
    with both a split property set to false and a keep-with-next property
    set to true. Now we ignore both properties in case the paragraph is a
    floating table anchor, which means that in SwTextFrame::FormatAdjust(),
    rFrameBreak.IsBreakNow() can return true, resulting in a call to
    SplitFrame(), as needed.
    
    The behavior for other types of anchored objects is unchanged, those
    don't go to a separate page in Word, either.
    
    Change-Id: I48835f355fa5aeb09b1a92bd8cee7e06cd148240
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187845
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sw/qa/core/text/data/floattable-heading-split.docx 
b/sw/qa/core/text/data/floattable-heading-split.docx
new file mode 100644
index 000000000000..adfd173c172e
Binary files /dev/null and b/sw/qa/core/text/data/floattable-heading-split.docx 
differ
diff --git a/sw/qa/core/text/widorp.cxx b/sw/qa/core/text/widorp.cxx
index 54d26aa2db07..7dd48bc9b879 100644
--- a/sw/qa/core/text/widorp.cxx
+++ b/sw/qa/core/text/widorp.cxx
@@ -60,6 +60,28 @@ CPPUNIT_TEST_FIXTURE(Test, testHideWhitespaceWidorp)
     // went to page 1, so it was not split anymore.
     CPPUNIT_ASSERT(pPara2->HasFollow());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testFloattableHeadingSplit)
+{
+    // Given a document which ends with a floating table and a heading 
paragraph:
+    // When loading that document & laying it out:
+    createSwDoc("floattable-heading-split.docx");
+
+    // Then make sure that the floating table is on page 1 and the last 
heading is on page 2:
+    SwDocShell* pDocShell = getSwDocShell();
+    SwDoc* pDoc = pDocShell->GetDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage1 = pLayout->Lower()->DynCastPageFrame();
+    // Without the accompanying fix in place, this test would have failed, the 
floating table went
+    // to page 2, not to page 1.
+    CPPUNIT_ASSERT(pPage1->GetSortedObjs());
+    // Make sure that page 2 has no floating table and has the heading on the 
correct page.
+    auto pPage2 = pPage1->GetNext()->DynCastPageFrame();
+    CPPUNIT_ASSERT(!pPage2->GetSortedObjs());
+    SwLayoutFrame* pBody2 = pPage2->FindBodyCont();
+    SwTextFrame* pPage2Para1 = pBody2->ContainsContent()->DynCastTextFrame();
+    CPPUNIT_ASSERT_EQUAL(u"page 2"_ustr, pPage2Para1->GetText());
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/widorp.cxx b/sw/source/core/text/widorp.cxx
index 4c0dd129da04..b6c5dd5b70aa 100644
--- a/sw/source/core/text/widorp.cxx
+++ b/sw/source/core/text/widorp.cxx
@@ -73,6 +73,14 @@ SwTextFrameBreak::SwTextFrameBreak( SwTextFrame *pNewFrame, 
const SwTwips nRst )
     }
     m_bKeep = m_bKeep || 
!m_pFrame->GetTextNodeForParaProps()->GetSwAttrSet().GetSplit().GetValue() ||
         
m_pFrame->GetTextNodeForParaProps()->GetSwAttrSet().GetKeep().GetValue();
+
+    if (m_bKeep && m_pFrame->HasSplitFlyDrawObjs())
+    {
+        // Ignore keep-together and keep-with-next if this is an anchor for a 
floating table. It's
+        // OK to split the text frame into two, to separate the floating table 
and the anchor text.
+        m_bKeep = false;
+    }
+
     m_bBreak = false;
 
     if( !m_nRstHeight && !m_pFrame->IsFollow() && m_pFrame->IsInFootnote() && 
m_pFrame->HasPara() )

Reply via email to