fdo#44736 RTF import: ignore direct formatting which equals to style

Change-Id: Ie82f18381a95adbfedf7ea02d6844685e44b151d
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index c8992ec..d1888dc 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -399,6 +399,21 @@ void RTFDocumentImpl::setNeedPar(bool bNeedPar)
    m_bNeedPar = bNeedPar;
}

writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::getProperties(RTFSprms& rAttributes, RTFSprms& rSprms)
{
    int nStyle = m_aStates.top().nCurrentStyleIndex;
    RTFReferenceTable::Entries_t::iterator it = m_aStyleTableEntries.find(nStyle);
    if (it != m_aStyleTableEntries.end())
    {
        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());
    }
    writerfilter::Reference<Properties>::Pointer_t pRet(new RTFReferenceProperties(rAttributes, rSprms));
    return pRet;
}

void RTFDocumentImpl::checkNeedPap()
{
    if (m_bNeedPap)
@@ -407,7 +422,7 @@ void RTFDocumentImpl::checkNeedPap()
        if (!m_pCurrentBuffer)
        {
            writerfilter::Reference<Properties>::Pointer_t const pParagraphProperties(
                    new RTFReferenceProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms)
                    getProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms)
                    );

            // Writer will ignore a page break before a text frame, so guard it with empty paragraphs
@@ -441,9 +456,7 @@ void RTFDocumentImpl::runProps()
{
    if (!m_pCurrentBuffer)
    {
        writerfilter::Reference<Properties>::Pointer_t const pProperties(
                new RTFReferenceProperties(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms)
                );
        writerfilter::Reference<Properties>::Pointer_t const pProperties = getProperties(m_aStates.top().aCharacterAttributes, m_aStates.top().aCharacterSprms);
        Mapper().props(pProperties);
    }
    else
@@ -1677,7 +1690,7 @@ int RTFDocumentImpl::dispatchSymbol(RTFKeyword nKeyword)
                m_aStates.top().aTableCellAttributes = m_aDefaultState.aTableCellAttributes;

                writerfilter::Reference<Properties>::Pointer_t const pParagraphProperties(
                        new RTFReferenceProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms)
                        getProperties(m_aStates.top().aParagraphAttributes, m_aStates.top().aParagraphSprms)
                        );
                Mapper().props(pParagraphProperties);

@@ -2623,6 +2636,7 @@ int RTFDocumentImpl::dispatchValue(RTFKeyword nKeyword, int nParam)
            }
            break;
        case RTF_S:
            m_aStates.top().nCurrentStyleIndex = nParam;
            if (m_aStates.top().nDestinationState == DESTINATION_STYLESHEET || m_aStates.top().nDestinationState == DESTINATION_STYLEENTRY)
            {
                m_nCurrentStyleIndex = nParam;
@@ -4206,7 +4220,8 @@ RTFParserState::RTFParserState(RTFDocumentImpl *pDocumentImpl)
    nMonth(0),
    nDay(0),
    nHour(0),
    nMinute(0)
    nMinute(0),
    nCurrentStyleIndex(-1)
{
}

diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.hxx b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
index 4942fac..9801164 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.hxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.hxx
@@ -399,6 +399,9 @@ namespace writerfilter {

                /// Text from special destinations.
                rtl::OUStringBuffer aDestinationText;

                /// Same as the int value of NS_rtf::LN_ISTD in aParagraphAttributes, for performance reasons.
                int nCurrentStyleIndex;
        };

        class RTFTokenizer;
@@ -478,6 +481,7 @@ namespace writerfilter {
                void runBreak();
                void parBreak();
                void tableBreak();
                writerfilter::Reference<Properties>::Pointer_t getProperties(RTFSprms& rAttributes, RTFSprms& rSprms);
                void checkNeedPap();
                void sectBreak(bool bFinal);
                void replayBuffer(RTFBuffer_t& rBuffer);
diff --git a/writerfilter/source/rtftok/rtfreferenceproperties.cxx b/writerfilter/source/rtftok/rtfreferenceproperties.cxx
index 03cd0e97..50f76e3e 100644
--- a/writerfilter/source/rtftok/rtfreferenceproperties.cxx
+++ b/writerfilter/source/rtftok/rtfreferenceproperties.cxx
@@ -62,6 +62,16 @@ std::string RTFReferenceProperties::getType() const
    return "RTFReferenceProperties";
}

RTFSprms& RTFReferenceProperties::getAttributes()
{
    return m_aAttributes;
}

RTFSprms& RTFReferenceProperties::getSprms()
{
    return m_aSprms;
}

} // namespace rtftok
} // namespace writerfilter

