diff options
-rw-r--r-- | sw/qa/extras/rtfimport/rtfimport.cxx | 10 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfdocumentimpl.cxx | 24 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfsprm.cxx | 70 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfsprm.hxx | 6 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfvalue.cxx | 8 | ||||
-rw-r--r-- | writerfilter/source/rtftok/rtfvalue.hxx | 1 |
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; |