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

Vasily Melenchuk (via logerrit) logerrit at kemper.freedesktop.org
Wed Jun 17 09:20:13 UTC 2020


 sw/qa/extras/ww8export/data/tdf120394.doc |binary
 sw/qa/extras/ww8export/ww8export3.cxx     |   30 +++++
 sw/source/filter/ww8/ww8par.hxx           |    3 
 sw/source/filter/ww8/ww8par3.cxx          |  157 ++++++------------------------
 4 files changed, 63 insertions(+), 127 deletions(-)

New commits:
commit 7e605bc3ff0cfea76be4683f0170d821fcae7203
Author:     Vasily Melenchuk <vasily.melenchuk at cib.de>
AuthorDate: Tue May 19 10:24:35 2020 +0300
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Wed Jun 17 11:19:35 2020 +0200

    tdf#120394: doc import: use list format string
    
    Since introducion of list level format string there is
    no need in complex parsing of doc level string and convering
    it to prefix-number-suffix format. We can just replace there
    special chars by %n placeholders (used in docx and now in LO)
    and this should be enough.
    
    Change-Id: I4e947939c4d4f393ee7e16c851cf22567d352ac3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/94475
    Tested-by: Jenkins
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/sw/qa/extras/ww8export/data/tdf120394.doc b/sw/qa/extras/ww8export/data/tdf120394.doc
new file mode 100644
index 000000000000..2ee9058a59ef
Binary files /dev/null and b/sw/qa/extras/ww8export/data/tdf120394.doc differ
diff --git a/sw/qa/extras/ww8export/ww8export3.cxx b/sw/qa/extras/ww8export/ww8export3.cxx
index 96547e30133a..f998ffe1d85a 100644
--- a/sw/qa/extras/ww8export/ww8export3.cxx
+++ b/sw/qa/extras/ww8export/ww8export3.cxx
@@ -561,6 +561,36 @@ DECLARE_WW8EXPORT_TEST(testPresetDash, "tdf127166_prstDash_Word97.doc")
     }
 }
 
+DECLARE_WW8EXPORT_TEST(testTdf120394, "tdf120394.doc")
+{
+    CPPUNIT_ASSERT_EQUAL(1, getPages());
+    {
+        uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2), getProperty<sal_Int16>(xPara, "NumberingLevel"));
+        CPPUNIT_ASSERT_EQUAL(OUString("1.1.1"), getProperty<OUString>(xPara, "ListLabelString"));
+    }
+    {
+        uno::Reference<beans::XPropertySet> xPara(getParagraph(5), uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(0), getProperty<sal_Int16>(xPara, "NumberingLevel"));
+        CPPUNIT_ASSERT_EQUAL(OUString(CHAR_ZWSP), getProperty<OUString>(xPara, "ListLabelString"));
+    }
+    {
+        uno::Reference<beans::XPropertySet> xPara(getParagraph(8), uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2), getProperty<sal_Int16>(xPara, "NumberingLevel"));
+        CPPUNIT_ASSERT_EQUAL(OUString(CHAR_ZWSP), getProperty<OUString>(xPara, "ListLabelString"));
+    }
+    {
+        uno::Reference<beans::XPropertySet> xPara(getParagraph(9), uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2), getProperty<sal_Int16>(xPara, "NumberingLevel"));
+        CPPUNIT_ASSERT_EQUAL(OUString("1.1.2"), getProperty<OUString>(xPara, "ListLabelString"));
+    }
+    {
+        uno::Reference<beans::XPropertySet> xPara(getParagraph(10), uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(2), getProperty<sal_Int16>(xPara, "NumberingLevel"));
+        CPPUNIT_ASSERT_EQUAL(OUString(CHAR_ZWSP), getProperty<OUString>(xPara, "ListLabelString"));
+    }
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
index 679c56a01ad5..810b692ee6aa 100644
--- a/sw/source/filter/ww8/ww8par.hxx
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -176,8 +176,7 @@ private:
     //the rParaSprms returns back the original word paragraph indent
     //sprms which are attached to this numbering level
     bool ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet>& rpItemSet, sal_uInt16 nLevelStyle,
