sw/qa/extras/ooxmlexport/ooxmlexport25.cxx   |   13 ++++++++++---
 sw/source/filter/ww8/docxattributeoutput.cxx |    6 +++++-
 2 files changed, 15 insertions(+), 4 deletions(-)

New commits:
commit b3e82cc18c6c61dfb3906631d311351355a476a0
Author:     [email protected] <[email protected]>
AuthorDate: Mon Jan 19 14:15:36 2026 -0500
Commit:     Justin Luth <[email protected]>
CommitDate: Tue Jan 20 13:31:02 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

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx
index 72fbe062ce04..2ea0d1a6a50f 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport25.cxx
@@ -154,12 +154,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 73bc0c17509e..b8497eb475d9 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -9290,6 +9290,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.
@@ -9313,13 +9315,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;

Reply via email to