sw/inc/SwStyleNameMapper.hxx              |    2 -
 sw/qa/extras/layout/layout3.cxx           |    2 -
 sw/qa/extras/ooxmlexport/ooxmlexport9.cxx |    4 +--
 sw/qa/extras/ooxmlimport/ooxmlimport.cxx  |    2 -
 sw/qa/extras/rtfexport/rtfexport4.cxx     |    3 --
 sw/qa/extras/uiwriter/uiwriter2.cxx       |    3 --
 sw/source/core/doc/SwStyleNameMapper.cxx  |   31 +++++++++++++++++++------
 sw/source/core/unocore/unostyle.cxx       |   37 +++++++++++++++++++-----------
 8 files changed, 55 insertions(+), 29 deletions(-)

New commits:
commit bd727654ec8cc339292072b42073e57d566cc220
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Thu Dec 5 12:22:14 2024 +0100
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Fri Dec 6 14:24:32 2024 +0100

    tdf#159549 sw: fix ODF import of newly colliding Body Text styles
    
    Commit c83d241effbd09491e9f96d3e435ab91700f58b0 "tdf#154933 Rename "Text
    Body" para style to "Body Text"" introduced a regression when importing
    certain ODF documents, but the problem is actually pre-existing.
    
    What happens is that first the built-in "Text body" style is created,
    and then a non-built-in style with the same translated name as "Text
    body" is imported, and instead of creating a new style, the built-in one
    is found and used, and so its properties are overwritten.
    
    The root cause is that SwStyleNameMapper::FillProgName() and in
    particular SwStyleNameMapper::FillUIName() are defined poorly, ever
    since they were introduced in 2001 in commit
    4fbc9dd48b7cebb304010e7337b1bbc3936c7923
    
    It becomes obvious relatively quickly that the way style names work is
    that at the UNO API level, the "ProgName" (internal, non-localised)
    names are used, and at the core document level, the "UIName" (localised)
    names are used.
    
    This is in itself questionable - why is the translation from ProgName to
    UIName not done in the UI? - but also very expensive to change now.
    
    So then the UNO services are responsible for translating between
    ProgName and UIName.
    
    But the 2 functions don't do that properly; both need to check if the
    given name is a known ProgName *or* a known UIName, and rename it in
    case it collides with a known target name; also the 2 functions need to
    cancel each other out, not add " (user)" at the end in both directions.
    
    Fixing this causes numerous tests to fail, due to:
    
    1. the UNO services calling themselves with already converted style
       names, which are then translated a second time, which fails now.
       (or calling the wrong function like SwXStyleFamily::getByIndex())
    
    2. many tests call the UNO API with UINames instead of ProgNames
    
    3. somehow the writerfilter import is also changed, causing failures in
       e.g. testTdf113182 and testTdf104492
    
    4. buggy code elsewhere (lcl_getUsedPageStyles()), problem similar to
       1., for PageDescs
    
    5. potentially more buggy code yet to be discovered (definitely table
       styles, forgot which test that was)
    
    So limit this fix for now to only paragraph styles, and don't do it in
    writerfilter import, now at least sw.check passes.
    
    Change-Id: I5cbdf3e174622e83f9af8787c3671b88c0e37bac
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/177858
    Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de>
    Tested-by: Jenkins

