sw/qa/extras/htmlimport/htmlimport.cxx |   10 ++++++++
 sw/source/core/docnode/ndtbl.cxx       |   41 ++++++++++++++++++++++++++++++++-
 2 files changed, 50 insertions(+), 1 deletion(-)

New commits:
commit 6ef29b80c973d197f2ffeb05f0ace78369893fe7
Author:     Justin Luth <jl...@mail.com>
AuthorDate: Tue Sep 16 15:35:17 2025 -0400
Commit:     Justin Luth <jl...@mail.com>
CommitDate: Wed Sep 17 02:25:19 2025 +0200

    tdf#145689 sw: transfer breaks to table-in-table
    
    A table is allowed to specify a page break.
    
    If a table-in-table is the first thing in cell A1,
    then (only) that table-in-table is checked for the page breaks,
    so transfer page breaks when inserting a table-in-table.
    
    make CppunitTest_sw_htmlimport CPPUNIT_TEST_NAME=testTdf155011
    
    Change-Id: Iae6d54aa2c7c33e07cdd235ff347a9d0fde3dc65
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191050
    Reviewed-by: Justin Luth <jl...@mail.com>
    Tested-by: Jenkins

diff --git a/sw/qa/extras/htmlimport/htmlimport.cxx 
b/sw/qa/extras/htmlimport/htmlimport.cxx
index 6cf8f22647b9..8d8d8d0a5804 100644
--- a/sw/qa/extras/htmlimport/htmlimport.cxx
+++ b/sw/qa/extras/htmlimport/htmlimport.cxx
@@ -20,7 +20,9 @@
 #include <com/sun/star/document/XEmbeddedObjectSupplier2.hpp>
 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
 #include <com/sun/star/embed/XInplaceObject.hpp>
+#include <com/sun/star/text/XPageCursor.hpp>
 #include <com/sun/star/text/XTextTable.hpp>
+#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
 
 #include <tools/datetime.hxx>
 #include <sfx2/linkmgr.hxx>
@@ -663,6 +665,14 @@ CPPUNIT_TEST_FIXTURE(HtmlImportTest, testTdf155011)
 {
     createSwWebDoc("tdf155011.html");
     // Must not crash / fail asserts
+
+    // tdf#145689: don't lose page style when inserting table-in-table
+    uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
+    uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(
+        xModel->getCurrentController(), uno::UNO_QUERY);
+    uno::Reference<text::XPageCursor> 
xCursor(xTextViewCursorSupplier->getViewCursor(),
+                                              uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(u"HTML"_ustr, getProperty<OUString>(xCursor, 
u"PageStyleName"_ustr));
 }
 
 } // end of anonymous namespace
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index 018889689764..7f0007450cd7 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -219,6 +219,37 @@ static SwTableBoxFormat *lcl_CreateAFormatBoxFormat( SwDoc 
&rDoc, std::vector<Sw
     return rBoxFormatArr[nId];
 }
 
+static void lcl_transferTableBreaks(const SwTableBox& rParentCell, const 
SwTableNode& rDestTableNd,
+                             SwFrameFormat& rDestFormat)
+{
+    // only if this is the first paragraph of the cell
+    if (rDestTableNd.StartOfSectionIndex() + 1 != rDestTableNd.GetIndex())
+        return;
+
+    if (!rParentCell.GetSttNd())
+        return;
+
+    const SwTable& rParentTable = 
rParentCell.GetSttNd()->FindTableNode()->GetTable();
+    // only if this is in the first cell in the table
+    if (rParentCell.FindPreviousBox(rParentTable, &rParentCell))
+        return;
+
+    SwFrameFormat& rSourceFormat = *rParentTable.GetFrameFormat();
+    const SfxPoolItem *pItem;
+    const SfxItemSet& rSet = rSourceFormat.GetAttrSet();
+    if (SfxItemState::SET == rSet.GetItemState(RES_PAGEDESC, false, &pItem))
+    {
+        rDestFormat.SetFormatAttr(*pItem);
+        // rSourceFormat.ResetFormatAttr(RES_PAGEDESC); // TODO: not 
transferred back on table delete
+    }
+
+    if (SfxItemState::SET == rSet.GetItemState(RES_BREAK, false, &pItem))
+    {
+        rDestFormat.SetFormatAttr(*pItem);
+        // rSourceFormat.ResetFormatAttr(RES_BREAK);
+    }
+}
+
 SwTableNode* SwDoc::IsIdxInTable( const SwNodeIndex& rIdx ) { return 
IsInTable(rIdx.GetNode()); }
 
 SwTableNode* SwDoc::IsInTable(const SwNode& rIdx)
@@ -453,7 +484,10 @@ const SwTable* SwDoc::InsertTable( const 
SwInsertTableOptions& rInsTableOpts,
     // Move the hard PageDesc/PageBreak Attributes if needed
     SwContentNode* pNextNd = GetNodes()[ pTableNd->EndOfSectionIndex()+1 ]
                             ->GetContentNode();
-    if( pNextNd && pNextNd->HasSwAttrSet() )
+    const SwTableBox* pParentTableCell = pTableNd->GetTableBox();
+    if (pParentTableCell) // table-in-table
+        lcl_transferTableBreaks(/*from*/ *pParentTableCell, /*to*/ *pTableNd, 
*pTableFormat);
+    else if (pNextNd && pNextNd->HasSwAttrSet())
     {
         const SfxItemSet* pNdSet = pNextNd->GetpSwAttrSet();
         if( const SwFormatPageDesc* pItem = pNdSet->GetItemIfSet( 
RES_PAGEDESC, false ) )
@@ -1042,6 +1076,8 @@ SwTableNode* SwNodes::TextToTable( const SwNodeRange& 
rRange, sal_Unicode cCh,
     if( rRange.aStart >= rRange.aEnd )
         return nullptr;
 
+    const SwTableBox* pParentTableCell = rRange.aStart.GetNode().GetTableBox();
+
     SwTableNode * pTableNd = new SwTableNode( rRange.aStart.GetNode() );
     new SwEndNode( rRange.aEnd.GetNode(), *pTableNd );
 
@@ -1088,6 +1124,9 @@ SwTableNode* SwNodes::TextToTable( const SwNodeRange& 
rRange, sal_Unicode cCh,
             }
         }
 
+        if (pParentTableCell && pTableFormat && 0 == nLines)
+            lcl_transferTableBreaks(/*from*/ *pParentTableCell, /*to*/ 
*pTableNd, *pTableFormat);
+
         lcl_RemoveBreaks(*pTextNd, (0 == nLines) ? pTableFormat : nullptr);
 
         // Set the TableNode as StartNode for all TextNodes in the Table

Reply via email to