sw/qa/extras/ooxmlexport/ooxmlexport22.cxx           |   10 +++++-----
 sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx |    8 +++++++-
 sw/source/writerfilter/dmapper/StyleSheetTable.cxx   |   10 ++++++++++
 3 files changed, 22 insertions(+), 6 deletions(-)

New commits:
commit 3abee091cd10f634b00e3bca733f3deff1dafd86
Author:     Justin Luth <jl...@mail.com>
AuthorDate: Tue Aug 12 09:25:09 2025 -0400
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Tue Aug 19 16:50:03 2025 +0200

    tdf#167721 writerfilter: adjust disabled leftChars by hangingChars
    
    Sixth Problem - in a very inconsistent move, with hangingChars
    MS Word ignores the fact that w:leftChars=0 has been disabled,
    (or even never defined)
    and simply treats it as a zero margin,
    even if a w:left margin has been defined.
    
    I imagine this is actually a bug in MS Word.
    That bug is seen in MS Word 2003 / 2010
    and still exists in MS Word 2024.
    
    There are even weirder things happening with styles,
    but when I actually apply a style to a paragraph,
    then that paragraph gets different margin properties
    than what is shown for the style,
    so probably best not to attempt any changes to styles at all.
    
    make CppunitTest_sw_ooxmlexport22 \
        CPPUNIT_TEST_NAME=testTdf167721_chUnits
    
    Change-Id: I689853f631aa1cb5e144e43e75672b177fd81537
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189437
    Reviewed-by: Justin Luth <jl...@mail.com>
    Tested-by: Jenkins
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189554

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
index 6f3e412bbeba..a929eb6faad0 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
@@ -245,7 +245,9 @@ DECLARE_OOXMLEXPORT_TEST(testTdf167721_chUnits, 
"tdf167721_chUnits.docx")
         = getProperty<css::beans::Pair<double, sal_Int16>>(xPara, 
u"ParaFirstLineIndentUnit"_ustr);
     CPPUNIT_ASSERT_EQUAL(double(-1), aFirstCh.First);
 
-    CPPUNIT_ASSERT_EQUAL(sal_Int32(5001), getProperty<sal_Int32>(xPara, 
u"ParaLeftMargin"_ustr));
+    // oddly, w:left is always ignored by MS Word in special case with 
hangingChars indent
+    aLeftCh = getProperty<css::beans::Pair<double, sal_Int16>>(xPara, 
u"ParaLeftMarginUnit"_ustr);
+    CPPUNIT_ASSERT_EQUAL(double(1), aLeftCh.First);
 
     aRightCh = getProperty<css::beans::Pair<double, sal_Int16>>(xPara, 
u"ParaRightMarginUnit"_ustr);
     CPPUNIT_ASSERT_EQUAL(double(2), aRightCh.First);
