[Libreoffice-commits] core.git: sw/qa writerfilter/source

Justin Luth (via logerrit) logerrit at kemper.freedesktop.org
Thu Jul 8 11:16:41 UTC 2021


 sw/qa/extras/ooxmlexport/data/tdf141966_chapterNumberTortureTest.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport16.cxx                            |   19 +++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx                     |   56 ++++++++--
 writerfilter/source/dmapper/DomainMapper_Impl.hxx                     |    2 
 4 files changed, 71 insertions(+), 6 deletions(-)

New commits:
commit bedd73ea578ad01171536ee90d22249fa221d2d6
Author:     Justin Luth <justin_luth at sil.org>
AuthorDate: Fri Apr 30 13:01:29 2021 +0200
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Jul 8 13:16:06 2021 +0200

    tdf#141964 writerfilter CN: get paragraph and inherited listLevel
    
    Just like numId, listLevel is inherited from parent styles.
    This was totally missing. Even the direct formatting of
    a listLevel value was ignored (although that case would
    be rare, because usually both numId and listLevel are defined
    together).
    
    It seems like the most fundamental basics of our numbering
    import are wrong. EXTREMELY DANGEROUS TERRITORY,
    although this particular change ought to be quite safe.
    
    Change-Id: Ia3cbd941a0a90a932938597e0797ee8e2b0aca6c
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115257
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <justin_luth at sil.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>

diff --git a/sw/qa/extras/ooxmlexport/data/tdf141966_chapterNumberTortureTest.docx b/sw/qa/extras/ooxmlexport/data/tdf141966_chapterNumberTortureTest.docx
new file mode 100644
index 000000000000..808a70846617
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf141966_chapterNumberTortureTest.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
index 8ec840b3b479..7ef26bb13b4c 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx
@@ -151,6 +151,25 @@ DECLARE_OOXMLEXPORT_TEST(testTdf141966_chapterNumbering, "tdf141966_chapterNumbe
     CPPUNIT_ASSERT_EQUAL(OUString("2nd"), getProperty<OUString>(xPara, "ListLabelString"));
 }
 
