summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/qa/extras/rtfimport/rtfimport.cxx10
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.cxx24
-rw-r--r--writerfilter/source/rtftok/rtfsprm.cxx70
-rw-r--r--writerfilter/source/rtftok/rtfsprm.hxx6
-rw-r--r--writerfilter/source/rtftok/rtfvalue.cxx8
-rw-r--r--writerfilter/source/rtftok/rtfvalue.hxx1
6 files changed, 103 insertions, 16 deletions
diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx
index 3699db8ded84..79a449449c0e 100644
--- a/sw/qa/extras/rtfimport/rtfimport.cxx
+++ b/sw/qa/extras/rtfimport/rtfimport.cxx
@@ -1173,8 +1173,18 @@ DECLARE_RTFIMPORT_TEST(testN825305, "n825305.rtf")
DECLARE_RTFIMPORT_TEST(testParaBottomMargin, "para-bottom-margin.rtf")
{
+ uno::Reference<beans::XPropertySet> xPropertySet(
+ getStyles("ParagraphStyles")->getByName("Standard"), uno::UNO_QUERY);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(353),
+ getProperty<sal_Int32>(xPropertySet, "ParaBottomMargin"));
+
// This was 353, i.e. bottom margin of the paragraph was 0.35cm instead of 0.
+ // The reason why this is 0 despite the default style containing \sa200
+ // is that Word will actually interpret \sN (or \pard which apparently
+ // implies \s0) as "set style N and for every attribute of that style,
+ // set an attribute with default value on the paragraph"
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), getProperty<sal_Int32>(getParagraph(1), "ParaBottomMargin"));
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), getProperty<sal_Int32>(getParagraph(1), "ParaTopMargin"));
}
DECLARE_RTFIMPORT_TEST(testN823655, "n823655.rtf")
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index 2d2dad7be690..465ada36457a 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -443,8 +443,12 @@ writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::getProperties(RT
{
RTFReferenceProperties& rProps = *(RTFReferenceProperties*)it->second.get();
// Get rid of direct formatting what is already in the style.
- rSprms.deduplicate(rProps.getSprms());
- rAttributes.deduplicate(rProps.getAttributes());
+ RTFSprms const sprms(
+ rSprms.cloneAndDeduplicate(rProps.getSprms()));
+ RTFSprms const attributes(
+ rAttributes.cloneAndDeduplicate(rProps.getAttributes()));
+ return writerfilter::Reference<Properties>::Pointer_t(
+ new RTFReferenceProperties(attributes, sprms));
}
writerfilter::Reference<Properties>::Pointer_t pRet(new RTFReferenceProperties(rAttributes, rSprms));
return pRet;
@@ -2759,6 +2763,7 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
// \pard is allowed between \cell and \row, but in that case it should not reset the fact that we're inside a table.
m_aStates.top().aParagraphSprms = m_aDefaultState.aParagraphSprms;
m_aStates.top().aParagraphAttributes = m_aDefaultState.aParagraphAttributes;
+
if (m_nTopLevelCells == 0 && m_nNestedCells == 0)
{
// Reset that we're in a table.
@@ -2772,7 +2777,20 @@ int RTFDocumentImpl::dispatchFlag(RTFKeyword nKeyword)
m_aStates.top().resetFrame();
// Reset currently selected paragraph style as well.
- m_aStates.top().nCurrentStyleIndex = -1;
+ // By default the style with index 0 is applied.
+ {
+ OUString const aName = getStyleName(0);
+ if (!aName.isEmpty())
+ {
+ m_aStates.top().aParagraphSprms.set(NS_ooxml::LN_CT_PPrBase_pStyle,
+ RTFValue::Pointer_t(new RTFValue(aName)));
+ m_aStates.top().nCurrentStyleIndex = 0;
+ }
+ else
+ {
+ m_aStates.top().nCurrentStyleIndex = -1;
+ }
+ }
break;
case RTF_SECTD:
{
diff --git a/writerfilter/source/rtftok/rtfsprm.cxx b/writerfilter/source/rtftok/rtfsprm.cxx
index c6349cb42858..40b8fcc47230 100644
--- a/writerfilter/source/rtftok/rtfsprm.cxx
+++ b/writerfilter/source/rtftok/rtfsprm.cxx
@@ -8,8 +8,10 @@
*/
#include <rtfsprm.hxx>
+
#include <rtl/strbuf.hxx>
+#include <ooxml/resourceids.hxx>
#include <resourcemodel/QNameToString.hxx>
@@ -138,22 +140,68 @@ bool RTFSprms::erase(Id nKeyword)
return false;
}
-void RTFSprms::deduplicate(RTFSprms& rReference)
+static RTFValue::Pointer_t getDefaultSPRM(Id const id)
{
- ensureCopyBeforeWrite();
+ switch (id)
+ {
+ case NS_ooxml::LN_CT_Spacing_before:
+ case NS_ooxml::LN_CT_Spacing_after:
+ return RTFValue::Pointer_t(new RTFValue(0));
- RTFSprms::Iterator_t i = m_pSprms->begin();
- while (i != m_pSprms->end())
+ default:
+ return 0;
+ }
+}
+
+RTFSprms RTFSprms::cloneAndDeduplicate(RTFSprms& rReference) const
+{
+ RTFSprms ret(*this);
+ ret.ensureCopyBeforeWrite();
+
+ // Note: apparently some attributes are set with OVERWRITE_NO_APPEND;
+ // it is probably a bad idea to mess with those in any way here?
+ for (RTFSprms::Iterator_t i = rReference.begin(); i != rReference.end(); ++i)
{
- bool bIgnore = false;
- RTFValue::Pointer_t pValue(rReference.find(i->first));
- if (pValue.get() && i->second->equals(*pValue))
- bIgnore = true;
- if (bIgnore)
- i = m_pSprms->erase(i);
+ RTFValue::Pointer_t const pValue(ret.find(i->first));
+ if (pValue)
+ {
+ if (i->second->equals(*pValue))
+ {
+ ret.erase(i->first); // duplicate to style
+ }
+ else if (!i->second->getSprms().empty() || !i->second->getAttributes().empty())
+ {
+ RTFSprms const sprms(
+ pValue->getSprms().cloneAndDeduplicate(i->second->getSprms()));
+ RTFSprms const attributes(
+ pValue->getAttributes().cloneAndDeduplicate(i->second->getAttributes()));
+ ret.set(i->first, RTFValue::Pointer_t(
+ pValue->CloneWithSprms(attributes, sprms)));
+ }
+ }
else
- ++i;
+ {
+ // not found - try to override style with default
+ RTFValue::Pointer_t const pDefault(getDefaultSPRM(i->first));
+ if (pDefault)
+ {
+ ret.set(i->first, pDefault);
+ }
+ else if (!i->second->getSprms().empty() || !i->second->getAttributes().empty())
+ {
+ RTFSprms const sprms(
+ RTFSprms().cloneAndDeduplicate(i->second->getSprms()));
+ RTFSprms const attributes(
+ RTFSprms().cloneAndDeduplicate(i->second->getAttributes()));
+ if (!sprms.empty() || !attributes.empty())
+ {
+ ret.set(i->first,
+ RTFValue::Pointer_t(new RTFValue(attributes, sprms)));
+ }
+ }
+ }
}
+ return ret;
}
bool RTFSprms::equals(RTFValue& rOther)
diff --git a/writerfilter/source/rtftok/rtfsprm.hxx b/writerfilter/source/rtftok/rtfsprm.hxx
index f6c9f5ba835b..ccf25adeb210 100644
--- a/writerfilter/source/rtftok/rtfsprm.hxx
+++ b/writerfilter/source/rtftok/rtfsprm.hxx
@@ -67,8 +67,10 @@ public:
/// Does the same as ->push_back(), except that it can overwrite or ignore existing entries.
void set(Id nKeyword, RTFValue::Pointer_t pValue, RTFOverwrite eOverwrite = OVERWRITE_YES);
bool erase(Id nKeyword);
- /// Removes elements, which are already in the reference set.
- void deduplicate(RTFSprms& rReference);
+ /// Removes elements which are already in the reference set.
+ /// Also insert default values to override attributes of style
+ /// (yes, really; that's what Word does).
+ RTFSprms cloneAndDeduplicate(RTFSprms& rReference) const;
size_t size() const
{
return m_pSprms->size();
diff --git a/writerfilter/source/rtftok/rtfvalue.cxx b/writerfilter/source/rtftok/rtfvalue.cxx
index 5d038828a031..adf7a7781e10 100644
--- a/writerfilter/source/rtftok/rtfvalue.cxx
+++ b/writerfilter/source/rtftok/rtfvalue.cxx
@@ -223,10 +223,18 @@ RTFValue* RTFValue::Clone()
return new RTFValue(m_nValue, m_sValue, *m_pAttributes, *m_pSprms, m_xShape, m_xStream, m_xObject, m_bForceString, *m_pShape);
}
+RTFValue* RTFValue::CloneWithSprms(
+ RTFSprms const& rAttributes, RTFSprms const& rSprms)
+{
+ return new RTFValue(m_nValue, m_sValue, rAttributes, rSprms, m_xShape, m_xStream, m_xObject, m_bForceString, *m_pShape);
+}
+
bool RTFValue::equals(RTFValue& rOther)
{
if (m_nValue != rOther.m_nValue)
return false;
+ if (m_sValue != rOther.m_sValue)
+ return false;
if (m_pAttributes->size() != rOther.m_pAttributes->size())
return false;
else if (!m_pAttributes->equals(rOther))
diff --git a/writerfilter/source/rtftok/rtfvalue.hxx b/writerfilter/source/rtftok/rtfvalue.hxx
index 5a6d20464940..797b340bc3d0 100644
--- a/writerfilter/source/rtftok/rtfvalue.hxx
+++ b/writerfilter/source/rtftok/rtfvalue.hxx
@@ -48,6 +48,7 @@ public:
virtual writerfilter::Reference<BinaryObj>::Pointer_t getBinary() SAL_OVERRIDE;
virtual std::string toString() const SAL_OVERRIDE;
virtual RTFValue* Clone();
+ virtual RTFValue* CloneWithSprms(RTFSprms const& rAttributes, RTFSprms const& rSprms);
RTFSprms& getAttributes();
RTFSprms& getSprms();
RTFShape& getShape() const;