summaryrefslogtreecommitdiff
path: root/writerfilter
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2018-03-19 21:38:43 +0100
committerCaolán McNamara <caolanm@redhat.com>2018-03-26 18:08:47 +0200
commit01d7bbdc13594965aad55269c1283716974ae743 (patch)
treed6088ca4a5c0abd6a10fef21c43765838a7b77ae /writerfilter
parentc3ca9d933b289df49e45f223493f3a22a1f74d14 (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.) (cherry picked from commit 0f0a80123d970ef6f3f8269619813e5277fff4df) Change-Id: Iec88d9bf1032d1d89194bd272500d6780c3c2224 Reviewed-on: https://gerrit.libreoffice.org/51690 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'writerfilter')
-rw-r--r--writerfilter/source/rtftok/rtfdispatchvalue.cxx4
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.cxx30
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.hxx13
-rw-r--r--writerfilter/source/rtftok/rtfsprm.cxx57
-rw-r--r--writerfilter/source/rtftok/rtfsprm.hxx2
5 files changed, 104 insertions, 2 deletions
diff --git a/writerfilter/source/rtftok/rtfdispatchvalue.cxx b/writerfilter/source/rtftok/rtfdispatchvalue.cxx
index 7079962c69d1..489875e3e78c 100644
--- a/writerfilter/source/rtftok/rtfdispatchvalue.cxx
+++ b/writerfilter/source/rtftok/rtfdispatchvalue.cxx
@@ -663,12 +663,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 0a5d3993ff43..b3bc922dd437 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -125,6 +125,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);
@@ -479,8 +488,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;
}
@@ -3015,6 +3040,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:
@@ -3165,6 +3191,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 d17fbf7844b7..6d215a6653c7 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -313,6 +313,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;
@@ -372,9 +376,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);
@@ -534,6 +541,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 e021feee623c..eb959cb3496b 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 7839682343b8..6a79d5b7a55a 100644
--- a/writerfilter/source/rtftok/rtfsprm.hxx
+++ b/writerfilter/source/rtftok/rtfsprm.hxx
@@ -65,6 +65,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(); }