diff options
author | Miklos Vajna <vmiklos@collabora.co.uk> | 2018-03-19 21:38:43 +0100 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.co.uk> | 2018-03-20 09:06:18 +0100 |
commit | 0f0a80123d970ef6f3f8269619813e5277fff4df (patch) | |
tree | 853a75eb51baedda07e85f4bebbed61a162554fd /writerfilter | |
parent | 48baafc46825f1248ea9269308cadbd698a23ffc (diff) |
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@libreoffice.org>
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
Diffstat (limited to 'writerfilter')
-rw-r--r-- | writerfilter/source/rtftok/rtfdispatchvalue.cxx | 4 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdocumentimpl.cxx | 30 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdocumentimpl.hxx | 13 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfsprm.cxx | 57 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfsprm.hxx | 2 |
5 files changed, 104 insertions, 2 deletions
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(); } |