summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/qa/extras/rtfimport/data/tdf116265.rtf28
-rw-r--r--sw/qa/extras/rtfimport/rtfimport.cxx8
-rw-r--r--writerfilter/source/rtftok/rtfdispatchdestination.cxx1
-rw-r--r--writerfilter/source/rtftok/rtfdispatchvalue.cxx2
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.cxx49
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.hxx6
-rw-r--r--writerfilter/source/rtftok/rtfsprm.cxx25
-rw-r--r--writerfilter/source/rtftok/rtfsprm.hxx3
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(); }