summaryrefslogtreecommitdiff
path: root/writerfilter/source/rtftok/rtfdocumentimpl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'writerfilter/source/rtftok/rtfdocumentimpl.cxx')
-rw-r--r--writerfilter/source/rtftok/rtfdocumentimpl.cxx194
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)