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