diff options
-rw-r--r-- | sw/qa/extras/rtfimport/data/tdf116265.rtf | 28 | ||||
-rw-r--r-- | sw/qa/extras/rtfimport/rtfimport.cxx | 8 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdispatchdestination.cxx | 1 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdispatchvalue.cxx | 2 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdocumentimpl.cxx | 49 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdocumentimpl.hxx | 6 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfsprm.cxx | 25 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfsprm.hxx | 3 |
8 files changed, 106 insertions, 16 deletions
diff --git a/sw/qa/extras/rtfimport/data/tdf116265.rtf b/sw/qa/extras/rtfimport/data/tdf116265.rtf new file mode 100644 index 000000000000..c5ad557d289d --- /dev/null +++ b/sw/qa/extras/rtfimport/data/tdf116265.rtf @@ -0,0 +1,28 @@ +{\rtf \ansi \ansicpg0 \deff0 \stshfdbch1 \stshfloch0 \stshfhich0 \deflang1033 \deflangfe1033 +{\fonttbl +{\f0 \froman \fcharset0 \fprq2 Times New Roman;} +} +{\stylesheet +{Normal;} +{\s19 \li720 \ri0 ListParagraph;} +} +{\*\listtable +{\list \listtemplateid700648999 \listhybrid +{\listlevel \levelnfc0 \levelnfcn0 \leveljc0 \leveljcn0 \levelstartat1 \levelfollow0 \levelspace0 \levelindent0 \levellegal0 \levelnorestart0 +{\leveltext +} +{\levelnumbers \'01 +{\uc1 \u59 ?} +} +\li720 \fi-360 } +{\listname ;} +\listid697112958 } +} +{\*\listoverridetable +{\listoverride \listid697112958 \listoverridecount0 \ls1 } +} +\paperw12240 \paperh15840 \margl1800 \margr1800 \margt1440 \margb1440 +\pard\plain We would add the following notes:\par +\pard \plain \s19 \fi-360 \li720 \ls1 +Strictly speaking, PDF is also a revisable format, but it is most often used to create documents for viewing.\par +} diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx index e4af20ddc392..4211c88429e7 100644 --- a/sw/qa/extras/rtfimport/rtfimport.cxx +++ b/sw/qa/extras/rtfimport/rtfimport.cxx @@ -636,6 +636,14 @@ DECLARE_RTFIMPORT_TEST(testTdf116269, "tdf116269.rtf") getProperty<sal_Int32>(getParagraph(1), "ParaLeftMargin")); } +DECLARE_RTFIMPORT_TEST(testTdf116265, "tdf116265.rtf") +{ + // This was -635, \fi as direct formatting has to be ignored due to + // matching \fi in list definition (and with invalid level numbers). + CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), + getProperty<sal_Int32>(getParagraph(2), "ParaFirstLineIndent")); +} + DECLARE_RTFIMPORT_TEST(testFdo66565, "fdo66565.rtf") { uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY); diff --git a/writerfilter/source/rtftok/rtfdispatchdestination.cxx b/writerfilter/source/rtftok/rtfdispatchdestination.cxx index af1a60d947ca..d67c043c08b2 100644 --- a/writerfilter/source/rtftok/rtfdispatchdestination.cxx +++ b/writerfilter/source/rtftok/rtfdispatchdestination.cxx @@ -140,6 +140,7 @@ RTFError RTFDocumentImpl::dispatchDestination(RTFKeyword nKeyword) break; case RTF_LISTLEVEL: m_aStates.top().eDestination = Destination::LISTLEVEL; + ++m_nListLevel; break; case RTF_LEVELTEXT: m_aStates.top().eDestination = Destination::LEVELTEXT; diff --git a/writerfilter/source/rtftok/rtfdispatchvalue.cxx b/writerfilter/source/rtftok/rtfdispatchvalue.cxx index bad8111a77aa..27f3d9ae9de9 100644 --- a/writerfilter/source/rtftok/rtfdispatchvalue.cxx +++ b/writerfilter/source/rtftok/rtfdispatchvalue.cxx @@ -1477,6 +1477,8 @@ RTFError RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam) if (m_aStates.top().bLevelNumbersValid) putNestedAttribute(m_aStates.top().aTableSprms, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_firstLine, pIntValue); + else + m_aInvalidListLevelFirstIndents[m_nListLevel] = nParam; } else putNestedAttribute(m_aStates.top().aParagraphSprms, NS_ooxml::LN_CT_PPrBase_ind, diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index 2e8ff1e9ab78..d0825e0ec275 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -443,6 +443,32 @@ static void lcl_copyFlatten(RTFReferenceProperties& rProps, RTFSprms& rStyleAttr writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::getProperties(RTFSprms& rAttributes, RTFSprms& rSprms, Id nStyleType) { + RTFSprms aSprms(rSprms); + RTFValue::Pointer_t pAbstractList; + int nAbstractListId = -1; + RTFValue::Pointer_t pNumId + = getNestedSprm(aSprms, NS_ooxml::LN_CT_PPrBase_numPr, NS_ooxml::LN_CT_NumPr_numId); + if (pNumId) + { + // We have a numbering, look up the abstract list for property + // deduplication and duplication. + auto itNumId = m_aListOverrideTable.find(pNumId->getInt()); + if (itNumId != m_aListOverrideTable.end()) + { + nAbstractListId = itNumId->second; + auto itAbstract = m_aListTable.find(nAbstractListId); + if (itAbstract != m_aListTable.end()) + pAbstractList = itAbstract->second; + } + } + + if (pAbstractList) + { + auto it = m_aInvalidListTableFirstIndents.find(nAbstractListId); + if (it != m_aInvalidListTableFirstIndents.end()) + aSprms.deduplicateList(it->second); + } + int nStyle = 0; if (!m_aStates.empty()) nStyle = m_aStates.top().nCurrentStyleIndex; @@ -476,26 +502,13 @@ RTFDocumentImpl::getProperties(RTFSprms& rAttributes, RTFSprms& rSprms, Id nStyl } // Get rid of direct formatting what is already in the style. - RTFSprms const sprms(rSprms.cloneAndDeduplicate(aStyleSprms)); + RTFSprms const sprms(aSprms.cloneAndDeduplicate(aStyleSprms)); 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); - } - } + if (pAbstractList) + aSprms.duplicateList(pAbstractList); writerfilter::Reference<Properties>::Pointer_t pRet = std::make_shared<RTFReferenceProperties>(rAttributes, aSprms); return pRet; @@ -3023,6 +3036,10 @@ RTFError RTFDocumentImpl::popState() m_aListTableSprms.set(NS_ooxml::LN_CT_Numbering_abstractNum, pValue, RTFOverwrite::NO_APPEND); m_aListTable[aState.nCurrentListIndex] = pValue; + m_nListLevel = -1; + m_aInvalidListTableFirstIndents[aState.nCurrentListIndex] + = m_aInvalidListLevelFirstIndents; + m_aInvalidListLevelFirstIndents.clear(); } break; case Destination::PARAGRAPHNUMBERING: diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx index 2200122ed030..cf099a9817fc 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx @@ -567,6 +567,12 @@ private: std::map<int, int> m_aListOverrideTable; /// Maps listtable indexes to listtable entries. std::map<int, RTFValue::Pointer_t> m_aListTable; + /// Index of the current list level in a list table entry. + int m_nListLevel = -1; + /// Maps List level indexes to removed values in the current list entry. + std::map<int, int> m_aInvalidListLevelFirstIndents; + /// Maps list table indexes to levels (and their removed values). + std::map<int, std::map<int, int>> m_aInvalidListTableFirstIndents; /// 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 8ebf9fd9ec5e..89d520c391bb 100644 --- a/writerfilter/source/rtftok/rtfsprm.cxx +++ b/writerfilter/source/rtftok/rtfsprm.cxx @@ -262,6 +262,31 @@ static RTFValue::Pointer_t getListLevel(RTFValue::Pointer_t pAbstract, int nLeve return RTFValue::Pointer_t(); } +void RTFSprms::deduplicateList(const std::map<int, int>& rInvalidListLevelFirstIndents) +{ + 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(); + + auto it = rInvalidListLevelFirstIndents.find(nLevel); + if (it == rInvalidListLevelFirstIndents.end()) + return; + + int nListValue = it->second; + + RTFValue::Pointer_t pParagraphValue + = getNestedAttribute(*this, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_firstLine); + if (!pParagraphValue) + return; + + int nParagraphValue = pParagraphValue->getInt(); + + if (nParagraphValue == nListValue) + eraseNestedAttribute(*this, NS_ooxml::LN_CT_PPrBase_ind, NS_ooxml::LN_CT_Ind_firstLine); +} + void RTFSprms::duplicateList(RTFValue::Pointer_t pAbstract) { int nLevel = 0; diff --git a/writerfilter/source/rtftok/rtfsprm.hxx b/writerfilter/source/rtftok/rtfsprm.hxx index 7232b04e9351..79694e5864bd 100644 --- a/writerfilter/source/rtftok/rtfsprm.hxx +++ b/writerfilter/source/rtftok/rtfsprm.hxx @@ -13,6 +13,7 @@ #include <string> #include <utility> #include <vector> +#include <map> #include <tools/ref.hxx> #include "rtfvalue.hxx" @@ -58,6 +59,8 @@ public: RTFSprms cloneAndDeduplicate(RTFSprms& rReference) const; /// Inserts default values to override attributes of pAbstract. void duplicateList(RTFValue::Pointer_t pAbstract); + /// Removes duplicated values based on in-list properties. + void deduplicateList(const std::map<int, int>& rInvalidListLevelFirstIndents); std::size_t size() const { return m_pSprms->size(); } bool empty() const { return m_pSprms->empty(); } Entry_t& back() { return m_pSprms->back(); } |