sw/qa/extras/rtfimport/data/165483.rtf            |   12 +++++
 sw/qa/extras/rtfimport/rtfimport.cxx              |   12 +++++
 sw/source/writerfilter/dmapper/DomainMapper.cxx   |   11 ++++
 sw/source/writerfilter/rtftok/rtfdocumentimpl.cxx |   51 +++++++++++++++-------
 sw/source/writerfilter/rtftok/rtfsprm.cxx         |    9 +++
 5 files changed, 80 insertions(+), 15 deletions(-)

New commits:
commit 62913746753044ff0045feed78912797ab458bfb
Author:     Oliver Specht <oliver.spe...@cib.de>
AuthorDate: Thu Feb 27 11:18:23 2025 +0100
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Wed Mar 12 10:31:10 2025 +0100

    tdf#165483 style inherits only repated properties
    
    Each attribute a style inherits from a parent style needs to be
    repeated at that style. Otherwise it is overwritten by a default
    attribute.
    
    Change-Id: I9cef60b0d1eaa16d212f091434e9896bfd4a44c8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182284
    Tested-by: Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>
    Tested-by: Jenkins
    Reviewed-by: Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182714
    Tested-by: allotropia jenkins <jenk...@allotropia.de>
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>

diff --git a/sw/qa/extras/rtfimport/data/165483.rtf 
b/sw/qa/extras/rtfimport/data/165483.rtf
new file mode 100755
index 000000000000..1c6eec96cdc9
--- /dev/null
+++ b/sw/qa/extras/rtfimport/data/165483.rtf
@@ -0,0 +1,12 @@
+{ tf1nsi
+{\stylesheet{s36 Normal;}
+{\*    s11\sl400\slmult1\sa100 \snext11 \ssemihidden \sunhideused Normal 
Table;}
+{      s12\sl400\slmult1\sa100 \snext11 \ssemihidden \sunhideused Normal Table 
Copy;}
+{      s96 \sbasedon12\snext196 Based On Table Normal Copy;}
+}
+{\s96 This text should have single line spacing and no spacing below 
paragraph. This text should have single line spacing and no spacing below 
paragraph. This text should have single line spacing and no spacing below 
paragraph. This text should have single line spacing and no spacing below 
paragraph. \par }
+{\s96 This text should have single line spacing and no spacing below 
paragraph. This text should have single line spacing and no spacing below 
paragraph. This text should have single line spacing and no spacing below 
paragraph. This text should have single line spacing and no spacing below 
paragraph. \par }
+{\s96 This text should have single line spacing and no spacing below 
paragraph. This text should have single line spacing and no spacing below 
paragraph. This text should have single line spacing and no spacing below 
paragraph. This text should have single line spacing and no spacing below 
paragraph. \par }
+{\s96 This text should have single line spacing and no spacing below 
paragraph. This text should have single line spacing and no spacing below 
paragraph. This text should have single line spacing and no spacing below 
paragraph. This text should have single line spacing and no spacing below 
paragraph. \par }
+
+}
diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx 
b/sw/qa/extras/rtfimport/rtfimport.cxx
index 34f49cae0de9..e9ff2f53b267 100644
--- a/sw/qa/extras/rtfimport/rtfimport.cxx
+++ b/sw/qa/extras/rtfimport/rtfimport.cxx
@@ -2001,6 +2001,18 @@ CPPUNIT_TEST_FIXTURE(Test, test165333Tdf)
     CPPUNIT_ASSERT_EQUAL(false, getProperty<bool>(xRun2, u"CharHidden"_ustr));
 }
 
+CPPUNIT_TEST_FIXTURE(Test, test165483Tdf)
+{
+    createSwDoc("165483.rtf");
+    uno::Reference<text::XTextRange> const xRun1(
+        getRun(uno::Reference<text::XTextRange>(getParagraphOrTable(1), 
uno::UNO_QUERY), 1));
+    uno::Reference<beans::XPropertySet> xStyle(
+        getStyles(u"ParagraphStyles"_ustr)->getByName(u"Based On Table Normal 
Copy"_ustr),
+        uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xRun1, 
u"ParaBottomMargin"_ustr));
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(xStyle, 
u"ParaBottomMargin"_ustr));
+}
+
 // tests should only be added to rtfIMPORT *if* they fail round-tripping in 
