sw/qa/extras/layout/data/tdf142694-1.odt |binary
 sw/qa/extras/layout/layout.cxx           |   24 ++++++++++++++++++++++++
 sw/source/core/layout/findfrm.cxx        |   16 +++++++++++++---
 3 files changed, 37 insertions(+), 3 deletions(-)

New commits:
commit fcf6f5550cc7949e94dc74cbcd10a700a225e574
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Thu Aug 10 19:04:08 2023 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Mon Aug 14 15:00:47 2023 +0200

    tdf#142694 sw: layout: fix infinite loop in SwFrame::PrepareMake()
    
    The problem is that SwFrame::FindNext_() returns itself, because it's a
    table frame 401 and its last cell is empty.
    
    There was a nested table in the cell, but during an attempt to split the
    outer table 401, the inner table moved backwards.
    
    This is due to code that was added in commit
    c9c956f2716c58e2573a9ac07073f712d736ed02, which only checks that the
    height of the table frame is 0, but in this case the inner table does
    contain a text frame which has never been formatted yet, but still the
    table frame's size and print area was set to valid.
    
    Unfortunately adding an obvious !ContainsContent() check to the
    condition breaks uiwriter4 testTdf114306_2, the last table is not on
    page 4 but on page 5, for no good reason.
    
    So just fix SwFrame::FindNext_(), it should never return "this" anyway.
    
    (somehow regression from commit 53a0a86df6eb5fc64a85ecd03f2e354fd4d8e213)
    
    Change-Id: If043a53c32f175fc560d422c4a4e16d8e8c6ef49
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/155563
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/qa/extras/layout/data/tdf142694-1.odt 
b/sw/qa/extras/layout/data/tdf142694-1.odt
new file mode 100644
index 000000000000..9e9245998735
Binary files /dev/null and b/sw/qa/extras/layout/data/tdf142694-1.odt differ
diff --git a/sw/qa/extras/layout/layout.cxx b/sw/qa/extras/layout/layout.cxx
index f36eaa93237b..743b88d350ba 100644
--- a/sw/qa/extras/layout/layout.cxx
+++ b/sw/qa/extras/layout/layout.cxx
@@ -3532,6 +3532,30 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf128611)
     assertXPathContent(pXmlDoc, "//tab/row/cell[1]/txt", "Abcd efghijkl");
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf142694)
+{
+    createSwDoc("tdf142694-1.odt");
+
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+    CPPUNIT_ASSERT(pXmlDoc);
+
+    // the problem with this table is that the 3rd text frame (inside a nested
+    // table) contains an as-char fly that doesn't fit on a page with the
+    // repeated header row; currently it's split so that the 3rd text frame is
+    // on a page of its own and extends outside the table.
+
+    assertXPathNoAttribute(pXmlDoc, "/root/page[4]/body/tab[1]", "precede");
+    CPPUNIT_ASSERT(!getXPath(pXmlDoc, "/root/page[4]/body/tab[1]", 
"follow").isEmpty());
+    assertXPath(pXmlDoc, "/root/page[4]/body/tab[1]/row[1]/cell[1]/tab", 1);
+    assertXPath(pXmlDoc, "/root/page[4]/body/tab[1]/row[2]/cell[1]/txt", 2);
+    CPPUNIT_ASSERT(!getXPath(pXmlDoc, "/root/page[5]/body/tab[1]", 
"precede").isEmpty());
+    assertXPathNoAttribute(pXmlDoc, "/root/page[5]/body/tab[1]", "follow");
+    assertXPath(pXmlDoc, "/root/page[5]/body/tab[1]/row[1]/cell[1]/tab", 1);
+    assertXPath(pXmlDoc, "/root/page[5]/body/tab[1]/row[2]/cell[1]/tab", 1);
+    assertXPathNoAttribute(pXmlDoc, 
"/root/page[5]/body/tab[1]/row[2]/cell[1]/tab", "follow");
+    assertXPath(pXmlDoc, 
"/root/page[5]/body/tab[1]/row[2]/cell[1]/tab/row/cell/txt", 1);
+}
+
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter, testTdf152413)
 {
     createSwDoc("tdf152413.fodt");
diff --git a/sw/source/core/layout/findfrm.cxx 
b/sw/source/core/layout/findfrm.cxx
index ae2c7473baf3..1a98f6cf6747 100644
--- a/sw/source/core/layout/findfrm.cxx
+++ b/sw/source/core/layout/findfrm.cxx
@@ -945,9 +945,19 @@ SwFrame *SwFrame::FindNext_()
                          )
                        )
                     {
-                        pRet = pNxtCnt->IsInTab() ? pNxtCnt->FindTabFrame()
-                                                    : pNxtCnt;
-                        break;
+                        if (pNxtCnt->IsInTab())
+                        {
+                            if (!IsTabFrame() || 
!static_cast<SwLayoutFrame*>(this)->IsAnLower(pNxtCnt))
+                            {
+                                pRet = pNxtCnt->FindTabFrame();
+                                break;
+                            }
+                        }
+                        else
+                        {
+                            pRet = pNxtCnt;
+                            break;
+                        }
                     }
                     pNxtCnt = lcl_NextFrame( pNxtCnt );
                 }

Reply via email to