+DECLARE_OOXMLEXPORT_TEST(testTdf141966_chapterNumberTortureTest, "tdf141966_chapterNumberTortureTest.docx")
+{
+    // There is no point in identifying what the wrong values where in this test,
+    //because EVERYTHING was wrong, and MANY different fixes are required to solve the problems.
+    uno::Reference<beans::XPropertySet> xPara(getParagraph(1, "No numId in style or paragraph"), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xPara, "ListLabelString"));
+
+    xPara.set(getParagraph(2, "Paragraph cancels numbering(0)"), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString(""), getProperty<OUString>(xPara, "ListLabelString"));
+
+    xPara.set(getParagraph(3, "First numbered line"), uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(OUString("1st.i.a.1.I"), getProperty<OUString>(xPara, "ListLabelString"));
+
+    xPara.set(getParagraph(7, "inheritOnly: inherit outlineLvl and listLvl."), uno::UNO_QUERY);
+    // 2nd.iii in MS Word 2003.  2nd.ii in MS Word 2010/2016 where para5 is not numbered. Why not?
+    CPPUNIT_ASSERT_EQUAL(OUString("2nd.iii"), getProperty<OUString>(xPara, "ListLabelString"));
+    CPPUNIT_ASSERT_EQUAL(sal_Int16(1), getProperty<sal_Int16>(xPara, "NumberingLevel")); // Level 2
+}
+
 DECLARE_OOXMLEXPORT_TEST(testTdf132752, "tdf132752.docx")
 {
     CPPUNIT_ASSERT_EQUAL(sal_Int32(1801), getProperty<sal_Int32>(getParagraph(1), "ParaLeftMargin"));
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 25390cc20024..74550ec80245 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1447,6 +1447,45 @@ static sal_Int32 lcl_getListId(const StyleSheetEntryPtr& rEntry, const StyleShee
     return lcl_getListId(pParent, rStyleTable, rNumberingFromBaseStyle);
 }
 
+/// Return the paragraph's list level (from styles, unless pParacontext is provided).
+/// -1 indicates the level is not set anywhere. [In that case, with a numId, use 0 (level 1)]
+///  9 indicates that numbering should be at body level (aka disabled) - rarely used by MSWord.
+///  0-8 are the nine valid numbering levels.
+sal_Int16 DomainMapper_Impl::GetListLevel(const StyleSheetEntryPtr& pEntry,
+                                  const PropertyMapPtr& pParaContext)
+{
+    sal_Int16 nListLevel = -1;
+    if (pParaContext)
+    {
+        GetAnyProperty(PROP_NUMBERING_LEVEL, pParaContext) >>= nListLevel;
+        if (nListLevel != -1)
+            return nListLevel;
+    }
+
+    if (!pEntry)
+        return -1;
+
+    const StyleSheetPropertyMap* pEntryProperties = dynamic_cast<const StyleSheetPropertyMap*>(pEntry->pProperties.get());
+    if (!pEntryProperties)
+        return -1;
+
+    nListLevel = pEntryProperties->GetListLevel();
+    // The style itself has a list level.
+    if (nListLevel >= 0)
+        return nListLevel;
+
+    // The style has no parent.
+    if (pEntry->sBaseStyleIdentifier.isEmpty())
+        return -1;
+
+    const StyleSheetEntryPtr pParent = GetStyleSheetTable()->FindStyleSheetByISTD(pEntry->sBaseStyleIdentifier);
+    // No such parent style or loop in the style hierarchy.
+    if (!pParent || pParent == pEntry)
+        return -1;
+
+    return GetListLevel(pParent);
+}
+
 void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, const bool bRemove, const bool bNoNumbering )
 {
     if (m_bDiscardHeaderFooter)
@@ -1499,14 +1538,19 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
     sal_Int32 nListId = -1;
     if ( !bRemove && pStyleSheetProperties && pParaContext )
     {
+        bool bNumberingFromBaseStyle = false;
+        nListId = lcl_getListId(pEntry, GetStyleSheetTable(), bNumberingFromBaseStyle);
+
         //apply numbering level/style to paragraph if it was set at the style, but only if the paragraph itself
         //does not specify the numbering
-        const sal_Int16 nListLevel = pStyleSheetProperties->GetListLevel();
+        sal_Int16 nListLevel = GetListLevel(pEntry, pParaContext);
+        // Undefined listLevel with a valid numId is treated as a first level numbering.
+        if (nListLevel == -1 && nListId > 0)
+            nListLevel = 0;
+
         if ( !bNoNumbering && !isNumberingViaRule && nListLevel >= 0 )
             pParaContext->Insert( PROP_NUMBERING_LEVEL, uno::makeAny(nListLevel), false );
 
-        bool bNumberingFromBaseStyle = false;
-        nListId = pEntry ? lcl_getListId(pEntry, GetStyleSheetTable(), bNumberingFromBaseStyle) : -1;
         auto const pList(GetListTable()->GetList(nListId));
         if (pList && nListId >= 0 && !pParaContext->isSet(PROP_NUMBERING_STYLE_NAME))
         {
@@ -2094,7 +2138,7 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
                                 xParaProps->setPropertyValue("ParaLeftMargin", aMargin);
                             else if (isNumberingViaStyle)
                             {
-                                const sal_Int32 nParaLeftMargin = getNumberingProperty(nListId, pStyleSheetProperties->GetListLevel(), "IndentAt");
+                                const sal_Int32 nParaLeftMargin = getNumberingProperty(nListId, GetListLevel(pEntry, pPropertyMap), "IndentAt");
                                 if (nParaLeftMargin != 0)
                                     xParaProps->setPropertyValue("ParaLeftMargin", uno::makeAny(nParaLeftMargin));
                             }
@@ -2112,7 +2156,7 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap, con
                                 xParaProps->setPropertyValue("ParaFirstLineIndent", aMargin);
                             else if (isNumberingViaStyle)
                             {
-                                const sal_Int32 nFirstLineIndent = getNumberingProperty(nListId, pStyleSheetProperties->GetListLevel(), "FirstLineIndent");
+                                const sal_Int32 nFirstLineIndent = getNumberingProperty(nListId, GetListLevel(pEntry, pPropertyMap), "FirstLineIndent");
                                 if (nFirstLineIndent != 0)
                                     xParaProps->setPropertyValue("ParaFirstLineIndent", uno::makeAny(nFirstLineIndent));
                             }
@@ -7579,7 +7623,7 @@ uno::Reference<container::XIndexAccess> DomainMapper_Impl::GetCurrentNumberingRu
         if (nListId < 0)
             return xRet;
         if (pListLevel)
-            *pListLevel = pStyleSheetProperties->GetListLevel();
+            *pListLevel = GetListLevel(pEntry, GetTopContextOfType(CONTEXT_PARAGRAPH));
 
         // So we are in a paragraph style and it has numbering. Look up the relevant numbering rules.
         auto const pList(GetListTable()->GetList(nListId));
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index c89e24cd4329..88b3eb7d8332 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -1031,6 +1031,8 @@ public:
     /// If the current paragraph has a numbering style associated, this method returns its numbering rules
     css::uno::Reference<css::container::XIndexAccess> GetCurrentNumberingRules(sal_Int32* pListLevel);
 
+    sal_Int16 GetListLevel(const StyleSheetEntryPtr& pEntry, const PropertyMapPtr& pParaContext = nullptr);
+
     /**
      Used for attributes/sprms which cannot be evaluated immediately (e.g. they depend
      on another one that comes in the same CONTEXT_CHARACTER). The property will be processed


More information about the Libreoffice-commits mailing list