rtfEXPORT
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/writerfilter/dmapper/DomainMapper.cxx 
b/sw/source/writerfilter/dmapper/DomainMapper.cxx
index b6075e2b3810..a8fa5eb5e18e 100644
--- a/sw/source/writerfilter/dmapper/DomainMapper.cxx
+++ b/sw/source/writerfilter/dmapper/DomainMapper.cxx
@@ -4224,8 +4224,9 @@ void DomainMapper::ResetStyleProperties()
                                 pContext->Insert(ePropertyId, uno::Any(0l));
                             }
                             break;
+                        case PROP_PARA_BOTTOM_MARGIN:
                         case PROP_PARA_RIGHT_MARGIN:
-                            pContext->Insert(ePropertyId, uno::Any(0l));
+                            pContext->Insert(ePropertyId, 
uno::Any(sal_Int32(0)));
                             break;
                         case PROP_PARA_LAST_LINE_ADJUST:
                         case PROP_PARA_ADJUST:
@@ -4240,6 +4241,14 @@ void DomainMapper::ResetStyleProperties()
                         case PROP_FILL_COLOR:
                             pContext->Insert(ePropertyId, 
uno::Any(sal_Int32(COL_TRANSPARENT)));
                             break;
+                        case PROP_PARA_LINE_SPACING:
+                            {
+                                style::LineSpacing aLineSpacing;
+                                aLineSpacing.Mode = 
style::LineSpacingMode::PROP;
+                                aLineSpacing.Height = sal_Int32(100);
+                                pContext->Insert(ePropertyId, 
uno::Any(aLineSpacing));
+                            }
+                            break;
                         case INVALID:
                         default:
                             break;
diff --git a/sw/source/writerfilter/rtftok/rtfdocumentimpl.cxx 
b/sw/source/writerfilter/rtftok/rtfdocumentimpl.cxx
index 431bdb60d90d..bdcd10705001 100644
--- a/sw/source/writerfilter/rtftok/rtfdocumentimpl.cxx
+++ b/sw/source/writerfilter/rtftok/rtfdocumentimpl.cxx
@@ -275,6 +275,32 @@ static void lcl_DestinationToMath(OUStringBuffer* 
pDestinationText,
     rMathBuffer.appendClosingTag(M_TOKEN(r));
 }
 
+static writerfilter::Reference<Properties>::Pointer_t
+lcl_findParentStyle(std::shared_ptr<RTFReferenceTable::Entries_t> 
pStyleTableEntries,
+                    RTFValue::Pointer_t const pStyle, const OUString& rBase)
+{
+    writerfilter::Reference<Properties>::Pointer_t ret;
+    if (!pStyle)
+        return ret;
+    auto itParent = pStyleTableEntries->begin();
+    while (itParent != pStyleTableEntries->end())
+    {
+        RTFValue::Pointer_t const pParentName
+            = static_cast<RTFReferenceProperties&>(*itParent->second)
+                  .getSprms()
+                  .find(NS_ooxml::LN_CT_Style_name);
+        if (pParentName && pParentName->getString().equals(rBase)
+            && !pParentName->getString().equals(pStyle->getString()))
+            break;
+        ++itParent;
+    }
+    if (itParent != pStyleTableEntries->end())
+    {
+        ret = itParent->second;
+    }
+    return ret;
+}
+
 RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& 
xContext,
                                  uno::Reference<io::XInputStream> const& 
xInputStream,
                                  rtl::Reference<SwXTextDocument> const& 