diff --git a/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx 
b/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx
index 6a23771998f1..0765810528ef 100644
--- a/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx
+++ b/sw/source/writerfilter/dmapper/DomainMapper_Impl.cxx
@@ -3160,9 +3160,15 @@ void DomainMapper_Impl::finishParagraph( const 
PropertyMapPtr& pPropertyMap, con
                         // tdf#83844: DOCX stores left and leftChars 
differently with hanging
                         // indentation. Character-based hanging indentation 
must be pre-added
                         // to the left margin here.
-                        if (bLeftChSet && stFirstCh.First < 0.0)
+
+                        // tdf#167721: Oddball MS Word implementation:
+                        // Even if LeftChars is disabled/undefined and a 
w:left is provided,
+                        // when a hangingChars is also provided
+                        // then the w:left is ignored and treated as a zero.
+                        if (stFirstCh.First < 0.0)
                         {
                             stLeftCh.First -= stFirstCh.First;
+                            bLeftChSet = true;
                         }
 
                         if (bLeftChSet)
commit 8a11beb71eff1b4c7fa2a4b61394cec825e7a804
Author:     Justin Luth <jl...@mail.com>
AuthorDate: Sat Aug 9 10:40:42 2025 -0400
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Tue Aug 19 16:49:48 2025 +0200

    tdf#167721 writerfilter styles: adjust leftChars by hangingChars
    
    Fifth Problem - styles import needs to adjust the left margin
    just like the paragraph import does.
    
    The way MS implements "hanging"
    is that w:hanging defines where the first line starts
    and w:left defines how much further the remaining lines start.
    
    This is opposed to "firstLine"
    where w:firstLine defines the additional indent for the first line
    and w:left defines where the entire paragraph's indent.
    
    LO's implementation is much nicer, where the left margin
    always defines the entire paragraph's indent.
    
    make CppunitTest_sw_ooxmlexport22 \
        CPPUNIT_TEST_NAME=testTdf167721_chUnits
    
    Change-Id: I6ac4b49350d33d31d0948530910b4d4712bdc403
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189269
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189553

diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
index f6765cab81ea..6f3e412bbeba 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
@@ -208,7 +208,7 @@ CPPUNIT_TEST_FIXTURE(Test, 
testTdf166553_paraStyleAfterBreak)
     CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD, getProperty<float>(xPara, 
u"CharWeight"_ustr));
 }
 
-CPPUNIT_TEST_FIXTURE(Test, testTdf167721_chUnits)
+DECLARE_OOXMLEXPORT_TEST(testTdf167721_chUnits, "tdf167721_chUnits.docx")
 {
     // given a document that specifies some margins using Ch-based Left/Right 
indentation
     // where w:rightChars is inherited from the parent styles - so it 
overrides w:right
@@ -220,8 +220,6 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf167721_chUnits)
     // inherited formatting from the style chain in styles.xml
     //     <w:ind w:rightChars="200" (2 ic) w:hangingChars=400 (4 ic)
     //            w:leftChars="300" (3 ic) w:left="2834"/> (5 cm)
-    createSwDoc("tdf167721_chUnits.docx");
-    // saveAndReload(mpFilter);
 
     // Test the style 
#############################################################################
     uno::Reference<beans::XPropertySet> xStyle(
@@ -234,7 +232,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf167721_chUnits)
 
     auto aLeftCh
         = getProperty<css::beans::Pair<double, sal_Int16>>(xStyle, 
u"ParaLeftMarginUnit"_ustr);
-    CPPUNIT_ASSERT_EQUAL(double(3), aLeftCh.First);
+    CPPUNIT_ASSERT_EQUAL(double(7), aLeftCh.First);
 
     auto aRightCh
         = getProperty<css::beans::Pair<double, sal_Int16>>(xStyle, 
u"ParaRightMarginUnit"_ustr);
diff --git a/sw/source/writerfilter/dmapper/StyleSheetTable.cxx 
b/sw/source/writerfilter/dmapper/StyleSheetTable.cxx
index bbd0b0c35b1c..9f5fe3dd9955 100644
--- a/sw/source/writerfilter/dmapper/StyleSheetTable.cxx
+++ b/sw/source/writerfilter/dmapper/StyleSheetTable.cxx
@@ -1433,6 +1433,16 @@ void StyleSheetTable::ApplyStyleSheetsImpl(const 
FontTablePtr& rFontTable, std::
                                             == 
getPropertyName(PROP_PARA_FIRST_LINE_INDENT_UNIT);
                                     });
                                 }
+
+                                // hanging margins need to alter the left 
margin
+                                if (bLeftChSet && stFirstCh.First < 0.0)
+                                {
+                                    stLeftCh.First -= stFirstCh.First;
+                                    beans::PropertyValue aPV(
+                                        
getPropertyName(PROP_PARA_LEFT_MARGIN_UNIT), 0,
+                                        uno::Any(stLeftCh), 
beans::PropertyState_DIRECT_VALUE);
+                                    aPropValues.push_back(aPV);
+                                }
                             }
 
                             if (bFirstSet && bFirstChSet)

Reply via email to