-        bool bSetStartNo, std::deque<bool> &rNotReallyThere, sal_uInt16 nLevel,
-        ww::bytes &rParaSprms);
+        bool bSetStartNo, sal_uInt16 nLevel, ww::bytes &rParaSprms);
 
     // character attributes from GrpprlChpx
     typedef std::unique_ptr<SfxItemSet> WW8aISet[nMaxLevel];
diff --git a/sw/source/filter/ww8/ww8par3.cxx b/sw/source/filter/ww8/ww8par3.cxx
index d35adc6ca42e..02c02ecc459d 100644
--- a/sw/source/filter/ww8/ww8par3.cxx
+++ b/sw/source/filter/ww8/ww8par3.cxx
@@ -70,6 +70,7 @@
 #include <unotools/fltrcfg.hxx>
 #include <rtl/character.hxx>
 #include <xmloff/odffields.hxx>
+#include <comphelper/string.hxx>
 
 using namespace com::sun::star;
 using namespace sw::util;
@@ -489,18 +490,6 @@ WW8LSTInfo* WW8ListManager::GetLSTByListId( sal_uInt32 nIdLst ) const
     return aResult->get();
 }
 
-static void lcl_CopyGreaterEight(OUString &rDest, OUString const &rSrc,
-    sal_Int32 nStart, sal_Int32 nLen = SAL_MAX_INT32)
-{
-    const sal_Int32 nMaxLen = std::min(rSrc.getLength(), nLen);
-    for( sal_Int32 nI = nStart; nI < nMaxLen; ++nI)
-    {
-        sal_Unicode nChar = rSrc[nI];
-        if (nChar > WW8ListManager::nMaxLevel)
-            rDest += OUStringChar(nChar);
-    }
-}
-
 static OUString sanitizeString(const OUString& rString)
 {
     sal_Int32 i=0;
@@ -628,20 +617,15 @@ SvxNumType WW8ListManager::GetSvxNumTypeFromMSONFC(sal_uInt16 nNFC)
 }
 
 bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet>& rpItemSet,
-    sal_uInt16 nLevelStyle, bool bSetStartNo,
-    std::deque<bool> &rNotReallyThere, sal_uInt16 nLevel,
-    ww::bytes &rParaSprms)
+    sal_uInt16 nLevelStyle, bool bSetStartNo, sal_uInt16 /*nLevel*/, ww::bytes &rParaSprms)
 {
     sal_uInt8       aBits1(0);
-    sal_uInt16      nStartNo(0);        // Start-No. for Writer
     SvxNumType      nType(SVX_NUM_ARABIC);
     SvxAdjust       eAdj;               // Alignment (Left/right/centered)
     sal_Unicode     cBullet(0x2190);    // default safe bullet
 
     sal_Unicode     cGrfBulletCP(USHRT_MAX);
 
-    OUString        sPrefix;
-    OUString        sPostfix;
     WW8LVL          aLVL = {};
 
     // 1. read LVLF
@@ -839,9 +823,6 @@ bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet
 
     // 5. convert read values into Writer syntax
 
-    if( 0 <= aLVL.nStartAt )
-        nStartNo = static_cast<sal_uInt16>(aLVL.nStartAt);
-
     nType = GetSvxNumTypeFromMSONFC(aLVL.nNFC);
     //For i120928,type info
     if (bIsPicBullet)
@@ -849,68 +830,6 @@ bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet
         nType = SVX_NUM_BITMAP;
     }
 
