sw/qa/extras/ooxmlexport/ooxmlexport8.cxx                   |    6 ++
 sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx               |   18 ++++++++
 sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx |   26 ++++++++++--
 3 files changed, 47 insertions(+), 3 deletions(-)

New commits:
commit fc8b2dd2520b1f90b01a09867260fd008c3f7b0b
Author:     Justin Luth <[email protected]>
AuthorDate: Tue Jan 6 14:52:06 2026 -0500
Commit:     Xisco Fauli <[email protected]>
CommitDate: Mon Jan 19 17:34:05 2026 +0100

    tdf#170208 docx import: conjure up a tblInd if none is provided
    
    This has always been wrong for compat14,
    but some documents have accidentally 'looked right' at various times,
    most recently before 25.8.3
    commit a80d7ba9c01c8c5c95bf01960d969b82dc7edffc
    Author: Aron Budea on Mon Sep 29 14:59:18 2025 +0930
        tdf#168598 Fix for tdf#148578 should only apply to RTF
        Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191587
    
    This patch is based solely on experimentation.
    MS docuemntation gives no indication that it just makes up
    an 'indent from left' when none is provided.
    Even their errata documentation doesn't mention this.
    
    As noted in the bug report, this made-up value
    is different in Word 2024 than in Word 2010.
    Fortunately the 'modern' version is a simple calculation.
    
    make CppunitTest_sw_ooxmlexport8 CPPUNIT_TEST_NAME=testN780853
    make CppunitTest_sw_ooxmlfieldexport CPPUNIT_TEST_NAME=testfdo78886
    
    Change-Id: Iba59184b988a48fe4d7176e6d3b1000870c87dab
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196625
    Reviewed-by: Justin Luth <[email protected]>
    Tested-by: Jenkins
    (cherry picked from commit d0fbf21288d27833a3d3c6b95252c68bcedd1d5c)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197134
    (cherry picked from commit 459530b73eb5650b2c5651a513a2d1e3541e689c)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197156
    Reviewed-by: Xisco Fauli <[email protected]>

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
index 9fd9e51f5380..97e07a377d8a 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
@@ -524,6 +524,12 @@ DECLARE_OOXMLEXPORT_TEST(testN780853, "n780853.docx")
     //tdf#102619 - I would have expected this to be "Standard", but MSO 
2013/2010/2003 all give FollowStyle==Date
     uno::Reference< beans::XPropertySet > 
properties(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Date"_ustr), 
uno::UNO_QUERY);
     CPPUNIT_ASSERT_EQUAL(u"Date"_ustr, getProperty<OUString>(properties, 
u"FollowStyle"_ustr));
+
+    // tdf#170208: compatibilityMode12 document - emulate table placement
+    // MS Word conjures up an 'indent from left' tblInd that cancels out the 
'shift by cell margin'.
+    // Without the fix, it spilled into the left margin by the border spacing 
distance (-203/0.2cm)
+    uno::Reference<text::XTextTable> xTable(xIndexAccess->getByIndex(0), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), 
getProperty<sal_Int32>(xTable, "LeftMargin"));
 }
 
 DECLARE_OOXMLEXPORT_TEST(testN780843, "n780843.docx")
diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
index 5ba02a4d6257..c6af7434cf10 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
@@ -425,6 +425,18 @@ CPPUNIT_TEST_FIXTURE(Test, testfdo78886)
     xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr);
 
     assertXPath(pXmlDoc, 
"/w:document[1]/w:body[1]/w:tbl[2]/w:tr[1]/w:tc[1]/w:p[1]/w:hyperlink[1]/w:r[2]/w:fldChar[1]",
 0);
+
+    // tdf#170208: compatibilityMode12 document - emulate table placement
+    // TableGrid style defines tblInd - which we adjust by the border spacing 
to emulate positioning
+    uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<container::XIndexAccess> 
xIndexAccess(xTextTablesSupplier->getTextTables(), uno::UNO_QUERY);
+    uno::Reference<text::XTextTable> xTable(xIndexAccess->getByIndex(0), 
uno::UNO_QUERY);
+    // The left margin (1619 / 1.62cm) is adjusted by the border spacing (203 
/ 0.2cm)
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1416), 
getProperty<sal_Int32>(xTable, "LeftMargin"));
+
+    xTable.set(xIndexAccess->getByIndex(1), uno::UNO_QUERY);
+    // Without the fix, this was -191 (DEF_BORDER_DIST)
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-203), 
getProperty<sal_Int32>(xTable, "LeftMargin"));
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testFdo78910)
diff --git a/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx 
b/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx
index f6adfb364a51..91cc9333d996 100644
--- a/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx
+++ b/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx
@@ -491,14 +491,16 @@ TableStyleSheetEntry * 
DomainMapperTableHandler::endTableGetTableStyle(TableInfo
             m_aTableProperties->Insert( PROP_TABLE_INTEROP_GRAB_BAG, uno::Any( 
aGrabBag.getAsConstPropertyValueList() ) );
         }
 
+        bool bLeftMarginProvided = false;
         std::optional<PropertyMap::Property> oLeftMarginFromStyle = 
m_aTableProperties->getProperty(PROP_LEFT_MARGIN);
         if (oLeftMarginFromStyle)
         {
-            oLeftMarginFromStyle->second >>= nLeftMargin;
+            bLeftMarginProvided = oLeftMarginFromStyle->second >>= nLeftMargin;
             // don't need to erase, we will push back the adjusted value
             // of this (or the direct formatting, if that exists) later
         }