diff --git a/sw/inc/SwStyleNameMapper.hxx b/sw/inc/SwStyleNameMapper.hxx
index 0fdfb381711a..4a3b0f1a582b 100644
--- a/sw/inc/SwStyleNameMapper.hxx
+++ b/sw/inc/SwStyleNameMapper.hxx
@@ -89,7 +89,7 @@ public:
     // This gets the UI Name from the programmatic name
     static const OUString& GetUIName(const OUString& rName, 
SwGetPoolIdFromName);
     static         void FillUIName(const OUString& rName, OUString& rFillName,
-                            SwGetPoolIdFromName);
+                            SwGetPoolIdFromName, bool bBugfix = false);
 
     // Get the programmatic Name from the UI name
     static const OUString& GetProgName(const OUString& rName,
diff --git a/sw/qa/extras/layout/layout3.cxx b/sw/qa/extras/layout/layout3.cxx
index ef5e948d5abf..af6dac583f29 100644
--- a/sw/qa/extras/layout/layout3.cxx
+++ b/sw/qa/extras/layout/layout3.cxx
@@ -794,7 +794,7 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter3, testTdf155177)
     createSwDoc("tdf155177-1-min.odt");
 
     uno::Reference<beans::XPropertySet> xStyle(
-        getStyles(u"ParagraphStyles"_ustr)->getByName(u"Body Text"_ustr), 
uno::UNO_QUERY_THROW);
+        getStyles(u"ParagraphStyles"_ustr)->getByName(u"Text body"_ustr), 
uno::UNO_QUERY_THROW);
     CPPUNIT_ASSERT_EQUAL(sal_Int32(210), getProperty<sal_Int32>(xStyle, 
u"ParaTopMargin"_ustr));
 
     {
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
index bf12d0178b62..c3e18bfbae48 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
@@ -481,7 +481,7 @@ DECLARE_OOXMLEXPORT_TEST(testKern, "kern.docx")
     // This failed: kerning was also enabled for the second paragraph.
     CPPUNIT_ASSERT(!getProperty<bool>(getRun(getParagraph(2), 1), 
u"CharAutoKerning"_ustr));
 
-    uno::Reference<beans::XPropertySet> 
xStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Default Paragraph 
Style"_ustr), uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> 
xStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Standard"_ustr), 
uno::UNO_QUERY);
     //tdf107801: kerning normally isn't enabled by default for .docx
     CPPUNIT_ASSERT_EQUAL_MESSAGE("AutoKern should be false", false, 
getProperty<bool>(xStyle, u"CharAutoKerning"_ustr));
 }
@@ -491,7 +491,7 @@ DECLARE_OOXMLEXPORT_TEST(testTdf89377, 
"tdf89377_tableWithBreakBeforeParaStyle.d
     // the paragraph style should set table's text-flow break-before-page
     CPPUNIT_ASSERT_EQUAL( 3, getPages() );
 
-    uno::Reference<beans::XPropertySet> 
xStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Default Paragraph 
Style"_ustr), uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> 
xStyle(getStyles(u"ParagraphStyles"_ustr)->getByName(u"Standard"_ustr), 
uno::UNO_QUERY);
     //tdf107801: kerning info wasn't exported previously.
     CPPUNIT_ASSERT_EQUAL_MESSAGE("AutoKern should be true", true, 
getProperty<bool>(xStyle, u"CharAutoKerning"_ustr));
 }
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx 
b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
index a30a29d397d7..13490dff0ffe 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport.cxx
@@ -734,7 +734,7 @@ CPPUNIT_TEST_FIXTURE(Test, testN820504)
     uno::Reference<style::XStyleFamiliesSupplier> 
xFamiliesSupplier(mxComponent, uno::UNO_QUERY);
     uno::Reference<container::XNameAccess> xFamiliesAccess = 
xFamiliesSupplier->getStyleFamilies();
     uno::Reference<container::XNameAccess> 
xStylesAccess(xFamiliesAccess->getByName(u"ParagraphStyles"_ustr), 
uno::UNO_QUERY);
-    uno::Reference<beans::XPropertySet> 
xStyle(xStylesAccess->getByName(u"Default Paragraph Style"_ustr), 
uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> 
xStyle(xStylesAccess->getByName(u"Standard"_ustr), uno::UNO_QUERY);
     // The problem was that the CharColor was set to AUTO (-1) even if we have 
some default char color set
     CPPUNIT_ASSERT_EQUAL(Color(0x3da7bb), getProperty<Color>(xStyle, 
u"CharColor"_ustr));
 
diff --git a/sw/qa/extras/rtfexport/rtfexport4.cxx 
b/sw/qa/extras/rtfexport/rtfexport4.cxx
index 29e3d4201860..adc6c8d0aa89 100644
--- a/sw/qa/extras/rtfexport/rtfexport4.cxx
+++ b/sw/qa/extras/rtfexport/rtfexport4.cxx
@@ -681,8 +681,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf136587_noStyleName)
                              getProperty<sal_Int16>(xStyleProps, 
u"ParaAdjust"_ustr));
 
         // The problem was that the default style wasn't imported at all, so 