diff --git a/writerfilter/source/rtftok/rtfreferenceproperties.hxx b/writerfilter/source/rtftok/rtfreferenceproperties.hxx
index d580de9..369590b 100644
--- a/writerfilter/source/rtftok/rtfreferenceproperties.hxx
+++ b/writerfilter/source/rtftok/rtfreferenceproperties.hxx
@@ -42,6 +42,8 @@ namespace writerfilter {
                virtual ~RTFReferenceProperties();
                virtual void resolve(Properties & rHandler);
                virtual std::string getType() const;
                RTFSprms& getAttributes();
                RTFSprms& getSprms();
            private:
                RTFSprms m_aAttributes;
                RTFSprms m_aSprms;
diff --git a/writerfilter/source/rtftok/rtfsprm.cxx b/writerfilter/source/rtftok/rtfsprm.cxx
index fb61d29..2958cde 100644
--- a/writerfilter/source/rtftok/rtfsprm.cxx
+++ b/writerfilter/source/rtftok/rtfsprm.cxx
@@ -29,6 +29,7 @@
#include <rtl/strbuf.hxx>

#include <resourcemodel/QNameToString.hxx>
#include <doctok/resourceids.hxx> // NS_rtf namespace

using rtl::OStringBuffer;

@@ -130,6 +131,25 @@ bool RTFSprms::erase(Id nKeyword)
    return false;
}

void RTFSprms::deduplicate(RTFSprms& rReference)
{
    RTFSprms::Iterator_t i = m_aSprms.begin();
    while (i != m_aSprms.end())
    {
        bool bIgnore = false;
        if (i->first != NS_rtf::LN_ISTD)
        {
            RTFValue::Pointer_t pValue(rReference.find(i->first));
            if (pValue.get() && i->second->equals(*pValue))
                bIgnore = true;
        }
        if (bIgnore)
            i = m_aSprms.erase(i);
        else
            ++i;
    }
}

RTFSprms::RTFSprms()
    : m_aSprms()
{
diff --git a/writerfilter/source/rtftok/rtfsprm.hxx b/writerfilter/source/rtftok/rtfsprm.hxx
index df223fc..80d41a3 100644
--- a/writerfilter/source/rtftok/rtfsprm.hxx
+++ b/writerfilter/source/rtftok/rtfsprm.hxx
@@ -47,6 +47,8 @@ namespace writerfilter {
                /// Does the same as ->push_back(), except that it can overwrite existing entries.
                void set(Id nKeyword, RTFValue::Pointer_t pValue, bool bOverwrite = true);
                bool erase(Id nKeyword);
                /// Removes elements, which are already in the reference set.
                void deduplicate(RTFSprms& rReference);
                void swap(RTFSprms& rOther);
                size_t size() const { return m_aSprms.size(); }
                bool empty() const { return m_aSprms.empty(); }
diff --git a/writerfilter/source/rtftok/rtfvalue.cxx b/writerfilter/source/rtftok/rtfvalue.cxx
index 4882522..eaacc2a 100644
--- a/writerfilter/source/rtftok/rtfvalue.cxx
+++ b/writerfilter/source/rtftok/rtfvalue.cxx
@@ -200,6 +200,11 @@ RTFValue* RTFValue::Clone()
    return new RTFValue(m_nValue, m_sValue, *m_pAttributes, *m_pSprms, m_xShape, m_xStream, m_xObject, m_bForceString);
}

bool RTFValue::equals(RTFValue& rOther)
{
    return m_nValue == rOther.m_nValue;
}

RTFSprms& RTFValue::getAttributes()
{
    return *m_pAttributes;
diff --git a/writerfilter/source/rtftok/rtfvalue.hxx b/writerfilter/source/rtftok/rtfvalue.hxx
index 6751126..3714d26 100644
--- a/writerfilter/source/rtftok/rtfvalue.hxx
+++ b/writerfilter/source/rtftok/rtfvalue.hxx
@@ -62,6 +62,7 @@ namespace writerfilter {
                virtual RTFValue* Clone();
                RTFSprms& getAttributes();
                RTFSprms& getSprms();
                bool equals(RTFValue& rOther);
            private:
                RTFValue& operator=(RTFValue const& rOther);
                int m_nValue;