xDstDoc,
@@ -527,6 +553,7 @@ RTFDocumentImpl::getProperties(const RTFSprms& rAttributes, 
RTFSprms const& rSpr
     if (!m_aStates.empty())
         nStyle = m_aStates.top().getCurrentStyleIndex();
     auto it = m_pStyleTableEntries->find(nStyle);
+
     if (it != m_pStyleTableEntries->end())
     {
         // cloneAndDeduplicate() wants to know about only a single "style", so
@@ -2185,12 +2212,9 @@ RTFError RTFDocumentImpl::pushState()
 
 writerfilter::Reference<Properties>::Pointer_t 
RTFDocumentImpl::createStyleProperties()
 {
-    int nBasedOn = 0;
     RTFValue::Pointer_t pBasedOn
         = m_aStates.top().getTableSprms().find(NS_ooxml::LN_CT_Style_basedOn);
-    if (pBasedOn)
-        nBasedOn = pBasedOn->getInt();
-    if (nBasedOn == 0)
+    if (!pBasedOn)
     {
         // No parent style, then mimic what Word does: ignore attributes which
         // would set a margin as formatting, but with a default value.
@@ -2243,13 +2267,13 @@ RTFReferenceTable::Entries_t 
RTFDocumentImpl::deduplicateStyleTable()
                 NS_ooxml::LN_CT_Style_basedOn));
         if (pBasedOn)
         {
-            int const nBasedOn(pBasedOn->getInt());
-            // don't deduplicate yourself - especially a potential problem for 
the default style.
-            if (it.first == nBasedOn)
-                continue;
+            RTFValue::Pointer_t const pStyleName(
+                static_cast<RTFReferenceProperties&>(*pStyle).getSprms().find(
+                    NS_ooxml::LN_CT_Style_name));
+            writerfilter::Reference<Properties>::Pointer_t parentStyle
+                = lcl_findParentStyle(m_pStyleTableEntries, pStyleName, 
pBasedOn->getString());
 
-            auto const itParent(m_pStyleTableEntries->find(nBasedOn)); // 
definition as read!
-            if (itParent != m_pStyleTableEntries->end())
+            if (parentStyle.is())
             {
                 auto const pStyleType(
                     
static_cast<RTFReferenceProperties&>(*pStyle).getAttributes().find(
@@ -2258,20 +2282,19 @@ RTFReferenceTable::Entries_t 
RTFDocumentImpl::deduplicateStyleTable()
                 int const nStyleType(pStyleType->getInt());
                 RTFSprms sprms(
                     
static_cast<RTFReferenceProperties&>(*pStyle).getSprms().cloneAndDeduplicate(
-                        
static_cast<RTFReferenceProperties&>(*itParent->second).getSprms(),
-                        nStyleType));
+                        
static_cast<RTFReferenceProperties&>(*parentStyle).getSprms(), nStyleType));
                 RTFSprms attributes(
                     static_cast<RTFReferenceProperties&>(*pStyle)
                         .getAttributes()
                         .cloneAndDeduplicate(
-                            
static_cast<RTFReferenceProperties&>(*itParent->second).getAttributes(),
+                            
static_cast<RTFReferenceProperties&>(*parentStyle).getAttributes(),
                             nStyleType));
 
                 ret[it.first] = new 
RTFReferenceProperties(std::move(attributes), std::move(sprms));
             }
             else
             {
-                SAL_WARN("writerfilter.rtf", "parent style not found: " << 
nBasedOn);
+                SAL_WARN("writerfilter.rtf", "parent style not found: " << 
pBasedOn->getString());
             }
         }
     }
diff --git a/sw/source/writerfilter/rtftok/rtfsprm.cxx 
b/sw/source/writerfilter/rtftok/rtfsprm.cxx
index 50035c086e23..fc2d5975d339 100644
--- a/sw/source/writerfilter/rtftok/rtfsprm.cxx
+++ b/sw/source/writerfilter/rtftok/rtfsprm.cxx
@@ -182,6 +182,14 @@ static RTFValue::Pointer_t getDefaultSPRM(Id const id, Id 
nStyleType)
     {
         switch (id)
         {
+            case NS_ooxml::LN_CT_PPrBase_spacing:
+            {
+                RTFSprms aAttributes;
+                RTFSprms aSprms;
+                aAttributes.set(NS_ooxml::LN_CT_Spacing_after, new 
RTFValue(0l));
+                return new RTFValue(aAttributes, aSprms);
+            }
+            break;
             case NS_ooxml::LN_CT_Spacing_before:
             case NS_ooxml::LN_CT_Spacing_after:
             case NS_ooxml::LN_CT_Ind_left:
@@ -224,6 +232,7 @@ static bool isSPRMDeduplicateDenylist(Id nId, RTFSprms* 
pDirect)
 {
     switch (nId)
     {
+        case NS_ooxml::LN_CT_Style_type: //never remove the style type
         // See the NS_ooxml::LN_CT_PPrBase_tabs handler in DomainMapper,
         // deduplication is explicitly not wanted for these tokens.
         case NS_ooxml::LN_CT_TabStop_val:

Reply via email to