-        m_aTableProperties->getValue( TablePropertyMap::LEFT_MARGIN, 
nLeftMargin );
+        if (m_aTableProperties->getValue(TablePropertyMap::LEFT_MARGIN, 
nLeftMargin))
+            bLeftMarginProvided = true;
 
         m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_LEFT,
                                      rInfo.nLeftBorderDistance );
@@ -605,7 +607,14 @@ TableStyleSheetEntry * 
DomainMapperTableHandler::endTableGetTableStyle(TableInfo
         {
             const sal_Int32 nMinLeftBorderDistance = aLeftBorder.LineWidth / 2;
             sal_Int32 nLeftBorderDistance = rInfo.nLeftBorderDistance;
-            if (!m_aCellProperties.empty() && !m_aCellProperties[0].empty())
+            if (!bLeftMarginProvided)
+            {
+                // Interestingly, MS Word 'makes up' an 'indent from left' if 
none is provided,
+                // and that value varies depending on the version of MS Word.
+                // Most recent versions effectively make it look like compat15 
would...
+                nLeftBorderDistance = nMinLeftBorderDistance;
+            }
+            else if (!m_aCellProperties.empty() && 
!m_aCellProperties[0].empty())
             {
                 // only the border spacing of the first row affects the 
placement of the table
                 std::optional<PropertyMap::Property> aCellLeftBorderDistance
commit 10de2a2a1d9fd1fe3bdf93228f9379f4efff110e
Author:     Justin Luth <[email protected]>
AuthorDate: Sat Jan 3 17:02:37 2026 -0500
Commit:     Xisco Fauli <[email protected]>
CommitDate: Mon Jan 19 17:33:51 2026 +0100

    tdf#170208 docx import: shift table by cell margin, not style margin
    
    This has always been wrong,
    but some documents have accidentally 'looked right' at various times,
    most recently before 25.8.3
    commit a80d7ba9c01c8c5c95bf01960d969b82dc7edffc
    Author: Aron Budea on Mon Sep 29 14:59:18 2025 +0930
        tdf#168598 Fix for tdf#148578 should only apply to RTF
        Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191587
    
    make CppunitTest_sw_ooxmlfieldexport \
        CPPUNIT_TEST_NAME=testTdf158661_blockSDT
    
    Another nice example was nested-floating-table.docx
    
    Change-Id: Ie4e256dc0651ade8d302bf78646b2a5215414bc6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196462
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <[email protected]>
    (cherry picked from commit a63534ef77c620c06d41be9ad29c283fe636bf7f)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/196587
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>
    (cherry picked from commit 53e53fa279c11ba28829164ca68a159e614368d3)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197121
    (cherry picked from commit 587c9ea7239d2c715975294d0b1d94b06550e74e)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/197133
    Reviewed-by: Xisco Fauli <[email protected]>

diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
index 82a90719b25d..5ba02a4d6257 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx
@@ -526,6 +526,12 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf158661_blockSDT)
     xContentControlEnum = xContentControlEnumAccess->createEnumeration();
     xTextPortionRange.set(xContentControlEnum->nextElement(), uno::UNO_QUERY);
     CPPUNIT_ASSERT_EQUAL(u"Test"_ustr, xTextPortionRange->getString());
+
+    // tdf#170208: compatibilityMode14 document - emulate table placement
+    // TODO: the first table is also not correctly positioned
+
+    // table2's cell margin (in the first row) is zero, so compat14 table 
shifts by zero, not .19cm
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), 
getProperty<sal_Int32>(xTable, "LeftMargin"));
 }
 
 CPPUNIT_TEST_FIXTURE(Test, testSdt2Run)
diff --git a/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx 
b/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx
index 612cb33c0f6d..f6adfb364a51 100644
--- a/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx
+++ b/sw/source/writerfilter/dmapper/DomainMapperTableHandler.cxx
@@ -603,7 +603,18 @@ TableStyleSheetEntry * 
DomainMapperTableHandler::endTableGetTableStyle(TableInfo
 
         if (m_rDMapper_Impl.IsOOXMLImport() && (nMode < 0 || (0 < nMode && 
nMode <= 14)) && rInfo.nNestLevel == 1)
         {
-            const sal_Int32 nAdjustedMargin = nLeftMargin - 
rInfo.nLeftBorderDistance;
+            const sal_Int32 nMinLeftBorderDistance = aLeftBorder.LineWidth / 2;
+            sal_Int32 nLeftBorderDistance = rInfo.nLeftBorderDistance;
+            if (!m_aCellProperties.empty() && !m_aCellProperties[0].empty())
+            {
+                // only the border spacing of the first row affects the 
placement of the table
+                std::optional<PropertyMap::Property> aCellLeftBorderDistance
+                    = 
m_aCellProperties[0][0]->getProperty(PROP_LEFT_BORDER_DISTANCE);
+                if (aCellLeftBorderDistance)
+                    aCellLeftBorderDistance->second >>= nLeftBorderDistance;
+            }
+            nLeftBorderDistance = std::max(nMinLeftBorderDistance, 
nLeftBorderDistance);
+            const sal_Int32 nAdjustedMargin = nLeftMargin - 
nLeftBorderDistance;
             m_aTableProperties->Insert( PROP_LEFT_MARGIN, uno::Any( 
nAdjustedMargin ) );
         }
         else

Reply via email to