-    //If a number level is not going to be used, then record this fact
-    if (SVX_NUM_NUMBER_NONE == nType)
-        rNotReallyThere[nLevel] = true;
-
-    /*
-     If a number level was not used (i.e. is in NotReallyThere), and that
-     number level appears at one of the positions in the display string of the
-     list, then it effectively is not there at all. So remove that level entry
-     from a copy of the aOfsNumsXCH.
-    */
-    std::vector<sal_uInt8> aOfsNumsXCH;
-    aOfsNumsXCH.reserve(nMaxLevel);
-
-    for(sal_uInt8 nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
-        aOfsNumsXCH.push_back(aLVL.aOfsNumsXCH[nLevelB]);
-
-    // nLevelB is an index in the aOfsNumsXCH array.
-    for(sal_uInt16 nLevelB = 0; nLevelB <= nLevel; ++nLevelB)
-    {
-        // nPos is a one-based character offset to a level placeholder in
-        // sNumString.
-        sal_uInt8 nPos = aOfsNumsXCH[nLevelB];
-        if (nPos && nPos < sNumString.getLength())
-        {
-            // nPosValue is the actual numbering level.
-            sal_Unicode nPosValue = sNumString[nPos-1];
-            if (nPosValue < nMaxLevel)
-            {
-                if (rNotReallyThere[nPosValue])
-                    aOfsNumsXCH[nLevelB] = 0;
-            }
-        }
-    }
-    auto aIter = std::remove(aOfsNumsXCH.begin(), aOfsNumsXCH.end(), 0);
-    auto aEnd = aOfsNumsXCH.end();
-    // #i60633# - suppress access on <aOfsNumsXCH.end()>
-    if ( aIter != aEnd )
-    {
-        // Somehow the first removed vector element, at which <aIter>
-        // points to, isn't reset to zero.
-        // Investigation is needed to clarify why. It seems that only
-        // special arrays are handled correctly by this code.
-        ++aIter;
-        while (aIter != aEnd)
-        {
-            (*aIter) = 0;
-            ++aIter;
-        }
-    }
-
-    sal_uInt8 nUpperLevel = 0;  // current displaydepth for Writer
-    for(sal_uInt8 nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
-    {
-        if (!nUpperLevel && !aOfsNumsXCH[nLevelB])
-            nUpperLevel = nLevelB;
-    }
-
-    // If the terminating char was not NULL, all indices of the list are
-    // filled, so the levels have to be displayed.
-    if (!nUpperLevel)
-        nUpperLevel = nMaxLevel;
-
     if (style::NumberingType::CHAR_SPECIAL == nType)
     {
         cBullet = !sNumString.isEmpty() ? sNumString[0] : 0x2190;
@@ -922,35 +841,6 @@ bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet
     {
         cGrfBulletCP = nWitchPicIsBullet;       // This is a bullet picture ID
     }
-    else
-    {
-        /*
-        #i173#
-        Our aOfsNumsXCH seems generally to be an array that contains the
-        offset into sNumString of locations where the numbers should be
-        filled in, so if the first "fill in a number" slot is greater than
-        1 there is a "prefix" before the number
-        */
-        //First number appears at
-        sal_uInt8 nOneBasedFirstNoIndex = aOfsNumsXCH[0];
-        const sal_Int32 nFirstNoIndex =
-            nOneBasedFirstNoIndex > 0 ? nOneBasedFirstNoIndex -1 : SAL_MAX_INT32;
-        lcl_CopyGreaterEight(sPrefix, sNumString, 0, nFirstNoIndex);
-
-        //Next number appears at
-        assert(nUpperLevel > 0);
-        sal_uInt8 nOneBasedNextNoIndex = aOfsNumsXCH[nUpperLevel-1];
-        const sal_Int32 nNextNoIndex =
-            nOneBasedNextNoIndex > 0 ? nOneBasedNextNoIndex : SAL_MAX_INT32;
-        if (sNumString.getLength() > nNextNoIndex)
-            lcl_CopyGreaterEight(sPostfix, sNumString, nNextNoIndex);
-
-        /*
-         We use lcl_CopyGreaterEight because once if we have removed unused
-         number indexes from the aOfsNumsXCH then placeholders remain in
-         sNumString which must not be copied into the final numbering strings
-        */
-    }
 
     switch( aLVL.nAlign )
     {
@@ -976,8 +866,8 @@ bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet
     }
 
     // 6. Configure NumFormat
-    if( bSetStartNo )
-        rNumFormat.SetStart( nStartNo );
+    if( bSetStartNo && 0 <= aLVL.nStartAt)
+        rNumFormat.SetStart(static_cast<sal_uInt16>(aLVL.nStartAt));
     rNumFormat.SetNumberingType( nType );
     rNumFormat.SetNumAdjust( eAdj );
 
@@ -995,12 +885,32 @@ bool WW8ListManager::ReadLVL(SwNumFormat& rNumFormat, std::unique_ptr<SfxItemSet
     }
     else
     {
-        // reminder: Garnix is default Prefix
-        if( !sPrefix.isEmpty() )
-            rNumFormat.SetPrefix( sPrefix );
-        // reminder: Point is default Postfix
-        rNumFormat.SetSuffix( sPostfix );
-        rNumFormat.SetIncludeUpperLevels( nUpperLevel );
+        // Replace symbols at aOfsNumsXCH offsets to %1, %2 as supported by DOCX and LO
+        OUString sListFormat = sNumString;
+        if (sListFormat.getLength())
+        {
+            sal_uInt32 nExtraOffset = 0;
+            for (sal_uInt8 nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
+            {
+                OUString sReplacement("%" + OUString::number(nLevelB + 1));
+                if (aLVL.aOfsNumsXCH[nLevelB])
+                {
+                    if (aLVL.aOfsNumsXCH[nLevelB] <= sNumString.getLength())
+                        sListFormat = sListFormat.replaceAt(aLVL.aOfsNumsXCH[nLevelB] + nExtraOffset - 1, 1, sReplacement);
+                    else
+                        SAL_WARN("sw.ww8", "List level reference is beyond the border. Ignored.");
+                }
+                // We need also update an offset, since we are replacing one symbol by at least two
+                nExtraOffset += sReplacement.getLength() - 1;
+            }
+        }
+
+        rNumFormat.SetListFormat(sListFormat);
+
+        // Total count of replacement holders is determining amount of required parent numbering to include
+        // TODO: not sure how "%" symbol is escaped. This is not supported yet
+        sal_Int16 nParentNum = comphelper::string::getTokenCount(sListFormat, '%');
+        rNumFormat.SetIncludeUpperLevels(nParentNum);
     }
 
     // #i89181#
@@ -1298,15 +1208,13 @@ WW8ListManager::WW8ListManager(SvStream& rSt_, SwWW8ImplReader& rReader_)
         // 1.2.1 read specific LVL(s) for this aLST
 
         sal_uInt16 nLvlCount = static_cast< sal_uInt16 >(pListInfo->bSimpleList ? nMinLevel : nMaxLevel);
-        std::deque<bool> aNotReallyThere;
-        aNotReallyThere.resize(nMaxLevel);
         pListInfo->maParaSprms.resize(nMaxLevel);
         for (sal_uInt16 nLevel = 0; nLevel < nLvlCount; ++nLevel)
         {
             SwNumFormat aNumFormat( rMyNumRule.Get( nLevel ) );
             // read LVLF
             bLVLOk = ReadLVL( aNumFormat, aItemSet[nLevel],
-                pListInfo->aIdSty[nLevel], true, aNotReallyThere, nLevel,
+                pListInfo->aIdSty[nLevel], true, nLevel,
                 pListInfo->maParaSprms[nLevel]);
             if( !bLVLOk )
                 break;
@@ -1449,7 +1357,6 @@ WW8ListManager::WW8ListManager(SvStream& rSt_, SwWW8ImplReader& rReader_)
                 while (nTest == 0xFFFFFFFF);
                 rSt.SeekRel(-4);
 
-                std::deque<bool> aNotReallyThere(WW8ListManager::nMaxLevel);
                 for (sal_uInt8 nLevel = 0; nLevel < rLFOInfo.nLfoLvl; ++nLevel)
                 {
                     WW8LFOLVL aLFOLVL;
@@ -1487,7 +1394,7 @@ WW8ListManager::WW8ListManager(SvStream& rSt_, SwWW8ImplReader& rReader_)
                             bLVLOk = nLevel < rLFOInfo.maParaSprms.size() &&
                                 ReadLVL(aNumFormat, aItemSet[nLevel],
                                 pParentListInfo->aIdSty[nLevel],
-                                aLFOLVL.bStartAt, aNotReallyThere, nLevel,
+                                aLFOLVL.bStartAt, nLevel,
                                 rLFOInfo.maParaSprms[nLevel]);
 
                             if (!bLVLOk)


More information about the Libreoffice-commits mailing list