the fontsize was only 12.
-        xStyleProps.set(paragraphStyles->getByName(u"Default Paragraph 
Style"_ustr),
-                        uno::UNO_QUERY_THROW);
+        xStyleProps.set(paragraphStyles->getByName(u"Standard"_ustr), 
uno::UNO_QUERY_THROW);
         CPPUNIT_ASSERT_EQUAL(32.0f, getProperty<float>(xStyleProps, 
u"CharHeight"_ustr));
     };
     createSwDoc("tdf136587_noStyleName.rtf");
diff --git a/sw/qa/extras/uiwriter/uiwriter2.cxx 
b/sw/qa/extras/uiwriter/uiwriter2.cxx
index 59320a62709d..b70fea7ce62a 100644
--- a/sw/qa/extras/uiwriter/uiwriter2.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter2.cxx
@@ -2578,8 +2578,7 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest2, 
testRTLparaStyle_LocaleArabic)
     saveAndReload(u"Office Open XML Text"_ustr);
 
     uno::Reference<beans::XPropertySet> xPageStyle(
-        getStyles(u"ParagraphStyles"_ustr)->getByName(u"Default Paragraph 
Style"_ustr),
-        uno::UNO_QUERY_THROW);
+        getStyles(u"ParagraphStyles"_ustr)->getByName(u"Standard"_ustr), 
uno::UNO_QUERY_THROW);
     // Test the text Direction value for the -none- based paragraph styles
     CPPUNIT_ASSERT_EQUAL_MESSAGE("RTL Writing Mode", sal_Int32(1),
                                  getProperty<sal_Int32>(xPageStyle, 
u"WritingMode"_ustr));
diff --git a/sw/source/core/doc/SwStyleNameMapper.cxx 
b/sw/source/core/doc/SwStyleNameMapper.cxx
index b047782a4221..554ab750fe49 100644
--- a/sw/source/core/doc/SwStyleNameMapper.cxx
+++ b/sw/source/core/doc/SwStyleNameMapper.cxx
@@ -263,10 +263,18 @@ void SwStyleNameMapper::FillProgName(
         rFillName = rName;
         if (nId == USHRT_MAX )
         {
-            // It isn't ...make sure the suffix isn't already " (user)"...if 
it is,
-            // we need to add another one
-            if (lcl_SuffixIsUser(rFillName))
-                rFillName += " (user)";
+            if (eFlags == SwGetPoolIdFromName::TxtColl)
+            {
+                // check if it has a " (user)" suffix, if so remove it
+                lcl_CheckSuffixAndDelete(rFillName);
+            }
+            else // FIXME don't do this
+            {
+                // It isn't ...make sure the suffix isn't already " 
(user)"...if it is,
+                // we need to add another one
+                if (lcl_SuffixIsUser(rFillName))
+                    rFillName += " (user)";
+            }
         }
         else
         {
@@ -287,7 +295,7 @@ void SwStyleNameMapper::FillProgName(
 // Get the UI name from the programmatic name in rName and put it into 
rFillName
 void SwStyleNameMapper::FillUIName(
         const OUString& rName, OUString& rFillName,
-        SwGetPoolIdFromName const eFlags)
+        SwGetPoolIdFromName const eFlags, bool const bBugfix)
 {
     OUString aName = rName;
     if (eFlags == SwGetPoolIdFromName::ChrFmt && rName == "Standard")
@@ -297,8 +305,17 @@ void SwStyleNameMapper::FillUIName(
     if ( nId == USHRT_MAX )
     {
         rFillName = aName;
-        // aName isn't in our Prog name table...check if it has a " (user)" 
suffix, if so remove it
-        lcl_CheckSuffixAndDelete ( rFillName );
+        if (eFlags != SwGetPoolIdFromName::TxtColl || // FIXME do it for all 
ids
+            !bBugfix || // TODO why does it change DOCX imports
+            GetPoolIdFromUIName(aName, eFlags) == USHRT_MAX)
+        {
+            // aName isn't in our Prog name table...check if it has a " 
(user)" suffix, if so remove it
+            lcl_CheckSuffixAndDelete(rFillName);
+        }
+        else
+        {
+            rFillName += " (user)";
+        }
     }
     else
     {
diff --git a/sw/source/core/unocore/unostyle.cxx 
b/sw/source/core/unocore/unostyle.cxx
index 2dfb37aa7a12..67facb9fcf58 100644
--- a/sw/source/core/unocore/unostyle.cxx
+++ b/sw/source/core/unocore/unostyle.cxx
@@ -915,7 +915,7 @@ uno::Any SwXStyleFamily::getByIndex(sal_Int32 nIndex)
     OUString sStyleName;
     try
     {
-        SwStyleNameMapper::FillUIName(m_rEntry.translateIndex(nIndex), 
sStyleName);
+        SwStyleNameMapper::FillProgName(m_rEntry.translateIndex(nIndex), 
sStyleName);
     } catch(...) {}
     if (sStyleName.isEmpty())
         GetCountOrName(&sStyleName, nIndex);
@@ -957,7 +957,8 @@ rtl::Reference<SwXBaseStyle> 
SwXStyleFamily::getStyleByName(const OUString& rNam
 {
     SolarMutexGuard aGuard;
     OUString sStyleName;
-    SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId());
+    SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId(),
+            m_pDocShell && !m_pDocShell->GetDoc()->IsInWriterfilterImport());
     if(!m_pBasePool)
         throw uno::RuntimeException();
     SfxStyleSheetBase* pBase = m_pBasePool->Find(sStyleName, 
m_rEntry.family());
@@ -1012,7 +1013,8 @@ sal_Bool SwXStyleFamily::hasByName(const OUString& rName)
     if(!m_pBasePool)
         throw uno::RuntimeException();
     OUString sStyleName;
-    SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId());
+    SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId(),
+            m_pDocShell && !m_pDocShell->GetDoc()->IsInWriterfilterImport());
     SfxStyleSheetBase* pBase = m_pBasePool->Find(sStyleName, 
m_rEntry.family());
     return nullptr != pBase;
 }
@@ -1023,7 +1025,8 @@ void SwXStyleFamily::insertStyleByName(const OUString& 
rName, const rtl::Referen
     if(!m_pBasePool)
         throw uno::RuntimeException();
     OUString sStyleName;
-    SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId());
+    SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId(),
+            m_pDocShell && !m_pDocShell->GetDoc()->IsInWriterfilterImport());
     SfxStyleSheetBase* pBase = m_pBasePool->Find(sStyleName, 
m_rEntry.family());
     if (pBase)
         throw container::ElementExistException();
@@ -1036,7 +1039,8 @@ void SwXStyleFamily::insertByName(const OUString& rName, 
const uno::Any& rElemen
     if(!m_pBasePool)
         throw uno::RuntimeException();
     OUString sStyleName;
-    SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId());
+    SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId(),
+            m_pDocShell && !m_pDocShell->GetDoc()->IsInWriterfilterImport());
     SfxStyleSheetBase* pBase = m_pBasePool->Find(sStyleName, 
m_rEntry.family());
     if (pBase)
         throw container::ElementExistException();
