sw/qa/extras/ooxmlexport/ooxmlexport25.cxx | 13 ++++++++++--- sw/source/filter/ww8/docxattributeoutput.cxx | 6 +++++- 2 files changed, 15 insertions(+), 4 deletions(-)
New commits: commit cdbebd3086498673ee5b668e3aaeb5c90674825f Author: [email protected] <[email protected]> AuthorDate: Mon Jan 19 14:15:36 2026 -0500 Commit: Justin Luth <[email protected]> CommitDate: Thu Jan 22 16:06:46 2026 +0100 tdf#170389 docx export: don't spam inherited tabstops Until now, we had been duplicating inherited tabstops into the current style or paragraph. While not a terrible thing, it is unnecessary (assuming inheritance is working properly). Also, it COULD (though unlikely) contribute to hitting the 64 maximum tabstop limit that DOCX has. That could have resulted in discarding necessary tabstops. make CppunitTest_sw_ooxmlexport25 \ CPPUNIT_TEST_NAME=testTdf170389_manyTabstops Change-Id: Ib68eaf043af15384fea2cd96e8fe178a505ec1db Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197607 Reviewed-by: Justin Luth <[email protected]> Tested-by: Jenkins (cherry picked from commit bef77a531f0a8d270a61e908149312ee243182e6) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197779 diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx index f6feec1fa36a..009b92a1d663 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx @@ -151,12 +151,19 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf170389_manyTabstops) { createSwDoc("tdf170389_manyTabstops.odt"); - save(TestFilter::DOCX); + saveAndReload(TestFilter::DOCX); xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); // MS Word reports document as corrupt if it has more than 64 tabstops defined - // The paragraph itself defines 40, and inherits 40. Without the fix, this was 80 - assertXPath(pXmlDoc, "//w:tabs/w:tab", 64); + // The paragraph itself defines 40, and inherits 40. Without the fixes, this was 80 or 64 + assertXPath(pXmlDoc, "//w:tabs/w:tab", 40); + + xmlDocUniquePtr pLayout = parseLayoutDump(); + sal_Int32 nSize + = getXPath(pLayout, "//SwFixPortion[@type='PortionType::TabLeft']", "width").toInt32(); + // The word 'tabstop' should be almost at the very end of the line, starting at 6 inches. + // Without the fix, the tabstop's width was a tiny 247, now it is 1797. + CPPUNIT_ASSERT_GREATER(sal_Int32(1500), nSize); // nSize > 1500 } CPPUNIT_TEST_FIXTURE(Test, testInvalidDatetimeInProps) diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 9398166c8c8a..a695f51221c7 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -9280,6 +9280,8 @@ void DocxAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop ) // <w:tabs> may contain 64 <w:tab> entries at most, or else MS Word reports the file as corrupt sal_uInt32 nWrittenTabs = 0; + // do not output inherited tabs multiple times (inside styles and inside inline properties) + std::vector<bool> vInherited(nCount, false); // Get offset for tabs // In DOCX, w:pos specifies the position of the current custom tab stop with respect to the current page margins. @@ -9303,13 +9305,15 @@ void DocxAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop ) FSNS( XML_w, XML_pos ), OString::number(pInheritedTabs->At(i).GetTabPos()) ); ++nWrittenTabs; } + else if (pInheritedTabs->At(i) == rTabStop[nCurrTab]) + vInherited[nCurrTab] = true; } for (sal_uInt16 i = 0; i < nCount; i++ ) { if( rTabStop[i].GetAdjustment() != SvxTabAdjust::Default ) { - if (nWrittenTabs < 64) + if (!vInherited[i] && nWrittenTabs < 64) { impl_WriteTabElement( m_pSerializer, rTabStop[i], tabsOffset ); ++nWrittenTabs;
