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

Miklos Vajna vmiklos at collabora.co.uk
Tue Mar 20 08:06:40 UTC 2018


 sw/qa/extras/rtfimport/data/tdf116269.rtf       |   22 +++++++++
 sw/qa/extras/rtfimport/rtfimport.cxx            |    8 +++
 writerfilter/source/rtftok/rtfdispatchvalue.cxx |    4 +
 writerfilter/source/rtftok/rtfdocumentimpl.cxx  |   30 ++++++++++++
 writerfilter/source/rtftok/rtfdocumentimpl.hxx  |   13 +++++
 writerfilter/source/rtftok/rtfsprm.cxx          |   57 ++++++++++++++++++++++++
 writerfilter/source/rtftok/rtfsprm.hxx          |    2 
 7 files changed, 134 insertions(+), 2 deletions(-)

New commits:
commit 0f0a80123d970ef6f3f8269619813e5277fff4df
Author: Miklos Vajna <vmiklos at collabora.co.uk>
Date:   Mon Mar 19 21:38:43 2018 +0100

    tdf#116269 RTF import: implement reverse deduplication for lists
    
    This is the same mechanism that was added in commit
    1be0a3fa9ebb22b607c54b47739d4467acfed259 (n#825305: writerfilter RTF
    import: override style properties like Word, 2014-06-17), except that
    here the reference is a list definition, not a paragraph style.
    
    Also, this commit only implements the part that inserts explicit
    defaults for not repeated properties, not the actual deduplication, as
    that already works at a dmapper level.
    
    (Saving the bugdoc as DOCX, it's visible in document.xml that DOCX marks
    these defaults explicitly:
    
    <w:ind w:left="0" w:right="-6" w:firstLine="0"/>
    
    but RTF does not, so the right place to fix this is in the tokenizer.)
    
    Change-Id: Iec88d9bf1032d1d89194bd272500d6780c3c2224
    Reviewed-on: https://gerrit.libreoffice.org/51589
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Miklos Vajna <vmiklos at collabora.co.uk>

diff --git a/sw/qa/extras/rtfimport/data/tdf116269.rtf b/sw/qa/extras/rtfimport/data/tdf116269.rtf
new file mode 100644
index 000000000000..39504c1ae9d5
--- /dev/null
+++ b/sw/qa/extras/rtfimport/data/tdf116269.rtf
@@ -0,0 +1,22 @@
+{\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf360
+{\*\listtable
+{\list\listtemplateid1\listhybrid
+{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0
+{\*\levelmarker \{decimal\}.}
+{\leveltext\leveltemplateid1\'02\'00.;}
+{\levelnumbers\'01;}
+\fi-360\li720\lin720 }
+{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0
+{\*\levelmarker \{decimal\}.}
+{\leveltext\leveltemplateid2\'02\'01.;}
+{\levelnumbers\'01;}
+\fi-360\li1440\lin1440 }
+{\listname ;}
+\listid42}
+}
+{\*\listoverridetable
+{\listoverride\listid42\listoverridecount0\ls1}
+}
+\paperw11900\paperh16840\margl1417\margr1417\margb1701\margt1984
+\pard\ri-6\ls1\ilvl1 Gaming proposal
+}
diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx
index 860fe0712044..6ddc2239be6c 100644
--- a/sw/qa/extras/rtfimport/rtfimport.cxx
+++ b/sw/qa/extras/rtfimport/rtfimport.cxx
@@ -656,6 +656,14 @@ DECLARE_RTFIMPORT_TEST(testFdo81033, "fdo81033.rtf")
     CPPUNIT_ASSERT_EQUAL(u'_', tabs[1].FillChar);
 }
 
+DECLARE_RTFIMPORT_TEST(testTdf116269, "tdf116269.rtf")
+{
+    // This was 2540, implicit 0 left margin was ignored on import (inherited
+    // value from list definition is repeated if it's not 0).
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0),
+                         getProperty<sal_Int32>(getParagraph(1), "ParaLeftMargin"));
+}
+
 DECLARE_RTFIMPORT_TEST(testFdo66565, "fdo66565.rtf")
 {
     uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
diff --git a/writerfilter/source/rtftok/rtfdispatchvalue.cxx b/writerfilter/source/rtftok/rtfdispatchvalue.cxx
index 66789d3e6824..bad8111a77aa 100644
--- a/writerfilter/source/rtftok/rtfdispatchvalue.cxx
+++ b/writerfilter/source/rtftok/rtfdispatchvalue.cxx
@@ -665,12 +665,16 @@ RTFError RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
                                                      pIntValue);
             else if (m_aStates.top().eDestination == Destination::LISTOVERRIDEENTRY)
                 m_aStates.top().aTableSprms.set(NS_ooxml::LN_CT_Num_abstractNumId, pIntValue);
+            m_aStates.top().nCurrentListIndex = nParam;
         }
         break;
         case RTF_LS:
         {
             if (m_aStates.top().eDestination == Destination::LISTOVERRIDEENTRY)
+            {
                 m_aStates.top().aTableAttributes.set(NS_ooxml::LN_CT_AbstractNum_nsid, pIntValue);
+                m_aStates.top().nCurrentListOverrideIndex = nParam;
+            }
             else
             {
                 // Insert at the start, so properties inherited from the list
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 4d5cf17c0b6e..d779e18bce71 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -114,6 +114,15 @@ RTFValue::Pointer_t getNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId)
     return rAttributes.find(nId);
 }
 
