diff options
Diffstat (limited to 'writerfilter/source/rtftok/rtfdocumentimpl.cxx')
-rw-r--r-- | writerfilter/source/rtftok/rtfdocumentimpl.cxx | 194 |
1 files changed, 130 insertions, 64 deletions
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx index 663ac935047d..41fc0cdec523 100644 --- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx +++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx @@ -50,6 +50,7 @@ #include "rtfskipdestination.hxx" #include "rtftokenizer.hxx" #include "rtflookahead.hxx" +#include "rtfcharsets.hxx" using namespace com::sun::star; @@ -80,8 +81,9 @@ namespace writerfilter::rtftok { Id getParagraphBorder(sal_uInt32 nIndex) { - static const Id aBorderIds[] = { NS_ooxml::LN_CT_PBdr_top, NS_ooxml::LN_CT_PBdr_left, - NS_ooxml::LN_CT_PBdr_bottom, NS_ooxml::LN_CT_PBdr_right }; + static const Id aBorderIds[] + = { NS_ooxml::LN_CT_PBdr_top, NS_ooxml::LN_CT_PBdr_left, NS_ooxml::LN_CT_PBdr_bottom, + NS_ooxml::LN_CT_PBdr_right, NS_ooxml::LN_CT_PBdr_between }; return aBorderIds[nIndex]; } @@ -324,6 +326,8 @@ RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& x m_pTokenizer = new RTFTokenizer(*this, m_pInStream.get(), m_xStatusIndicator); m_pSdrImport = new RTFSdrImport(*this, m_xDstDoc); + + m_pStyleTableEntries = std::make_shared<RTFReferenceTable::Entries_t>(); } RTFDocumentImpl::~RTFDocumentImpl() = default; @@ -363,6 +367,7 @@ void RTFDocumentImpl::resolveSubstream(std::size_t nPos, Id nId, OUString const& m_aAuthorInitials.clear(); } pImpl->m_nDefaultFontIndex = m_nDefaultFontIndex; + pImpl->m_pStyleTableEntries = m_pStyleTableEntries; pImpl->Strm().Seek(nPos); SAL_INFO("writerfilter.rtf", "substream start"); Mapper().substream(nId, pImpl); @@ -394,16 +399,22 @@ void RTFDocumentImpl::checkFirstRun() assert(!m_bNeedSect || m_bFirstRunException); setNeedSect(true); // first call that succeeds - // set the requested default font, if there are none + // set the requested default font, if there are none for each state in stack RTFValue::Pointer_t pFont = getNestedAttribute(m_aDefaultState.getCharacterSprms(), NS_ooxml::LN_EG_RPrBase_rFonts, NS_ooxml::LN_CT_Fonts_ascii); - RTFValue::Pointer_t pCurrentFont - = getNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_EG_RPrBase_rFonts, - NS_ooxml::LN_CT_Fonts_ascii); - if (pFont && !pCurrentFont) - putNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_EG_RPrBase_rFonts, - NS_ooxml::LN_CT_Fonts_ascii, pFont); + if (!pFont) + return; + + for (size_t i = 0; i < m_aStates.size(); i++) + { + RTFValue::Pointer_t pCurrentFont + = getNestedAttribute(m_aStates[i].getCharacterSprms(), NS_ooxml::LN_EG_RPrBase_rFonts, + NS_ooxml::LN_CT_Fonts_ascii); + if (!pCurrentFont) + putNestedAttribute(m_aStates[i].getCharacterSprms(), NS_ooxml::LN_EG_RPrBase_rFonts, + NS_ooxml::LN_CT_Fonts_ascii, pFont); + } } void RTFDocumentImpl::setNeedPar(bool bNeedPar) { m_bNeedPar = bNeedPar; } @@ -497,16 +508,16 @@ RTFDocumentImpl::getProperties(const RTFSprms& rAttributes, RTFSprms const& rSpr int nStyle = 0; if (!m_aStates.empty()) nStyle = m_aStates.top().getCurrentStyleIndex(); - auto it = m_aStyleTableEntries.find(nStyle); - if (it != m_aStyleTableEntries.end()) + auto it = m_pStyleTableEntries->find(nStyle); + if (it != m_pStyleTableEntries->end()) { // cloneAndDeduplicate() wants to know about only a single "style", so // let's merge paragraph and character style properties here. - auto itChar = m_aStyleTableEntries.end(); + auto itChar = m_pStyleTableEntries->end(); if (!m_aStates.empty()) { int nCharStyle = m_aStates.top().getCurrentCharacterStyleIndex(); - itChar = m_aStyleTableEntries.find(nCharStyle); + itChar = m_pStyleTableEntries->find(nCharStyle); } RTFSprms aStyleSprms; @@ -517,7 +528,7 @@ RTFDocumentImpl::getProperties(const RTFSprms& rAttributes, RTFSprms const& rSpr RTFReferenceProperties& rProps = *static_cast<RTFReferenceProperties*>(it->second.get()); lcl_copyFlatten(rProps, aStyleAttributes, aStyleSprms); - if (itChar != m_aStyleTableEntries.end()) + if (itChar != m_pStyleTableEntries->end()) { // Found active character style, then update aStyleSprms/Attributes. if (!nStyleType || nStyleType == NS_ooxml::LN_Value_ST_StyleType_character) @@ -1322,6 +1333,74 @@ void RTFDocumentImpl::singleChar(sal_uInt8 nValue, bool bRunProps) } } +void RTFDocumentImpl::handleFontTableEntry() +{ + OUString aName = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); + + if (aName.isEmpty()) + return; + + if (aName.endsWith(";")) + { + aName = aName.copy(0, aName.getLength() - 1); + } + + // Old documents can contain no encoding information in fontinfo, + // but there can be font name suffixes: Arial CE is not a special + // font, it is ordinal Arial, but with used cp 1250 encoding. + // Moreover these suffixes have priority over \cpgN and \fcharsetN + // in MS Word. + OUString aFontSuffix; + OUString aNameNoSuffix(aName); + sal_Int32 nLastSpace = aName.lastIndexOf(' '); + if (nLastSpace >= 0) + { + aFontSuffix = aName.copy(nLastSpace + 1); + aNameNoSuffix = aName.copy(0, nLastSpace); + sal_Int32 nEncoding = RTL_TEXTENCODING_DONTKNOW; + for (int i = 0; aRTFFontNameSuffixes[i].codepage != RTL_TEXTENCODING_DONTKNOW; i++) + { + if (aFontSuffix.equalsAscii(aRTFFontNameSuffixes[i].suffix)) + { + nEncoding = aRTFFontNameSuffixes[i].codepage; + break; + } + } + if (nEncoding > RTL_TEXTENCODING_DONTKNOW) + { + m_nCurrentEncoding = nEncoding; + m_aStates.top().setCurrentEncoding(m_nCurrentEncoding); + } + else + { + // Unknown suffix: looks like it is just a part of font name, restore it + aNameNoSuffix = aName; + } + } + + m_aFontNames[m_nCurrentFontIndex] = aNameNoSuffix; + if (m_nCurrentEncoding >= 0) + { + m_aFontEncodings[m_nCurrentFontIndex] = m_nCurrentEncoding; + m_nCurrentEncoding = -1; + } + m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Font_name, + new RTFValue(aNameNoSuffix)); + + writerfilter::Reference<Properties>::Pointer_t const pProp(new RTFReferenceProperties( + m_aStates.top().getTableAttributes(), m_aStates.top().getTableSprms())); + + //See fdo#47347 initial invalid font entry properties are inserted first, + //so when we attempt to insert the correct ones, there's already an + //entry in the map for them, so the new ones aren't inserted. + auto lb = m_aFontTableEntries.lower_bound(m_nCurrentFontIndex); + if (lb != m_aFontTableEntries.end() + && !(m_aFontTableEntries.key_comp()(m_nCurrentFontIndex, lb->first))) + lb->second = pProp; + else + m_aFontTableEntries.insert(lb, std::make_pair(m_nCurrentFontIndex, pProp)); +} + void RTFDocumentImpl::text(OUString& rString) { if (rString.getLength() == 1 && m_aStates.top().getDestination() != Destination::DOCCOMM) @@ -1335,10 +1414,7 @@ void RTFDocumentImpl::text(OUString& rString) bool bRet = true; switch (m_aStates.top().getDestination()) { - // Note: in fonttbl there may or may not be groups; in stylesheet - // and revtbl groups are mandatory - case Destination::FONTTABLE: - case Destination::FONTENTRY: + // Note: in stylesheet and revtbl groups are mandatory case Destination::STYLEENTRY: case Destination::LISTNAME: case Destination::REVISIONENTRY: @@ -1358,34 +1434,6 @@ void RTFDocumentImpl::text(OUString& rString) = m_aStates.top().getCurrentDestinationText()->makeStringAndClear(); switch (m_aStates.top().getDestination()) { - case Destination::FONTTABLE: - case Destination::FONTENTRY: - { - m_aFontNames[m_nCurrentFontIndex] = aName; - if (m_nCurrentEncoding >= 0) - { - m_aFontEncodings[m_nCurrentFontIndex] = m_nCurrentEncoding; - m_nCurrentEncoding = -1; - } - m_aStates.top().getTableAttributes().set(NS_ooxml::LN_CT_Font_name, - new RTFValue(aName)); - - writerfilter::Reference<Properties>::Pointer_t const pProp( - new RTFReferenceProperties(m_aStates.top().getTableAttributes(), - m_aStates.top().getTableSprms())); - - //See fdo#47347 initial invalid font entry properties are inserted first, - //so when we attempt to insert the correct ones, there's already an - //entry in the map for them, so the new ones aren't inserted. - auto lb = m_aFontTableEntries.lower_bound(m_nCurrentFontIndex); - if (lb != m_aFontTableEntries.end() - && !(m_aFontTableEntries.key_comp()(m_nCurrentFontIndex, lb->first))) - lb->second = pProp; - else - m_aFontTableEntries.insert(lb, - std::make_pair(m_nCurrentFontIndex, pProp)); - } - break; case Destination::STYLEENTRY: { RTFValue::Pointer_t pType @@ -1402,7 +1450,7 @@ void RTFDocumentImpl::text(OUString& rString) writerfilter::Reference<Properties>::Pointer_t const pProp( createStyleProperties()); - m_aStyleTableEntries.insert( + m_pStyleTableEntries->insert( std::make_pair(m_nCurrentStyleIndex, pProp)); } else @@ -1423,6 +1471,8 @@ void RTFDocumentImpl::text(OUString& rString) } } break; + case Destination::FONTTABLE: + case Destination::FONTENTRY: case Destination::LEVELTEXT: case Destination::SHAPEPROPERTYNAME: case Destination::SHAPEPROPERTYVALUE: @@ -1862,13 +1912,13 @@ RTFError RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int n case RTFParserState::RunType::HICH: case RTFParserState::RunType::RTLCH_LTRCH_1: case RTFParserState::RunType::LTRCH_RTLCH_2: - case RTFParserState::RunType::DBCH: nSprm = NS_ooxml::LN_EG_RPrBase_bCs; break; case RTFParserState::RunType::NONE: case RTFParserState::RunType::LOCH: case RTFParserState::RunType::LTRCH_RTLCH_1: case RTFParserState::RunType::RTLCH_LTRCH_2: + case RTFParserState::RunType::DBCH: default: nSprm = NS_ooxml::LN_EG_RPrBase_b; break; @@ -1881,13 +1931,13 @@ RTFError RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int n case RTFParserState::RunType::HICH: case RTFParserState::RunType::RTLCH_LTRCH_1: case RTFParserState::RunType::LTRCH_RTLCH_2: - case RTFParserState::RunType::DBCH: nSprm = NS_ooxml::LN_EG_RPrBase_iCs; break; case RTFParserState::RunType::NONE: case RTFParserState::RunType::LOCH: case RTFParserState::RunType::LTRCH_RTLCH_1: case RTFParserState::RunType::RTLCH_LTRCH_2: + case RTFParserState::RunType::DBCH: default: nSprm = NS_ooxml::LN_EG_RPrBase_i; break; @@ -1922,7 +1972,14 @@ RTFError RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int n } if (nSprm >= 0) { - m_aStates.top().getCharacterSprms().set(nSprm, pBoolValue); + if (m_aStates.top().getDestination() == Destination::LISTLEVEL) + { + m_aStates.top().getTableSprms().set(nSprm, pBoolValue); + } + else + { + m_aStates.top().getCharacterSprms().set(nSprm, pBoolValue); + } return RTFError::OK; } @@ -2091,7 +2148,7 @@ writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::createStylePrope /** 2 different representations of the styles are needed: 1) flat content, as read from the input file: - stored in m_aStyleTableEntries, used as reference input for + stored in m_pStyleTableEntries, used as reference input for deduplication both here and for hard formatting in getProperties() 2) real content, with proper override of sprms/attributes where it differs @@ -2100,7 +2157,7 @@ writerfilter::Reference<Properties>::Pointer_t RTFDocumentImpl::createStylePrope RTFReferenceTable::Entries_t RTFDocumentImpl::deduplicateStyleTable() { RTFReferenceTable::Entries_t ret; - for (auto const& it : m_aStyleTableEntries) + for (auto const& it : *m_pStyleTableEntries) { auto pStyle = it.second; ret[it.first] = pStyle; @@ -2116,8 +2173,8 @@ RTFReferenceTable::Entries_t RTFDocumentImpl::deduplicateStyleTable() if (it.first == nBasedOn) continue; - auto const itParent(m_aStyleTableEntries.find(nBasedOn)); // definition as read! - if (itParent != m_aStyleTableEntries.end()) + auto const itParent(m_pStyleTableEntries->find(nBasedOn)); // definition as read! + if (itParent != m_pStyleTableEntries->end()) { auto const pStyleType( static_cast<RTFReferenceProperties&>(*pStyle).getAttributes().find( @@ -2143,7 +2200,7 @@ RTFReferenceTable::Entries_t RTFDocumentImpl::deduplicateStyleTable() } } } - assert(ret.size() == m_aStyleTableEntries.size()); + assert(ret.size() == m_pStyleTableEntries->size()); return ret; } @@ -2172,17 +2229,26 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState) { switch (rState.getDestination()) { + //Note: in fonttbl there may or may not be groups, so process it as no groups case Destination::FONTTABLE: + case Destination::FONTENTRY: { - writerfilter::Reference<Table>::Pointer_t const pTable( - new RTFReferenceTable(m_aFontTableEntries)); - Mapper().table(NS_ooxml::LN_FONTTABLE, pTable); - if (m_nDefaultFontIndex >= 0) + // Some text unhandled? Seems it is last font name + if (m_aStates.top().getCurrentDestinationText()->getLength()) + handleFontTableEntry(); + + if (rState.getDestination() == Destination::FONTTABLE) { - auto pValue = new RTFValue(m_aFontNames[getFontIndex(m_nDefaultFontIndex)]); - putNestedAttribute(m_aDefaultState.getCharacterSprms(), - NS_ooxml::LN_EG_RPrBase_rFonts, NS_ooxml::LN_CT_Fonts_ascii, - pValue); + writerfilter::Reference<Table>::Pointer_t const pTable( + new RTFReferenceTable(m_aFontTableEntries)); + Mapper().table(NS_ooxml::LN_FONTTABLE, pTable); + if (m_nDefaultFontIndex >= 0) + { + auto pValue = new RTFValue(m_aFontNames[getFontIndex(m_nDefaultFontIndex)]); + putNestedAttribute(m_aDefaultState.getCharacterSprms(), + NS_ooxml::LN_EG_RPrBase_rFonts, NS_ooxml::LN_CT_Fonts_ascii, + pValue); + } } } break; @@ -3668,7 +3734,7 @@ RTFParserState::RTFParserState(RTFDocumentImpl* pDocumentImpl) , m_nHour(0) , m_nMinute(0) , m_pCurrentDestinationText(nullptr) - , m_nCurrentStyleIndex(-1) + , m_nCurrentStyleIndex(0) , m_nCurrentCharacterStyleIndex(-1) , m_pCurrentBuffer(nullptr) , m_bInListpicture(false) |