@@ -1099,7 +1103,8 @@ void SwXStyleFamily::replaceByName(const OUString& rName, 
const uno::Any& rEleme
     if(!m_pBasePool)
         throw uno::RuntimeException();
     OUString sStyleName;
-    SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId());
+    SwStyleNameMapper::FillUIName(rName, sStyleName, m_rEntry.poolId(),
+            m_pDocShell && !m_pDocShell->GetDoc()->IsInWriterfilterImport());
     SfxStyleSheetBase* pBase = m_pBasePool->Find(sStyleName, 
m_rEntry.family());
     // replacements only for userdefined styles
     if(!pBase)
@@ -1160,7 +1165,8 @@ void SwXStyleFamily::removeByName(const OUString& rName)
     if(!m_pBasePool)
         throw uno::RuntimeException();
     OUString sName;
-    SwStyleNameMapper::FillUIName(rName, sName, m_rEntry.poolId());
+    SwStyleNameMapper::FillUIName(rName, sName, m_rEntry.poolId(),
+            m_pDocShell && !m_pDocShell->GetDoc()->IsInWriterfilterImport());
     SfxStyleSheetBase* pBase = m_pBasePool->Find(sName, m_rEntry.family());
     if(!pBase)
         throw container::NoSuchElementException();
@@ -1447,7 +1453,8 @@ void SwXStyle::setParentStyle(const OUString& 
rParentStyle)
 {
     SolarMutexGuard aGuard;
     OUString sParentStyle;
-    SwStyleNameMapper::FillUIName(rParentStyle, sParentStyle, 
lcl_GetSwEnumFromSfxEnum ( m_rEntry.family()) );
+    SwStyleNameMapper::FillUIName(rParentStyle, sParentStyle, 
lcl_GetSwEnumFromSfxEnum ( m_rEntry.family()),
+            m_pDoc && !m_pDoc->IsInWriterfilterImport());
     if(!m_pBasePool)
     {
         if(!m_bIsDescriptor)
@@ -1455,7 +1462,7 @@ void SwXStyle::setParentStyle(const OUString& 
rParentStyle)
         m_sParentStyleName = sParentStyle;
         try
         {
-            const auto aAny = m_xStyleFamily->getByName(sParentStyle);
+            const auto aAny = m_xStyleFamily->getByName(rParentStyle);
             m_xStyleData = aAny.get<decltype(m_xStyleData)>();
         }
         catch(...)
@@ -1753,7 +1760,8 @@ void 
SwXStyle::SetPropertyValue<FN_UNO_FOLLOW_STYLE>(const SfxItemPropertyMapEnt
         return;
     const auto sValue(rValue.get<OUString>());
     OUString aString;
-    SwStyleNameMapper::FillUIName(sValue, aString, m_rEntry.poolId());
+    SwStyleNameMapper::FillUIName(sValue, aString, m_rEntry.poolId(),
+            m_pDoc && !m_pDoc->IsInWriterfilterImport());
     o_rStyleBase.getNewBase()->SetFollow(aString);
 }
 
@@ -1767,7 +1775,8 @@ void SwXStyle::SetPropertyValue<FN_UNO_LINK_STYLE>(const 
SfxItemPropertyMapEntry
         return;
     const auto sValue(rValue.get<OUString>());
     OUString aString;
-    SwStyleNameMapper::FillUIName(sValue, aString, m_rEntry.poolId());
+    SwStyleNameMapper::FillUIName(sValue, aString, m_rEntry.poolId(),
+            m_pDoc && !m_pDoc->IsInWriterfilterImport());
     o_rStyleBase.getNewBase()->SetLink(aString);
 }
 
@@ -1849,7 +1858,8 @@ void 
SwXStyle::SetPropertyValue<FN_UNO_PARA_STYLE_CONDITIONS>(const SfxItemPrope
         const OUString sValue(rNamedValue.Value.get<OUString>());
         // get UI style name from programmatic style name
         OUString aStyleName;
-        SwStyleNameMapper::FillUIName(sValue, aStyleName, 
lcl_GetSwEnumFromSfxEnum(m_rEntry.family()));
+        SwStyleNameMapper::FillUIName(sValue, aStyleName, 
lcl_GetSwEnumFromSfxEnum(m_rEntry.family()),
+            m_pDoc && !m_pDoc->IsInWriterfilterImport());
 
         // check for correct context and style name
         const auto nIdx(GetCommandContextIndex(rNamedValue.Name));
@@ -1893,7 +1903,8 @@ void 
SwXStyle::SetPropertyValue<SID_SWREGISTER_COLLECTION>(const SfxItemProperty
     aReg.SetWhich(SID_SWREGISTER_MODE);
     o_rStyleBase.GetItemSet().Put(aReg);
     OUString aString;
-    SwStyleNameMapper::FillUIName(sName, aString, 
SwGetPoolIdFromName::TxtColl);
+    SwStyleNameMapper::FillUIName(sName, aString, SwGetPoolIdFromName::TxtColl,
+            m_pDoc && !m_pDoc->IsInWriterfilterImport());
     o_rStyleBase.GetItemSet().Put(SfxStringItem(SID_SWREGISTER_COLLECTION, 
aString ) );
 }
 template<>

Reply via email to