+RTFValue::Pointer_t getNestedSprm(RTFSprms& rSprms, Id nParent, Id nId)
+{
+    RTFValue::Pointer_t pParent = rSprms.find(nParent);
+    if (!pParent)
+        return RTFValue::Pointer_t();
+    RTFSprms& rInner = pParent->getSprms();
+    return rInner.find(nId);
+}
+
 bool eraseNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId)
 {
     RTFValue::Pointer_t pParent = rSprms.find(nParent);
@@ -470,8 +479,24 @@ RTFDocumentImpl::getProperties(RTFSprms& rAttributes, RTFSprms& rSprms, Id nStyl
         RTFSprms const attributes(rAttributes.cloneAndDeduplicate(aStyleAttributes));
         return std::make_shared<RTFReferenceProperties>(attributes, sprms);
     }
+
+    RTFSprms aSprms(rSprms);
+    RTFValue::Pointer_t pNumId
+        = getNestedSprm(aSprms, NS_ooxml::LN_CT_PPrBase_numPr, NS_ooxml::LN_CT_NumPr_numId);
+    if (pNumId)
+    {
+        // We have a numbering, see if defaults has to be inserted for not
+        // repeated direct formatting.
+        auto itNumId = m_aListOverrideTable.find(pNumId->getInt());
+        if (itNumId != m_aListOverrideTable.end())
+        {
+            auto itAbstract = m_aListTable.find(itNumId->second);
+            if (itAbstract != m_aListTable.end())
+                aSprms.duplicateList(itAbstract->second);
+        }
+    }
     writerfilter::Reference<Properties>::Pointer_t pRet
-        = std::make_shared<RTFReferenceProperties>(rAttributes, rSprms);
+        = std::make_shared<RTFReferenceProperties>(rAttributes, aSprms);
     return pRet;
 }
 
@@ -2996,6 +3021,7 @@ RTFError RTFDocumentImpl::popState()
             auto pValue = std::make_shared<RTFValue>(aState.aTableAttributes, aState.aTableSprms);
             m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_abstractNum, pValue,
                                   RTFOverwrite::NO_APPEND);
+            m_aListTable[aState.nCurrentListIndex] = pValue;
         }
         break;
         case Destination::PARAGRAPHNUMBERING:
@@ -3146,6 +3172,8 @@ RTFError RTFDocumentImpl::popState()
                         = std::make_shared<RTFValue>(aState.aTableAttributes, aState.aTableSprms);
                     m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_num, pValue,
                                           RTFOverwrite::NO_APPEND);
+                    m_aListOverrideTable[aState.nCurrentListOverrideIndex]
+                        = aState.nCurrentListIndex;
                 }
             }
             break;
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
index ae05d7a0647d..2200122ed030 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -335,6 +335,10 @@ public:
     int nCurrentStyleIndex;
     /// Index of the current character style.
     int nCurrentCharacterStyleIndex;
+    /// Current listid, points to a listtable entry.
+    int nCurrentListIndex = -1;
+    /// Current ls, points to a listoverridetable entry.
+    int nCurrentListOverrideIndex = -1;
 
     /// Points to the active buffer, if there is one.
     RTFBuffer_t* pCurrentBuffer;
@@ -394,9 +398,12 @@ void putNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId, const RTFValue::Po
                         RTFOverwrite eOverwrite = RTFOverwrite::YES, bool bAttribute = true);
 bool eraseNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId);
 
-/// Looks up the nParent then the nested nId key in rSprms.
+/// Looks up the nParent then the nested nId attribute in rSprms.
 RTFValue::Pointer_t getNestedAttribute(RTFSprms& rSprms, Id nParent, Id nId);
 
+/// Looks up the nParent then the nested nId sprm in rSprms.
+RTFValue::Pointer_t getNestedSprm(RTFSprms& rSprms, Id nParent, Id nId);
+
 /// Checks if rName is contained at least once in rProperties as a key.
 bool findPropertyName(const std::vector<css::beans::PropertyValue>& rProperties,
                       const OUString& rName);
@@ -556,6 +563,10 @@ private:
     bool m_bNeedFinalPar;
     /// The list table and list override table combined.
     RTFSprms m_aListTableSprms;
+    /// Maps between listoverridetable and listtable indexes.
+    std::map<int, int> m_aListOverrideTable;
+    /// Maps listtable indexes to listtable entries.
+    std::map<int, RTFValue::Pointer_t> m_aListTable;
     /// The settings table attributes.
     RTFSprms m_aSettingsTableAttributes;
     /// The settings table sprms.
diff --git a/writerfilter/source/rtftok/rtfsprm.cxx b/writerfilter/source/rtftok/rtfsprm.cxx
index 271ad821cef3..8ebf9fd9ec5e 100644
--- a/writerfilter/source/rtftok/rtfsprm.cxx
+++ b/writerfilter/source/rtftok/rtfsprm.cxx
@@ -11,6 +11,7 @@
 #include <ooxml/resourceids.hxx>
 #include <ooxml/QNameToString.hxx>
 #include <rtl/strbuf.hxx>
+#include "rtfdocumentimpl.hxx"
 
 namespace writerfilter
 {
@@ -145,6 +146,7 @@ static RTFValue::Pointer_t getDefaultSPRM(Id const id)
         case NS_ooxml::LN_EG_RPrBase_b:
         case NS_ooxml::LN_CT_Ind_left:
         case NS_ooxml::LN_CT_Ind_right:
+        case NS_ooxml::LN_CT_Ind_firstLine:
             return std::make_shared<RTFValue>(0);
 
         default:
@@ -239,6 +241,61 @@ static void cloneAndDeduplicateSprm(std::pair<Id, RTFValue::Pointer_t> const& rS
     }
 }
 
+/// Extracts the list level matching nLevel from pAbstract.
+static RTFValue::Pointer_t getListLevel(RTFValue::Pointer_t pAbstract, int nLevel)
+{
+    for (const auto& rPair : pAbstract->getSprms())
+    {
+        if (rPair.first != NS_ooxml::LN_CT_AbstractNum_lvl)
+            continue;
+
+        RTFValue::Pointer_t pLevel = rPair.second->getAttributes().find(NS_ooxml::LN_CT_Lvl_ilvl);
+        if (!pLevel)
+            continue;
+
+        if (pLevel->getInt() != nLevel)
+            continue;
+
+        return rPair.second;
+    }
+
+    return RTFValue::Pointer_t();
+}
+
+void RTFSprms::duplicateList(RTFValue::Pointer_t pAbstract)
+{
+    int nLevel = 0;
+    RTFValue::Pointer_t pLevelId
+        = getNestedSprm(*this, NS_ooxml::LN_CT_PPrBase_numPr, NS_ooxml::LN_CT_NumPr_ilvl);
+    if (pLevelId)
+        nLevel = pLevelId->getInt();
+
+    RTFValue::Pointer_t pLevel = getListLevel(pAbstract, nLevel);
+    if (!pLevel)
+        return;
+
+    RTFValue::Pointer_t pLevelInd = pLevel->getSprms().find(NS_ooxml::LN_CT_PPrBase_ind);
+    if (!pLevelInd)
+        return;
+
+    for (const auto& rListLevelPair : pLevelInd->getAttributes())
+    {
+        switch (rListLevelPair.first)
+        {
+            case NS_ooxml::LN_CT_Ind_left:
+            case NS_ooxml::LN_CT_Ind_right:
+            case NS_ooxml::LN_CT_Ind_firstLine:
+                RTFValue::Pointer_t pParagraphValue
+                    = getNestedAttribute(*this, NS_ooxml::LN_CT_PPrBase_ind, rListLevelPair.first);
+                if (!pParagraphValue)
+                    putNestedAttribute(*this, NS_ooxml::LN_CT_PPrBase_ind, rListLevelPair.first,
+                                       getDefaultSPRM(rListLevelPair.first));
+
+                break;
+        }
+    }
+}
+
 RTFSprms RTFSprms::cloneAndDeduplicate(RTFSprms& rReference) const
 {
     RTFSprms ret(*this);
diff --git a/writerfilter/source/rtftok/rtfsprm.hxx b/writerfilter/source/rtftok/rtfsprm.hxx
index bb9228074277..7232b04e9351 100644
--- a/writerfilter/source/rtftok/rtfsprm.hxx
+++ b/writerfilter/source/rtftok/rtfsprm.hxx
@@ -56,6 +56,8 @@ public:
     /// Also insert default values to override attributes of style
     /// (yes, really; that's what Word does).
     RTFSprms cloneAndDeduplicate(RTFSprms& rReference) const;
+    /// Inserts default values to override attributes of pAbstract.
+    void duplicateList(RTFValue::Pointer_t pAbstract);
     std::size_t size() const { return m_pSprms->size(); }
     bool empty() const { return m_pSprms->empty(); }
     Entry_t& back() { return m_pSprms->back(); }


More information about the Libreoffice-commits mailing list