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.cxx784
1 files changed, 497 insertions, 287 deletions
diff --git a/writerfilter/source/rtftok/rtfdocumentimpl.cxx b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
index dc014457c8d5..ab700ff0dc14 100644
--- a/writerfilter/source/rtftok/rtfdocumentimpl.cxx
+++ b/writerfilter/source/rtftok/rtfdocumentimpl.cxx
@@ -8,14 +8,20 @@
*/
#include "rtfdocumentimpl.hxx"
+
#include <algorithm>
#include <memory>
+#include <string_view>
+
#include <com/sun/star/embed/XEmbeddedObject.hpp>
#include <com/sun/star/beans/PropertyAttribute.hpp>
#include <com/sun/star/io/WrongFormatException.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <com/sun/star/text/XDependentTextField.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+
#include <i18nlangtag/languagetag.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/streamwrap.hxx>
@@ -23,15 +29,14 @@
#include <filter/msfilter/util.hxx>
#include <filter/msfilter/rtfutil.hxx>
#include <comphelper/string.hxx>
-#include <tools/diagnose_ex.h>
+#include <comphelper/diagnose_ex.hxx>
#include <tools/globname.hxx>
#include <tools/datetimeutils.hxx>
#include <comphelper/classids.hxx>
#include <comphelper/embeddedobjectcontainer.hxx>
#include <svl/lngmisc.hxx>
-#include <sfx2/sfxbasemodel.hxx>
#include <sfx2/classificationhelper.hxx>
-#include <oox/mathml/import.hxx>
+#include <oox/mathml/imexport.hxx>
#include <ooxml/resourceids.hxx>
#include <oox/token/namespaces.hxx>
#include <oox/drawingml/drawingmltypes.hxx>
@@ -49,26 +54,27 @@
#include "rtfskipdestination.hxx"
#include "rtftokenizer.hxx"
#include "rtflookahead.hxx"
+#include "rtfcharsets.hxx"
using namespace com::sun::star;
namespace
{
/// Returns an util::DateTime from a 'YYYY. MM. DD.' string.
-util::DateTime getDateTimeFromUserProp(const OUString& rString)
+util::DateTime getDateTimeFromUserProp(std::u16string_view rString)
{
util::DateTime aRet;
- sal_Int32 nLen = rString.getLength();
+ size_t nLen = rString.size();
if (nLen >= 4)
{
- aRet.Year = rString.copy(0, 4).toInt32();
+ aRet.Year = o3tl::toInt32(rString.substr(0, 4));
- if (nLen >= 8 && rString.match(". ", 4))
+ if (nLen >= 8 && o3tl::starts_with(rString.substr(4), u". "))
{
- aRet.Month = rString.copy(6, 2).toInt32();
+ aRet.Month = o3tl::toInt32(rString.substr(6, 2));
- if (nLen >= 12 && rString.match(". ", 8))
- aRet.Day = rString.copy(10, 2).toInt32();
+ if (nLen >= 12 && o3tl::starts_with(rString.substr(8), u". "))
+ aRet.Day = o3tl::toInt32(rString.substr(10, 2));
}
}
return aRet;
@@ -79,8 +85,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];
}
@@ -183,6 +190,21 @@ void putBorderProperty(RTFStack& aStates, Id nId, const RTFValue::Pointer_t& pVa
else if (aStates.top().getBorderState() == RTFBorderState::PAGE)
pAttributes = &getLastAttributes(aStates.top().getSectionSprms(),
NS_ooxml::LN_EG_SectPrContents_pgBorders);
+ else if (aStates.top().getBorderState() == RTFBorderState::NONE)
+ {
+ // this is invalid, but Word apparently clears or overrides all paragraph borders now
+ for (int i = 0; i < 4; ++i)
+ {
+ auto const nBorder = getParagraphBorder(i);
+ RTFSprms aAttributes;
+ RTFSprms aSprms;
+ aAttributes.set(NS_ooxml::LN_CT_Border_val,
+ new RTFValue(NS_ooxml::LN_Value_ST_Border_none));
+ putNestedSprm(aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PrBase_pBdr, nBorder,
+ new RTFValue(aAttributes, aSprms), RTFOverwrite::YES);
+ }
+ }
+
if (pAttributes)
pAttributes->set(nId, pValue);
}
@@ -290,11 +312,12 @@ RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& x
, m_nCurrentFontIndex(0)
, m_nCurrentEncoding(-1)
, m_nDefaultFontIndex(-1)
+ , m_pStyleTableEntries(new RTFReferenceTable::Entries_t)
, m_nCurrentStyleIndex(0)
, m_bFormField(false)
, m_bMathNor(false)
, m_bIgnoreNextContSectBreak(false)
- , m_nResetBreakOnSectBreak(RTF_invalid)
+ , m_nResetBreakOnSectBreak(RTFKeyword::invalid)
, m_bNeedSect(false) // done by checkFirstRun
, m_bWasInFrame(false)
, m_bHadPicture(false)
@@ -307,7 +330,6 @@ RTFDocumentImpl::RTFDocumentImpl(uno::Reference<uno::XComponentContext> const& x
, m_hasFHeader(false)
, m_hasRFooter(false)
, m_hasFFooter(false)
- , m_bAfterCellBeforeRow(false)
{
OSL_ASSERT(xInputStream.is());
m_pInStream = utl::UcbStreamHelper::CreateStream(xInputStream, true);
@@ -323,6 +345,9 @@ 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);
+
+ // unlike OOXML, this is enabled by default
+ m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Compat_splitPgBreakAndParaMark, new RTFValue(1));
}
RTFDocumentImpl::~RTFDocumentImpl() = default;
@@ -362,6 +387,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);
@@ -371,11 +397,15 @@ void RTFDocumentImpl::resolveSubstream(std::size_t nPos, Id nId, OUString const&
void RTFDocumentImpl::outputSettingsTable()
{
+ // tdf#136740: do not change target document settings when pasting
+ if (!m_bIsNewDoc || isSubstream())
+ return;
writerfilter::Reference<Properties>::Pointer_t pProp
= new RTFReferenceProperties(m_aSettingsTableAttributes, m_aSettingsTableSprms);
RTFReferenceTable::Entries_t aSettingsTableEntries;
aSettingsTableEntries.insert(std::make_pair(0, pProp));
- writerfilter::Reference<Table>::Pointer_t pTable = new RTFReferenceTable(aSettingsTableEntries);
+ writerfilter::Reference<Table>::Pointer_t pTable
+ = new RTFReferenceTable(std::move(aSettingsTableEntries));
Mapper().table(NS_ooxml::LN_settings_settings, pTable);
}
@@ -390,16 +420,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; }
@@ -493,16 +529,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;
@@ -513,7 +549,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)
@@ -524,17 +560,15 @@ RTFDocumentImpl::getProperties(const RTFSprms& rAttributes, RTFSprms const& rSpr
}
}
- // Get rid of direct formatting what is already in the style.
- RTFSprms const sprms(aSprms.cloneAndDeduplicate(aStyleSprms, nStyleType, true, &aSprms));
- RTFSprms const attributes(
- rAttributes.cloneAndDeduplicate(aStyleAttributes, nStyleType, true));
- return new RTFReferenceProperties(attributes, sprms);
+ RTFSprms sprms(aSprms.cloneAndDeduplicate(aStyleSprms, nStyleType, true, &aSprms));
+ RTFSprms attributes(rAttributes.cloneAndDeduplicate(aStyleAttributes, nStyleType, true));
+ return new RTFReferenceProperties(std::move(attributes), std::move(sprms));
}
if (pAbstractList)
aSprms.duplicateList(pAbstractList);
writerfilter::Reference<Properties>::Pointer_t pRet
- = new RTFReferenceProperties(rAttributes, aSprms);
+ = new RTFReferenceProperties(rAttributes, std::move(aSprms));
return pRet;
}
@@ -555,19 +589,20 @@ void RTFDocumentImpl::checkNeedPap()
NS_ooxml::LN_Value_ST_StyleType_paragraph));
// Writer will ignore a page break before a text frame, so guard it with empty paragraphs
+ const bool bIsInFrame = m_aStates.top().getFrame().hasProperties();
bool hasBreakBeforeFrame
- = m_aStates.top().getFrame().hasProperties()
+ = bIsInFrame
&& m_aStates.top().getParagraphSprms().find(NS_ooxml::LN_CT_PPrBase_pageBreakBefore);
if (hasBreakBeforeFrame)
{
- dispatchSymbol(RTF_PAR);
+ dispatchSymbol(RTFKeyword::PAR);
m_bNeedPap = false;
}
Mapper().props(pParagraphProperties);
if (hasBreakBeforeFrame)
- dispatchSymbol(RTF_PAR);
+ dispatchSymbol(RTFKeyword::PAR);
- if (m_aStates.top().getFrame().hasProperties())
+ if (bIsInFrame)
{
writerfilter::Reference<Properties>::Pointer_t const pFrameProperties(
new RTFReferenceProperties(RTFSprms(), m_aStates.top().getFrame().getSprms()));
@@ -595,7 +630,8 @@ void RTFDocumentImpl::runProps()
{
auto pValue = new RTFValue(m_aStates.top().getCharacterAttributes(),
m_aStates.top().getCharacterSprms());
- bufferProperties(*m_aStates.top().getCurrentBuffer(), pValue, nullptr);
+ bufferProperties(*m_aStates.top().getCurrentBuffer(), pValue, nullptr,
+ NS_ooxml::LN_Value_ST_StyleType_character);
}
// Delete the sprm, so the trackchange range will be started only once.
@@ -611,13 +647,14 @@ void RTFDocumentImpl::runProps()
void RTFDocumentImpl::runBreak()
{
- sal_uInt8 const sBreak[] = { 0xd };
- Mapper().text(sBreak, 1);
+ sal_Unicode const sBreak[] = { 0x0d };
+ Mapper().utext(sBreak, 1);
m_bNeedCr = false;
}
void RTFDocumentImpl::tableBreak()
{
+ checkFirstRun(); // ooo113308-1.rtf has a header at offset 151084 that doesn't startParagraphGroup() without this
runBreak();
Mapper().endParagraphGroup();
Mapper().startParagraphGroup();
@@ -636,7 +673,10 @@ void RTFDocumentImpl::parBreak()
m_bHadPicture = false;
// start new one
- Mapper().startParagraphGroup();
+ if (!m_bParAtEndOfSection)
+ {
+ Mapper().startParagraphGroup();
+ }
}
void RTFDocumentImpl::sectBreak(bool bFinal)
@@ -645,22 +685,31 @@ void RTFDocumentImpl::sectBreak(bool bFinal)
bool bNeedSect = m_bNeedSect;
RTFValue::Pointer_t pBreak
= m_aStates.top().getSectionSprms().find(NS_ooxml::LN_EG_SectPrContents_type);
- bool bContinuous
- = pBreak
- && pBreak->getInt()
- == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_SectionMark_continuous);
+ bool bContinuous = pBreak && pBreak->getInt() == NS_ooxml::LN_Value_ST_SectionMark_continuous;
// If there is no paragraph in this section, then insert a dummy one, as required by Writer,
// unless this is the end of the doc, we had nothing since the last section break and this is not a continuous one.
// Also, when pasting, it's fine to not have any paragraph inside the document at all.
if (m_bNeedPar && (!bFinal || m_bNeedSect || bContinuous) && !isSubstream() && m_bIsNewDoc)
- dispatchSymbol(RTF_PAR);
+ {
+ m_bParAtEndOfSection = true;
+ dispatchSymbol(RTFKeyword::PAR);
+ }
// It's allowed to not have a non-table paragraph at the end of an RTF doc, add it now if required.
if (m_bNeedFinalPar && bFinal)
{
- dispatchFlag(RTF_PARD);
- dispatchSymbol(RTF_PAR);
+ dispatchFlag(RTFKeyword::PARD);
+ m_bParAtEndOfSection = true;
+ dispatchSymbol(RTFKeyword::PAR);
m_bNeedSect = bNeedSect;
}
+ // testTdf148515, if RTF ends with \row, endParagraphGroup() must be called!
+ if (!m_bParAtEndOfSection || m_aStates.top().getCurrentBuffer())
+ {
+ Mapper().endParagraphGroup(); // < top para context dies with page break
+ }
+ m_bParAtEndOfSection = false;
+ // paragraph properties are *done* now - only section properties following
+
while (!m_nHeaderFooterPositions.empty())
{
std::pair<Id, std::size_t> aPair = m_nHeaderFooterPositions.front();
@@ -684,7 +733,7 @@ void RTFDocumentImpl::sectBreak(bool bFinal)
RTFSprms aSprms;
aSprms.set(NS_ooxml::LN_CT_PPr_sectPr, pValue);
writerfilter::Reference<Properties>::Pointer_t pProperties
- = new RTFReferenceProperties(aAttributes, aSprms);
+ = new RTFReferenceProperties(std::move(aAttributes), std::move(aSprms));
if (bFinal && !m_pSuperstream)
// This is the end of the document, not just the end of e.g. a header.
@@ -693,7 +742,6 @@ void RTFDocumentImpl::sectBreak(bool bFinal)
// The trick is that we send properties of the previous section right now, which will be exactly what dmapper expects.
Mapper().props(pProperties);
- Mapper().endParagraphGroup();
// End Section
if (!m_pSuperstream)
@@ -761,8 +809,9 @@ OUString RTFDocumentImpl::getStyleName(int nIndex)
if (!m_pSuperstream)
{
OUString aRet;
- if (m_aStyleNames.find(nIndex) != m_aStyleNames.end())
- aRet = m_aStyleNames[nIndex];
+ auto it = m_aStyleNames.find(nIndex);
+ if (it != m_aStyleNames.end())
+ aRet = it->second;
return aRet;
}
@@ -774,8 +823,9 @@ Id RTFDocumentImpl::getStyleType(int nIndex)
if (!m_pSuperstream)
{
Id nRet = 0;
- if (m_aStyleTypes.find(nIndex) != m_aStyleTypes.end())
- nRet = m_aStyleTypes[nIndex];
+ auto it = m_aStyleTypes.find(nIndex);
+ if (it != m_aStyleTypes.end())
+ nRet = it->second;
return nRet;
}
@@ -844,8 +894,9 @@ void RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XS
int count = 2;
// Feed the destination text to a stream.
- OString aStr = OUStringToOString(m_aStates.top().getDestinationText().makeStringAndClear(),
- RTL_TEXTENCODING_ASCII_US);
+ auto& rDestinationTextBuffer = m_aStates.top().getDestinationText();
+ OString aStr = OUStringToOString(rDestinationTextBuffer, RTL_TEXTENCODING_ASCII_US);
+ rDestinationTextBuffer.setLength(0);
for (int i = 0; i < aStr.getLength(); ++i)
{
char ch = aStr[i];
@@ -896,12 +947,18 @@ void RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XS
uno::Reference<io::XInputStream> xInputStream(new utl::OInputStreamWrapper(pStream));
WmfExternal aExtHeader;
aExtHeader.mapMode = m_aStates.top().getPicture().eWMetafile;
- aExtHeader.xExt = sal_uInt16(
- std::clamp<sal_Int32>(m_aStates.top().getPicture().nWidth, 0,
- SAL_MAX_UINT16)); //TODO: better way to handle out-of-bounds values?
- aExtHeader.yExt = sal_uInt16(
- std::clamp<sal_Int32>(m_aStates.top().getPicture().nHeight, 0,
- SAL_MAX_UINT16)); //TODO: better way to handle out-of-bounds values?
+ if (m_aStates.top().getPicture().nGoalWidth == 0
+ || m_aStates.top().getPicture().nGoalHeight == 0)
+ {
+ // Don't use the values provided by picw and pich if the desired size is provided.
+
+ aExtHeader.xExt = sal_uInt16(std::clamp<sal_Int32>(
+ m_aStates.top().getPicture().nWidth, 0,
+ SAL_MAX_UINT16)); //TODO: better way to handle out-of-bounds values?
+ aExtHeader.yExt = sal_uInt16(std::clamp<sal_Int32>(
+ m_aStates.top().getPicture().nHeight, 0,
+ SAL_MAX_UINT16)); //TODO: better way to handle out-of-bounds values?
+ }
WmfExternal* pExtHeader = &aExtHeader;
uno::Reference<lang::XServiceInfo> xServiceInfo(m_aStates.top().getDrawingObject().getShape(),
uno::UNO_QUERY);
@@ -927,8 +984,23 @@ void RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XS
m_aStates.top().getPicture().nHeight = aSize.Height();
}
- // Wrap it in an XShape.
uno::Reference<drawing::XShape> xShape(rShape);
+ if (m_aStates.top().getInShape() && xShape.is())
+ {
+ awt::Size aSize = xShape->getSize();
+ if (aSize.Width || aSize.Height)
+ {
+ // resolvePict() is processing pib structure inside shape
+ // So if shape has dimensions we should use them instead of
+ // \picwN, \pichN, \picscalexN, \picscaleyN given with picture
+ m_aStates.top().getPicture().nGoalWidth = aSize.Width;
+ m_aStates.top().getPicture().nGoalHeight = aSize.Height;
+ m_aStates.top().getPicture().nScaleX = 100;
+ m_aStates.top().getPicture().nScaleY = 100;
+ }
+ }
+
+ // Wrap it in an XShape.
if (xShape.is())
{
uno::Reference<lang::XServiceInfo> xSI(xShape, uno::UNO_QUERY_THROW);
@@ -963,7 +1035,7 @@ void RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XS
xPropertySet->setPropertyValue("Graphic", uno::Any(xGraphic));
// check if the picture is in an OLE object and if the \objdata element is used
- // (see RTF_OBJECT in RTFDocumentImpl::dispatchDestination)
+ // (see RTFKeyword::OBJECT in RTFDocumentImpl::dispatchDestination)
if (m_bObject)
{
// Set the object size
@@ -978,7 +1050,7 @@ void RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XS
// Replacement graphic is inline by default, see oox::vml::SimpleShape::implConvertAndInsert().
xPropertySet->setPropertyValue("AnchorType",
- uno::makeAny(text::TextContentAnchorType_AS_CHARACTER));
+ uno::Any(text::TextContentAnchorType_AS_CHARACTER));
auto pShapeValue = new RTFValue(xShape);
m_aObjectAttributes.set(NS_ooxml::LN_shape, pShapeValue);
@@ -998,6 +1070,16 @@ void RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XS
RTFSprms aAttributes;
// shape attribute
RTFSprms aPicAttributes;
+ if (m_aStates.top().getPicture().nCropT != 0 || m_aStates.top().getPicture().nCropB != 0
+ || m_aStates.top().getPicture().nCropL != 0 || m_aStates.top().getPicture().nCropR != 0)
+ {
+ text::GraphicCrop const crop{ m_aStates.top().getPicture().nCropT,
+ m_aStates.top().getPicture().nCropB,
+ m_aStates.top().getPicture().nCropL,
+ m_aStates.top().getPicture().nCropR };
+ auto const pCrop = new RTFValue(crop);
+ aPicAttributes.set(NS_ooxml::LN_CT_BlipFillProperties_srcRect, pCrop);
+ }
auto pShapeValue = new RTFValue(xShape);
aPicAttributes.set(NS_ooxml::LN_shape, pShapeValue);
// pic sprm
@@ -1028,12 +1110,6 @@ void RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XS
* (nYExt
- (m_aStates.top().getPicture().nCropT + m_aStates.top().getPicture().nCropB)))
/ 100L;
- if (m_aStates.top().getInShape())
- {
- // Picture in shape: it looks like pib picture, so we will stretch the picture to shape size (tdf#49893)
- nXExt = m_aStates.top().getShape().getRight() - m_aStates.top().getShape().getLeft();
- nYExt = m_aStates.top().getShape().getBottom() - m_aStates.top().getShape().getTop();
- }
auto pXExtValue = new RTFValue(oox::drawingml::convertHmmToEmu(nXExt));
auto pYExtValue = new RTFValue(oox::drawingml::convertHmmToEmu(nYExt));
aExtentAttributes.set(NS_ooxml::LN_CT_PositiveSize2D_cx, pXExtValue);
@@ -1143,12 +1219,12 @@ void RTFDocumentImpl::resolvePict(bool const bInline, uno::Reference<drawing::XS
auto pValue = new RTFValue(m_aStates.top().getShape().getAnchorAttributes(), aAnchorSprms);
aSprms.set(NS_ooxml::LN_anchor_anchor, pValue);
}
- writerfilter::Reference<Properties>::Pointer_t pProperties
- = new RTFReferenceProperties(aAttributes, aSprms);
checkFirstRun();
if (!m_aStates.top().getCurrentBuffer())
{
+ writerfilter::Reference<Properties>::Pointer_t pProperties
+ = new RTFReferenceProperties(std::move(aAttributes), std::move(aSprms));
Mapper().props(pProperties);
// Make sure we don't lose these properties with a too early reset.
m_bHadPicture = true;
@@ -1249,7 +1325,7 @@ RTFError RTFDocumentImpl::resolveChars(char ch)
&& m_aStates.top().getDestination() != Destination::LEVELTEXT)
{
checkUnicode(/*bUnicode =*/false, /*bHex =*/true);
- dispatchSymbol(RTF_PAR);
+ dispatchSymbol(RTFKeyword::PAR);
}
else
{
@@ -1287,8 +1363,6 @@ RTFError RTFDocumentImpl::resolveChars(char ch)
return RTFError::OK;
}
-bool RTFFrame::inFrame() const { return m_nW > 0 || m_nH > 0 || m_nX > 0 || m_nY > 0; }
-
void RTFDocumentImpl::singleChar(sal_uInt8 nValue, bool bRunProps)
{
sal_uInt8 sValue[] = { nValue };
@@ -1297,19 +1371,95 @@ void RTFDocumentImpl::singleChar(sal_uInt8 nValue, bool bRunProps)
if (!pCurrentBuffer)
{
Mapper().startCharacterGroup();
- // Should we send run properties?
- if (bRunProps)
- runProps();
+ }
+ else
+ {
+ pCurrentBuffer->emplace_back(BUFFER_STARTRUN, nullptr, nullptr);
+ }
+
+ // Should we send run properties?
+ if (bRunProps)
+ runProps();
+
+ if (!pCurrentBuffer)
+ {
Mapper().text(sValue, 1);
Mapper().endCharacterGroup();
}
else
{
- pCurrentBuffer->push_back(Buf_t(BUFFER_STARTRUN, nullptr, nullptr));
auto pValue = new RTFValue(*sValue);
- pCurrentBuffer->push_back(Buf_t(BUFFER_TEXT, pValue, nullptr));
- pCurrentBuffer->push_back(Buf_t(BUFFER_ENDRUN, nullptr, nullptr));
+ pCurrentBuffer->emplace_back(BUFFER_TEXT, pValue, nullptr);
+ pCurrentBuffer->emplace_back(BUFFER_ENDRUN, nullptr, nullptr);
+ }
+}
+
+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)
@@ -1325,10 +1475,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:
@@ -1348,34 +1495,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
@@ -1392,7 +1511,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
@@ -1413,6 +1532,13 @@ void RTFDocumentImpl::text(OUString& rString)
}
}
break;
+ case Destination::DOCVAR:
+ {
+ m_aStates.top().appendDocVar(rString);
+ }
+ break;
+ case Destination::FONTTABLE:
+ case Destination::FONTENTRY:
case Destination::LEVELTEXT:
case Destination::SHAPEPROPERTYNAME:
case Destination::SHAPEPROPERTYVALUE:
@@ -1483,8 +1609,7 @@ void RTFDocumentImpl::text(OUString& rString)
if (m_aStates.top().getTableCellSprms().find(NS_ooxml::LN_CT_TcPrBase_vAlign)
&& m_nTopLevelCells == 0)
{
- m_aTableBufferStack.back().emplace_back(
- Buf_t(BUFFER_UTEXT, new RTFValue(rString), nullptr));
+ m_aTableBufferStack.back().emplace_back(BUFFER_UTEXT, new RTFValue(rString), nullptr);
return;
}
@@ -1505,7 +1630,7 @@ void RTFDocumentImpl::text(OUString& rString)
else if (pCurrentBuffer)
{
RTFValue::Pointer_t pValue;
- pCurrentBuffer->push_back(Buf_t(BUFFER_STARTRUN, pValue, nullptr));
+ pCurrentBuffer->emplace_back(BUFFER_STARTRUN, pValue, nullptr);
}
if (m_aStates.top().getDestination() == Destination::NORMAL
@@ -1514,11 +1639,11 @@ void RTFDocumentImpl::text(OUString& rString)
runProps();
if (!pCurrentBuffer)
- Mapper().utext(reinterpret_cast<sal_uInt8 const*>(rString.getStr()), rString.getLength());
+ Mapper().utext(rString.getStr(), rString.getLength());
else
{
auto pValue = new RTFValue(rString);
- pCurrentBuffer->push_back(Buf_t(BUFFER_UTEXT, pValue, nullptr));
+ pCurrentBuffer->emplace_back(BUFFER_UTEXT, pValue, nullptr);
}
m_bNeedCr = true;
@@ -1528,7 +1653,7 @@ void RTFDocumentImpl::text(OUString& rString)
else if (pCurrentBuffer)
{
RTFValue::Pointer_t pValue;
- pCurrentBuffer->push_back(Buf_t(BUFFER_ENDRUN, pValue, nullptr));
+ pCurrentBuffer->emplace_back(BUFFER_ENDRUN, pValue, nullptr);
}
}
@@ -1599,20 +1724,20 @@ void RTFDocumentImpl::sendProperties(
tableBreak();
}
-void RTFDocumentImpl::replayRowBuffer(RTFBuffer_t& rBuffer, ::std::deque<RTFSprms>& rCellsSrpms,
+void RTFDocumentImpl::replayRowBuffer(RTFBuffer_t& rBuffer, ::std::deque<RTFSprms>& rCellsSprms,
::std::deque<RTFSprms>& rCellsAttributes, int const nCells)
{
for (int i = 0; i < nCells; ++i)
{
- replayBuffer(rBuffer, &rCellsSrpms.front(), &rCellsAttributes.front());
- rCellsSrpms.pop_front();
+ replayBuffer(rBuffer, &rCellsSprms.front(), &rCellsAttributes.front());
+ rCellsSprms.pop_front();
rCellsAttributes.pop_front();
}
for (Buf_t& i : rBuffer)
{
SAL_WARN_IF(BUFFER_CELLEND == std::get<0>(i), "writerfilter.rtf", "dropping table cell!");
}
- assert(rCellsSrpms.empty());
+ assert(rCellsSprms.empty());
assert(rCellsAttributes.empty());
}
@@ -1623,11 +1748,13 @@ void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer, RTFSprms* const pSprms,
{
Buf_t aTuple(rBuffer.front());
rBuffer.pop_front();
- if (std::get<0>(aTuple) == BUFFER_PROPS)
+ if (std::get<0>(aTuple) == BUFFER_PROPS || std::get<0>(aTuple) == BUFFER_PROPS_CHAR)
{
// Construct properties via getProperties() and not directly, to take care of deduplication.
writerfilter::Reference<Properties>::Pointer_t const pProp(getProperties(
- std::get<1>(aTuple)->getAttributes(), std::get<1>(aTuple)->getSprms(), 0));
+ std::get<1>(aTuple)->getAttributes(), std::get<1>(aTuple)->getSprms(),
+ std::get<0>(aTuple) == BUFFER_PROPS_CHAR ? NS_ooxml::LN_Value_ST_StyleType_character
+ : 0));
Mapper().props(pProp);
}
else if (std::get<0>(aTuple) == BUFFER_NESTROW)
@@ -1661,8 +1788,7 @@ void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer, RTFSprms* const pSprms,
else if (std::get<0>(aTuple) == BUFFER_UTEXT)
{
OUString const aString(std::get<1>(aTuple)->getString());
- Mapper().utext(reinterpret_cast<sal_uInt8 const*>(aString.getStr()),
- aString.getLength());
+ Mapper().utext(aString.getStr(), aString.getLength());
}
else if (std::get<0>(aTuple) == BUFFER_ENDRUN)
Mapper().endCharacterGroup();
@@ -1679,9 +1805,11 @@ void RTFDocumentImpl::replayBuffer(RTFBuffer_t& rBuffer, RTFSprms* const pSprms,
// Set current shape during replay, needed by e.g. wrap in
// background.
+ RTFShape aShape = m_aStates.top().getShape();
m_aStates.top().getShape() = std::get<1>(aTuple)->getShape();
m_pSdrImport->resolve(std::get<1>(aTuple)->getShape(), true, RTFSdrImport::SHAPE);
+ m_aStates.top().getShape() = std::move(aShape);
m_aStates.top().setCurrentBuffer(pCurrentBuffer);
}
else if (std::get<0>(aTuple) == BUFFER_ENDSHAPE)
@@ -1759,49 +1887,49 @@ RTFError RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int n
// Underline toggles.
switch (nKeyword)
{
- case RTF_UL:
+ case RTFKeyword::UL:
nSprm = NS_ooxml::LN_Value_ST_Underline_single;
break;
- case RTF_ULDASH:
+ case RTFKeyword::ULDASH:
nSprm = NS_ooxml::LN_Value_ST_Underline_dash;
break;
- case RTF_ULDASHD:
+ case RTFKeyword::ULDASHD:
nSprm = NS_ooxml::LN_Value_ST_Underline_dotDash;
break;
- case RTF_ULDASHDD:
+ case RTFKeyword::ULDASHDD:
nSprm = NS_ooxml::LN_Value_ST_Underline_dotDotDash;
break;
- case RTF_ULDB:
+ case RTFKeyword::ULDB:
nSprm = NS_ooxml::LN_Value_ST_Underline_double;
break;
- case RTF_ULHWAVE:
+ case RTFKeyword::ULHWAVE:
nSprm = NS_ooxml::LN_Value_ST_Underline_wavyHeavy;
break;
- case RTF_ULLDASH:
+ case RTFKeyword::ULLDASH:
nSprm = NS_ooxml::LN_Value_ST_Underline_dashLong;
break;
- case RTF_ULTH:
+ case RTFKeyword::ULTH:
nSprm = NS_ooxml::LN_Value_ST_Underline_thick;
break;
- case RTF_ULTHD:
+ case RTFKeyword::ULTHD:
nSprm = NS_ooxml::LN_Value_ST_Underline_dottedHeavy;
break;
- case RTF_ULTHDASH:
+ case RTFKeyword::ULTHDASH:
nSprm = NS_ooxml::LN_Value_ST_Underline_dashedHeavy;
break;
- case RTF_ULTHDASHD:
+ case RTFKeyword::ULTHDASHD:
nSprm = NS_ooxml::LN_Value_ST_Underline_dashDotHeavy;
break;
- case RTF_ULTHDASHDD:
+ case RTFKeyword::ULTHDASHDD:
nSprm = NS_ooxml::LN_Value_ST_Underline_dashDotDotHeavy;
break;
- case RTF_ULTHLDASH:
+ case RTFKeyword::ULTHLDASH:
nSprm = NS_ooxml::LN_Value_ST_Underline_dashLongHeavy;
break;
- case RTF_ULULDBWAVE:
+ case RTFKeyword::ULULDBWAVE:
nSprm = NS_ooxml::LN_Value_ST_Underline_wavyDouble;
break;
- case RTF_ULWAVE:
+ case RTFKeyword::ULWAVE:
nSprm = NS_ooxml::LN_Value_ST_Underline_wave;
break;
default:
@@ -1818,19 +1946,19 @@ RTFError RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int n
// Accent characters (over dot / over comma).
switch (nKeyword)
{
- case RTF_ACCNONE:
+ case RTFKeyword::ACCNONE:
nSprm = NS_ooxml::LN_Value_ST_Em_none;
break;
- case RTF_ACCDOT:
+ case RTFKeyword::ACCDOT:
nSprm = NS_ooxml::LN_Value_ST_Em_dot;
break;
- case RTF_ACCCOMMA:
+ case RTFKeyword::ACCCOMMA:
nSprm = NS_ooxml::LN_Value_ST_Em_comma;
break;
- case RTF_ACCCIRCLE:
+ case RTFKeyword::ACCCIRCLE:
nSprm = NS_ooxml::LN_Value_ST_Em_circle;
break;
- case RTF_ACCUNDERDOT:
+ case RTFKeyword::ACCUNDERDOT:
nSprm = NS_ooxml::LN_Value_ST_Em_underDot;
break;
default:
@@ -1846,66 +1974,66 @@ RTFError RTFDocumentImpl::dispatchToggle(RTFKeyword nKeyword, bool bParam, int n
// Trivial character sprms.
switch (nKeyword)
{
- case RTF_B:
- case RTF_AB:
+ case RTFKeyword::B:
+ case RTFKeyword::AB:
switch (m_aStates.top().getRunType())
{
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;
}
break;
- case RTF_I:
- case RTF_AI:
+ case RTFKeyword::I:
+ case RTFKeyword::AI:
switch (m_aStates.top().getRunType())
{
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;
}
break;
- case RTF_OUTL:
+ case RTFKeyword::OUTL:
nSprm = NS_ooxml::LN_EG_RPrBase_outline;
break;
- case RTF_SHAD:
+ case RTFKeyword::SHAD:
nSprm = NS_ooxml::LN_EG_RPrBase_shadow;
break;
- case RTF_V:
+ case RTFKeyword::V:
nSprm = NS_ooxml::LN_EG_RPrBase_vanish;
break;
- case RTF_STRIKE:
+ case RTFKeyword::STRIKE:
nSprm = NS_ooxml::LN_EG_RPrBase_strike;
break;
- case RTF_STRIKED:
+ case RTFKeyword::STRIKED:
nSprm = NS_ooxml::LN_EG_RPrBase_dstrike;
break;
- case RTF_SCAPS:
+ case RTFKeyword::SCAPS:
nSprm = NS_ooxml::LN_EG_RPrBase_smallCaps;
break;
- case RTF_IMPR:
+ case RTFKeyword::IMPR:
nSprm = NS_ooxml::LN_EG_RPrBase_imprint;
break;
- case RTF_CAPS:
+ case RTFKeyword::CAPS:
nSprm = NS_ooxml::LN_EG_RPrBase_caps;
break;
default:
@@ -1913,39 +2041,47 @@ 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;
}
switch (nKeyword)
{
- case RTF_ASPALPHA:
+ case RTFKeyword::ASPALPHA:
m_aStates.top().getParagraphSprms().set(NS_ooxml::LN_CT_PPrBase_autoSpaceDE,
pBoolValue);
break;
- case RTF_DELETED:
- case RTF_REVISED:
+ case RTFKeyword::DELETED:
+ case RTFKeyword::REVISED:
{
- auto pValue = new RTFValue(nKeyword == RTF_DELETED ? oox::XML_del : oox::XML_ins);
+ auto pValue
+ = new RTFValue(nKeyword == RTFKeyword::DELETED ? oox::XML_del : oox::XML_ins);
putNestedAttribute(m_aStates.top().getCharacterSprms(), NS_ooxml::LN_trackchange,
NS_ooxml::LN_token, pValue);
}
break;
- case RTF_SBAUTO:
+ case RTFKeyword::SBAUTO:
putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_spacing,
NS_ooxml::LN_CT_Spacing_beforeAutospacing, pBoolValue);
break;
- case RTF_SAAUTO:
+ case RTFKeyword::SAAUTO:
putNestedAttribute(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_spacing,
NS_ooxml::LN_CT_Spacing_afterAutospacing, pBoolValue);
break;
- case RTF_FACINGP:
+ case RTFKeyword::FACINGP:
m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_evenAndOddHeaders, pBoolValue);
break;
- case RTF_HYPHAUTO:
+ case RTFKeyword::HYPHAUTO:
m_aSettingsTableSprms.set(NS_ooxml::LN_CT_Settings_autoHyphenation, pBoolValue);
break;
- case RTF_HYPHPAR:
+ case RTFKeyword::HYPHPAR:
m_aStates.top().getParagraphSprms().set(NS_ooxml::LN_CT_PPrBase_suppressAutoHyphens,
new RTFValue(int(bParam && nParam == 0)));
break;
@@ -2009,6 +2145,8 @@ RTFError RTFDocumentImpl::pushState()
case Destination::FIELDRESULT:
case Destination::SHAPETEXT:
case Destination::FORMFIELD:
+ //TODO: if this is pushed then the font encoding is used which results in a broken command string
+ // if it is not pushed to NORMAL then it is not restored in time.
case Destination::FIELDINSTRUCTION:
case Destination::PICT:
m_aStates.top().setDestination(Destination::NORMAL);
@@ -2081,7 +2219,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
@@ -2090,7 +2228,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;
@@ -2106,26 +2244,26 @@ 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(
NS_ooxml::LN_CT_Style_type));
assert(pStyleType);
int const nStyleType(pStyleType->getInt());
- RTFSprms const sprms(
+ RTFSprms sprms(
static_cast<RTFReferenceProperties&>(*pStyle).getSprms().cloneAndDeduplicate(
static_cast<RTFReferenceProperties&>(*itParent->second).getSprms(),
nStyleType));
- RTFSprms const attributes(
+ RTFSprms attributes(
static_cast<RTFReferenceProperties&>(*pStyle)
.getAttributes()
.cloneAndDeduplicate(
static_cast<RTFReferenceProperties&>(*itParent->second).getAttributes(),
nStyleType));
- ret[it.first] = new RTFReferenceProperties(attributes, sprms);
+ ret[it.first] = new RTFReferenceProperties(std::move(attributes), std::move(sprms));
}
else
{
@@ -2133,7 +2271,7 @@ RTFReferenceTable::Entries_t RTFDocumentImpl::deduplicateStyleTable()
}
}
}
- assert(ret.size() == m_aStyleTableEntries.size());
+ assert(ret.size() == m_pStyleTableEntries->size());
return ret;
}
@@ -2162,25 +2300,34 @@ 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;
case Destination::STYLESHEET:
{
- RTFReferenceTable::Entries_t const pStyleTableDeduplicated(deduplicateStyleTable());
+ RTFReferenceTable::Entries_t pStyleTableDeduplicated(deduplicateStyleTable());
writerfilter::Reference<Table>::Pointer_t const pTable(
- new RTFReferenceTable(pStyleTableDeduplicated));
+ new RTFReferenceTable(std::move(pStyleTableDeduplicated)));
Mapper().table(NS_ooxml::LN_STYLESHEET, pTable);
}
break;
@@ -2188,11 +2335,11 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
{
RTFSprms aListTableAttributes;
writerfilter::Reference<Properties>::Pointer_t pProp
- = new RTFReferenceProperties(aListTableAttributes, m_aListTableSprms);
+ = new RTFReferenceProperties(std::move(aListTableAttributes), m_aListTableSprms);
RTFReferenceTable::Entries_t aListTableEntries;
aListTableEntries.insert(std::make_pair(0, pProp));
writerfilter::Reference<Table>::Pointer_t const pTable(
- new RTFReferenceTable(aListTableEntries));
+ new RTFReferenceTable(std::move(aListTableEntries)));
Mapper().table(NS_ooxml::LN_NUMBERING, pTable);
}
break;
@@ -2210,7 +2357,7 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
if (!m_aStates.top().getCurrentBuffer())
{
writerfilter::Reference<Properties>::Pointer_t pProperties
- = new RTFReferenceProperties(aFFAttributes, aFFSprms);
+ = new RTFReferenceProperties(std::move(aFFAttributes), std::move(aFFSprms));
Mapper().props(pProperties);
}
else
@@ -2220,7 +2367,10 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
}
m_aFormfieldAttributes.clear();
m_aFormfieldSprms.clear();
- singleChar(cFieldSep);
+
+ if (m_aStates.top().isFieldLocked())
+ singleChar(cFieldLock);
+ singleChar(cFieldSep, true);
}
break;
case Destination::FIELDRESULT:
@@ -2230,11 +2380,11 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
{
// Read the picture into m_aStates.top().aDestinationText.
pushState();
- dispatchDestination(RTF_PICT);
+ dispatchDestination(RTFKeyword::PICT);
if (m_aPicturePath.endsWith(".png"))
- dispatchFlag(RTF_PNGBLIP);
+ dispatchFlag(RTFKeyword::PNGBLIP);
OUString aFileURL = m_rMediaDescriptor.getUnpackedValueOrDefault(
- utl::MediaDescriptor::PROP_URL(), OUString());
+ utl::MediaDescriptor::PROP_URL, OUString());
OUString aPictureURL;
try
{
@@ -2258,7 +2408,7 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
aStream.ReadUChar(ch);
if (ch < 16)
aBuf.append("0");
- aBuf.append(OUString::number(ch, 16));
+ aBuf.append(static_cast<sal_Int32>(ch), 16);
}
m_aStates.top().getDestinationText() = aBuf;
}
@@ -2376,8 +2526,8 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
// Also buffer the RTFPicture of the state stack as it contains
// the shape size.
auto pPictureValue = new RTFValue(m_aStates.top().getPicture());
- m_aStates.top().getCurrentBuffer()->push_back(
- Buf_t(BUFFER_PICTURE, pPictureValue, nullptr));
+ m_aStates.top().getCurrentBuffer()->emplace_back(BUFFER_PICTURE, pPictureValue,
+ nullptr);
auto pValue = new RTFValue(m_aStates.top().getShape());
// Buffer wrap type.
@@ -2391,8 +2541,8 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
}
}
- m_aStates.top().getCurrentBuffer()->push_back(
- Buf_t(BUFFER_RESOLVESHAPE, pValue, nullptr));
+ m_aStates.top().getCurrentBuffer()->emplace_back(BUFFER_RESOLVESHAPE, pValue,
+ nullptr);
}
}
else if (rState.getInShapeGroup() && !rState.getInShape())
@@ -2442,12 +2592,12 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
OUString str(m_aStates.top().getCurrentDestinationText()->makeStringAndClear());
// dmapper expects this as a field, so let's fake something...
auto const field((Destination::INDEXENTRY == rState.getDestination())
- ? OUStringLiteral(u"XE")
- : OUStringLiteral(u"TC"));
- str = field + " \"" + str.replaceAll("\"", "\\\"") + "\"";
+ ? std::u16string_view(u"XE")
+ : std::u16string_view(u"TC"));
+ str = OUString::Concat(field) + " \"" + str.replaceAll("\"", "\\\"") + "\"";
singleChar(cFieldStart);
- Mapper().utext(reinterpret_cast<sal_uInt8 const*>(str.getStr()), str.getLength());
- singleChar(cFieldSep);
+ Mapper().utext(str.getStr(), str.getLength());
+ singleChar(cFieldSep, true);
// no result
singleChar(cFieldEnd);
}
@@ -2469,19 +2619,22 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
break; // not for nested group
auto pValue
= new RTFValue(m_aStates.top().getCurrentDestinationText()->makeStringAndClear());
- m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_listEntry, pValue);
+ // OOXML puts these into a LN_CT_FFData_ddList but FFDataHandler should handle this too
+ m_aFormfieldSprms.set(NS_ooxml::LN_CT_FFDDList_listEntry, pValue,
+ RTFOverwrite::NO_APPEND);
}
break;
case Destination::DATAFIELD:
{
if (m_bFormField)
{
- if (&m_aStates.top().getDestinationText()
- != m_aStates.top().getCurrentDestinationText())
+ OUStringBuffer* pCurrentDestinationText
+ = m_aStates.top().getCurrentDestinationText();
+ if (&m_aStates.top().getDestinationText() != pCurrentDestinationText)
break; // not for nested group
- OString aStr = OUStringToOString(
- m_aStates.top().getCurrentDestinationText()->makeStringAndClear(),
- rState.getCurrentEncoding());
+ OString aStr
+ = OUStringToOString(*pCurrentDestinationText, rState.getCurrentEncoding());
+ pCurrentDestinationText->setLength(0);
// decode hex dump
OStringBuffer aBuf;
int b = 0;
@@ -2563,8 +2716,13 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
!= m_aStates.top().getCurrentDestinationText())
break; // not for nested group
if (m_xDocumentProperties.is())
- m_xDocumentProperties->setKeywords(comphelper::string::convertCommaSeparated(
- m_aStates.top().getCurrentDestinationText()->makeStringAndClear()));
+ {
+ OUStringBuffer* pCurrentDestinationText
+ = m_aStates.top().getCurrentDestinationText();
+ m_xDocumentProperties->setKeywords(
+ comphelper::string::convertCommaSeparated(*pCurrentDestinationText));
+ pCurrentDestinationText->setLength(0);
+ }
break;
case Destination::COMMENT:
if (&m_aStates.top().getDestinationText()
@@ -2609,8 +2767,7 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
break; // not for nested group
OUString aName = rState.getDestination() == Destination::OPERATOR ? OUString("Operator")
: OUString("Company");
- uno::Any aValue
- = uno::makeAny(m_aStates.top().getCurrentDestinationText()->makeStringAndClear());
+ uno::Any aValue(m_aStates.top().getCurrentDestinationText()->makeStringAndClear());
if (m_xDocumentProperties.is())
{
uno::Reference<beans::XPropertyContainer> xUserDefinedProperties
@@ -2651,7 +2808,7 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
{
// if the object is in a special container we will use the \result
// element instead of the \objdata
- // (see RTF_OBJECT in RTFDocumentImpl::dispatchDestination)
+ // (see RTFKeyword::OBJECT in RTFDocumentImpl::dispatchDestination)
break;
}
@@ -2664,7 +2821,7 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
auto pValue = new RTFValue(m_aObjectAttributes, aObjectSprms);
aObjSprms.set(NS_ooxml::LN_object, pValue);
writerfilter::Reference<Properties>::Pointer_t pProperties
- = new RTFReferenceProperties(aObjAttributes, aObjSprms);
+ = new RTFReferenceProperties(std::move(aObjAttributes), std::move(aObjSprms));
uno::Reference<drawing::XShape> xShape;
RTFValue::Pointer_t pShape = m_aObjectAttributes.find(NS_ooxml::LN_shape);
OSL_ASSERT(pShape);
@@ -2683,18 +2840,17 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
break;
case Destination::ANNOTATIONDATE:
{
- if (&m_aStates.top().getDestinationText()
- != m_aStates.top().getCurrentDestinationText())
+ OUStringBuffer* pCurrentDestinationText = m_aStates.top().getCurrentDestinationText();
+ if (&m_aStates.top().getDestinationText() != pCurrentDestinationText)
break; // not for nested group
- OUString aStr(OStringToOUString(
- DTTM22OString(
- m_aStates.top().getCurrentDestinationText()->makeStringAndClear().toInt32()),
- rState.getCurrentEncoding()));
+ OUString aStr(OStringToOUString(DTTM22OString(o3tl::toInt32(*pCurrentDestinationText)),
+ rState.getCurrentEncoding()));
+ pCurrentDestinationText->setLength(0);
auto pValue = new RTFValue(aStr);
RTFSprms aAnnAttributes;
aAnnAttributes.set(NS_ooxml::LN_CT_TrackChange_date, pValue);
writerfilter::Reference<Properties>::Pointer_t pProperties
- = new RTFReferenceProperties(aAnnAttributes);
+ = new RTFReferenceProperties(std::move(aAnnAttributes));
Mapper().props(pProperties);
}
break;
@@ -2723,10 +2879,10 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
aAttributes.set(NS_ooxml::LN_EG_RangeMarkupElements_commentRangeStart, pValue);
else
aAttributes.set(NS_ooxml::LN_EG_RangeMarkupElements_commentRangeEnd, pValue);
- writerfilter::Reference<Properties>::Pointer_t pProperties
- = new RTFReferenceProperties(aAttributes);
if (!m_aStates.top().getCurrentBuffer())
{
+ writerfilter::Reference<Properties>::Pointer_t pProperties
+ = new RTFReferenceProperties(std::move(aAttributes));
Mapper().props(pProperties);
}
else
@@ -2744,7 +2900,7 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
OUString aStr = m_aStates.top().getCurrentDestinationText()->makeStringAndClear();
RTFSprms aAnnAttributes;
aAnnAttributes.set(NS_ooxml::LN_CT_Markup_id, new RTFValue(aStr.toInt32()));
- Mapper().props(new RTFReferenceProperties(aAnnAttributes));
+ Mapper().props(new RTFReferenceProperties(std::move(aAnnAttributes)));
}
break;
case Destination::FALT:
@@ -2768,15 +2924,15 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
bool bTextFrame = xServiceInfo->supportsService("com.sun.star.text.TextFrame");
// The default is certainly not inline, but then what Word supports is just at-character.
- xPropertySet->setPropertyValue(
- "AnchorType", uno::makeAny(text::TextContentAnchorType_AT_CHARACTER));
+ xPropertySet->setPropertyValue("AnchorType",
+ uno::Any(text::TextContentAnchorType_AT_CHARACTER));
if (bTextFrame)
{
xPropertySet->setPropertyValue("HoriOrientPosition",
- uno::makeAny(rDrawing.getLeft()));
+ uno::Any(rDrawing.getLeft()));
xPropertySet->setPropertyValue("VertOrientPosition",
- uno::makeAny(rDrawing.getTop()));
+ uno::Any(rDrawing.getTop()));
}
else
{
@@ -2786,22 +2942,21 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
if (rDrawing.getHasLineColor())
{
- uno::Any aLineColor = uno::makeAny(sal_uInt32((rDrawing.getLineColorR() << 16)
- + (rDrawing.getLineColorG() << 8)
- + rDrawing.getLineColorB()));
+ uno::Any aLineColor(sal_uInt32((rDrawing.getLineColorR() << 16)
+ + (rDrawing.getLineColorG() << 8)
+ + rDrawing.getLineColorB()));
uno::Any aLineWidth;
RTFSdrImport::resolveLineColorAndWidth(bTextFrame, xPropertySet, aLineColor,
aLineWidth);
}
if (rDrawing.getHasFillColor())
xPropertySet->setPropertyValue(
- "FillColor", uno::makeAny(sal_uInt32((rDrawing.getFillColorR() << 16)
- + (rDrawing.getFillColorG() << 8)
- + rDrawing.getFillColorB())));
+ "FillColor", uno::Any(sal_uInt32((rDrawing.getFillColorR() << 16)
+ + (rDrawing.getFillColorG() << 8)
+ + rDrawing.getFillColorB())));
else if (!bTextFrame)
// If there is no fill, the Word default is 100% transparency.
- xPropertySet->setPropertyValue("FillTransparence",
- uno::makeAny(sal_Int32(100)));
+ xPropertySet->setPropertyValue("FillTransparence", uno::Any(sal_Int32(100)));
RTFSdrImport::resolveFLine(xPropertySet, rDrawing.getFLine());
@@ -2823,7 +2978,11 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
case Destination::SHAPE:
m_bNeedFinalPar = true;
m_bNeedCr = m_bNeedCrOrig;
- if (rState.getFrame().inFrame())
+ // tdf#47036 insert paragraph break for graphic object inside text
+ // frame at start of document - TODO: the object may actually be
+ // anchored inside the text frame and this ends up putting the
+ // anchor in the body, but better than losing the shape...
+ if (rState.getFrame().hasProperties() && m_pSdrImport->isTextGraphicObject())
{
// parBreak() modifies m_aStates.top() so we can't apply resetFrame() directly on aState
resetFrame();
@@ -2846,18 +3005,15 @@ RTFError RTFDocumentImpl::beforePopState(RTFParserState& rState)
{
uno::Reference<util::XCloseable> xComponent(xObject->getComponent(),
uno::UNO_SET_THROW);
- // gcc4.4 (and 4.3 and possibly older) have a problem with dynamic_cast directly to the target class,
- // so help it with an intermediate cast. I'm not sure what exactly the problem is, seems to be unrelated
- // to RTLD_GLOBAL, so most probably a gcc bug.
- auto& rImport = dynamic_cast<oox::FormulaImportBase&>(
- dynamic_cast<SfxBaseModel&>(*xComponent));
- rImport.readFormulaOoxml(m_aMathBuffer);
+ if (oox::FormulaImExportBase* pImport
+ = dynamic_cast<oox::FormulaImExportBase*>(xComponent.get()))
+ pImport->readFormulaOoxml(m_aMathBuffer);
auto pValue = new RTFValue(xObject);
RTFSprms aMathAttributes;
aMathAttributes.set(NS_ooxml::LN_starmath, pValue);
writerfilter::Reference<Properties>::Pointer_t pProperties
- = new RTFReferenceProperties(aMathAttributes);
+ = new RTFReferenceProperties(std::move(aMathAttributes));
Mapper().props(pProperties);
}
@@ -3251,20 +3407,20 @@ void RTFDocumentImpl::afterPopState(RTFParserState& rState)
// Table
RTFSprms aListTableAttributes;
- writerfilter::Reference<Properties>::Pointer_t pProp
- = new RTFReferenceProperties(aListTableAttributes, aListTableSprms);
+ writerfilter::Reference<Properties>::Pointer_t pProp = new RTFReferenceProperties(
+ std::move(aListTableAttributes), std::move(aListTableSprms));
RTFReferenceTable::Entries_t aListTableEntries;
aListTableEntries.insert(std::make_pair(0, pProp));
writerfilter::Reference<Table>::Pointer_t const pTable(
- new RTFReferenceTable(aListTableEntries));
+ new RTFReferenceTable(std::move(aListTableEntries)));
Mapper().table(NS_ooxml::LN_NUMBERING, pTable);
// Use it
putNestedSprm(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_numPr,
- NS_ooxml::LN_CT_NumPr_ilvl, pIlvlValue);
+ NS_ooxml::LN_CT_NumPr_ilvl, pIlvlValue, RTFOverwrite::YES_PREPEND);
putNestedSprm(m_aStates.top().getParagraphSprms(), NS_ooxml::LN_CT_PPrBase_numPr,
- NS_ooxml::LN_CT_NumPr_numId, pIdValue);
+ NS_ooxml::LN_CT_NumPr_numId, pIdValue, RTFOverwrite::YES_PREPEND);
}
}
break;
@@ -3361,6 +3517,30 @@ void RTFDocumentImpl::afterPopState(RTFParserState& rState)
if (rState.getFieldStatus() == RTFFieldStatus::INSTRUCTION)
singleChar(cFieldEnd);
break;
+ case Destination::DOCVAR:
+ if (!m_aStates.empty())
+ {
+ OUString docvar(rState.getDocVar());
+ if (m_aStates.top().getDocVarName().isEmpty())
+ {
+ m_aStates.top().setDocVarName(docvar);
+ }
+ else
+ {
+ uno::Reference<beans::XPropertySet> xMaster(
+ m_xModelFactory->createInstance("com.sun.star.text.FieldMaster.User"),
+ uno::UNO_QUERY_THROW);
+ xMaster->setPropertyValue("Name", uno::Any(m_aStates.top().getDocVarName()));
+ uno::Reference<text::XDependentTextField> xField(
+ m_xModelFactory->createInstance("com.sun.star.text.TextField.User"),
+ uno::UNO_QUERY);
+ xField->attachTextFieldMaster(xMaster);
+ xField->getTextFieldMaster()->setPropertyValue("Content", uno::Any(docvar));
+
+ m_aStates.top().clearDocVarName();
+ }
+ }
+ break;
case Destination::SHAPEPROPERTYVALUEPICT:
if (!m_aStates.empty())
{
@@ -3427,8 +3607,8 @@ void RTFDocumentImpl::afterPopState(RTFParserState& rState)
if (!m_aStates.top().getCurrentBuffer())
m_pSdrImport->close();
else
- m_aStates.top().getCurrentBuffer()->push_back(
- Buf_t(BUFFER_ENDSHAPE, nullptr, nullptr));
+ m_aStates.top().getCurrentBuffer()->emplace_back(BUFFER_ENDSHAPE, nullptr,
+ nullptr);
}
// It's allowed to declare these inside the shape text, and they
@@ -3465,7 +3645,7 @@ RTFError RTFDocumentImpl::popState()
checkUnicode(/*bUnicode =*/true, /*bHex =*/true);
RTFParserState aState(m_aStates.top());
- m_bWasInFrame = aState.getFrame().inFrame();
+ m_bWasInFrame = aState.getFrame().hasProperties();
// dmapper expects some content in header/footer, so if there would be nothing, add an empty paragraph.
if (m_pTokenizer->getGroup() == 1 && m_bFirstRun)
@@ -3478,7 +3658,7 @@ RTFError RTFDocumentImpl::popState()
case NS_ooxml::LN_footerl:
case NS_ooxml::LN_footerr:
case NS_ooxml::LN_footerf:
- dispatchSymbol(RTF_PAR);
+ dispatchSymbol(RTFKeyword::PAR);
break;
}
}
@@ -3494,7 +3674,7 @@ RTFError RTFDocumentImpl::popState()
auto pValue = new RTFValue(0);
aTCSprms.set(NS_ooxml::LN_endtrackchange, pValue);
if (!m_aStates.top().getCurrentBuffer())
- Mapper().props(new RTFReferenceProperties(RTFSprms(), aTCSprms));
+ Mapper().props(new RTFReferenceProperties(RTFSprms(), std::move(aTCSprms)));
else
bufferProperties(*m_aStates.top().getCurrentBuffer(),
new RTFValue(RTFSprms(), aTCSprms), nullptr);
@@ -3506,10 +3686,28 @@ RTFError RTFDocumentImpl::popState()
// \par means an empty paragraph at the end of footnotes/endnotes, but
// not in case of other substreams, like headers.
if (m_bNeedCr && m_nStreamType != NS_ooxml::LN_footnote
- && m_nStreamType != NS_ooxml::LN_endnote && m_bIsNewDoc)
- dispatchSymbol(RTF_PAR);
+ && m_nStreamType != NS_ooxml::LN_endnote)
+ {
+ if (!m_bIsNewDoc)
+ {
+ // Make sure all the paragraph settings are set, but do not add next paragraph
+ Mapper().markLastParagraph();
+ }
+ dispatchSymbol(RTFKeyword::PAR);
+ }
if (m_bNeedSect) // may be set by dispatchSymbol above!
sectBreak(true);
+ else if (!m_pSuperstream)
+ {
+ Mapper().markLastSectionGroup(); // ensure it's set for \par below
+ }
+ if (m_bNeedPar && !m_pSuperstream)
+ {
+ assert(!m_bNeedSect);
+ dispatchSymbol(RTFKeyword::PAR);
+ m_bNeedSect = false; // reset - m_bNeedPar was set for \sect at
+ // end of doc so don't need another one
+ }
}
m_aStates.pop();
@@ -3528,11 +3726,11 @@ RTFError RTFDocumentImpl::popState()
if (!m_aStates.empty() && m_aStates.top().getTableRowWidthAfter() > 0
&& aState.getTableRowWidthAfter() == 0)
- // An RTF_ROW in the inner group already parsed nTableRowWidthAfter,
+ // An RTFKeyword::ROW in the inner group already parsed nTableRowWidthAfter,
// don't do it again in the outer state later.
m_aStates.top().setTableRowWidthAfter(0);
- if (m_nResetBreakOnSectBreak != RTF_invalid && !m_aStates.empty())
+ if (m_nResetBreakOnSectBreak != RTFKeyword::invalid && !m_aStates.empty())
{
// Section break type created for \page still has an effect in the
// outer state as well.
@@ -3547,17 +3745,16 @@ RTFError RTFDocumentImpl::popState()
RTFError RTFDocumentImpl::handleEmbeddedObject()
{
- OString aStr
- = OUStringToOString(m_aStates.top().getCurrentDestinationText()->makeStringAndClear(),
- RTL_TEXTENCODING_ASCII_US);
+ OUStringBuffer* pCurrentDestinationText = m_aStates.top().getCurrentDestinationText();
+ OString aStr = OUStringToOString(*pCurrentDestinationText, RTL_TEXTENCODING_ASCII_US);
+ pCurrentDestinationText->setLength(0);
std::unique_ptr<SvStream> pStream(new SvMemoryStream());
if (!msfilter::rtfutil::ExtractOLE2FromObjdata(aStr, *pStream))
return RTFError::HEX_INVALID;
uno::Reference<io::XInputStream> xInputStream(
new utl::OSeekableInputStreamWrapper(pStream.release(), /*_bOwner=*/true));
- auto pStreamValue = new RTFValue(xInputStream);
- m_aOLEAttributes.set(NS_ooxml::LN_inputstream, pStreamValue);
+ m_aOLEAttributes.set(NS_ooxml::LN_inputstream, new RTFValue(xInputStream));
return RTFError::OK;
}
@@ -3580,7 +3777,7 @@ void RTFDocumentImpl::setDestination(Destination eDestination)
// this is a questionably named method that is used only in a very special
// situation where it looks like the "current" buffer is needed?
-void RTFDocumentImpl::setDestinationText(OUString const& rString)
+void RTFDocumentImpl::setDestinationText(std::u16string_view rString)
{
m_aStates.top().getDestinationText().setLength(0);
m_aStates.top().getDestinationText().append(rString);
@@ -3624,10 +3821,13 @@ void RTFDocumentImpl::checkUnicode(bool bUnicode, bool bHex)
if (bHex && !m_aHexBuffer.isEmpty())
{
rtl_TextEncoding nEncoding = m_aStates.top().getCurrentEncoding();
- if (m_aStates.top().getDestination() == Destination::FONTENTRY
- && m_aStates.top().getCurrentEncoding() == RTL_TEXTENCODING_SYMBOL)
+ if (nEncoding == RTL_TEXTENCODING_SYMBOL
+ && (m_aStates.top().getDestination() == Destination::FONTENTRY
+ || (m_aStates.size() > 1
+ && m_aStates[m_aStates.size() - 2].getDestination()
+ == Destination::FIELDINSTRUCTION)))
nEncoding = RTL_TEXTENCODING_MS_1252;
- OUString aString = OStringToOUString(m_aHexBuffer.toString(), nEncoding);
+ OUString aString = OStringToOUString(m_aHexBuffer, nEncoding);
m_aHexBuffer.setLength(0);
aString = FilterControlChars(m_aStates.top().getDestination(), aString);
text(aString);
@@ -3639,6 +3839,7 @@ RTFParserState::RTFParserState(RTFDocumentImpl* pDocumentImpl)
, m_nInternalState(RTFInternalState::NORMAL)
, m_eDestination(Destination::NORMAL)
, m_eFieldStatus(RTFFieldStatus::NONE)
+ , m_bFieldLocked(false)
, m_nBorderState(RTFBorderState::NONE)
, m_nCurrentEncoding(rtl_getTextEncodingFromWindowsCharset(0))
, m_nUc(1)
@@ -3654,7 +3855,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)
@@ -3671,11 +3872,15 @@ RTFParserState::RTFParserState(RTFDocumentImpl* pDocumentImpl)
void RTFDocumentImpl::resetFrame() { m_aStates.top().getFrame() = RTFFrame(&m_aStates.top()); }
void RTFDocumentImpl::bufferProperties(RTFBuffer_t& rBuffer, const RTFValue::Pointer_t& pValue,
- const tools::SvRef<TableRowBuffer>& pTableProperties)
+ const tools::SvRef<TableRowBuffer>& pTableProperties,
+ Id const nStyleType)
{
- rBuffer.emplace_back(
- Buf_t(BUFFER_SETSTYLE, new RTFValue(m_aStates.top().getCurrentStyleIndex()), nullptr));
- rBuffer.emplace_back(Buf_t(BUFFER_PROPS, pValue, pTableProperties));
+ rBuffer.emplace_back(BUFFER_SETSTYLE, new RTFValue(m_aStates.top().getCurrentStyleIndex()),
+ nullptr);
+ assert(nStyleType == 0 || nStyleType == NS_ooxml::LN_Value_ST_StyleType_character);
+ rBuffer.emplace_back(nStyleType == NS_ooxml::LN_Value_ST_StyleType_character ? BUFFER_PROPS_CHAR
+ : BUFFER_PROPS,
+ pValue, pTableProperties);
}
RTFShape::RTFShape() = default;
@@ -3700,11 +3905,6 @@ RTFFrame::RTFFrame(RTFParserState* pParserState)
void RTFFrame::setSprm(Id nId, Id nValue)
{
- if (m_pDocumentImpl->getFirstRun() && !m_pDocumentImpl->isStyleSheetImport())
- {
- m_pDocumentImpl->checkFirstRun();
- m_pDocumentImpl->setNeedPar(false);
- }
switch (nId)
{
case NS_ooxml::LN_CT_FramePr_w:
@@ -3743,6 +3943,12 @@ void RTFFrame::setSprm(Id nId, Id nValue)
default:
break;
}
+
+ if (m_pDocumentImpl->getFirstRun() && !m_pDocumentImpl->isStyleSheetImport() && hasProperties())
+ {
+ m_pDocumentImpl->checkFirstRun();
+ m_pDocumentImpl->setNeedPar(false);
+ }
}
RTFSprms RTFFrame::getSprms()
@@ -3797,7 +4003,7 @@ RTFSprms RTFFrame::getSprms()
case NS_ooxml::LN_CT_FramePr_hAnchor:
{
if (m_nHoriAnchor == 0)
- m_nHoriAnchor = NS_ooxml::LN_Value_doc_ST_HAnchor_margin;
+ m_nHoriAnchor = NS_ooxml::LN_Value_doc_ST_HAnchor_text;
pValue = new RTFValue(m_nHoriAnchor);
}
break;
@@ -3842,9 +4048,13 @@ RTFSprms RTFFrame::getSprms()
bool RTFFrame::hasProperties() const
{
- return m_nX != 0 || m_nY != 0 || m_nW != 0 || m_nH != 0 || m_nHoriPadding != 0
- || m_nVertPadding != 0 || m_nHoriAlign != 0 || m_nHoriAnchor != 0 || m_nVertAlign != 0
- || m_nVertAnchor != 0;
+ // tdf#153178 \dxfrtext \dfrmtxtx \dfrmtxty \wrapdefault do *not* create frame
+ return m_nX != 0 || m_nY != 0 || m_nW != 0 || m_nH != 0
+ || (m_nHoriAlign && m_nHoriAlign != NS_ooxml::LN_Value_doc_ST_XAlign_left)
+ || (m_nHoriAnchor && m_nHoriAnchor != NS_ooxml::LN_Value_doc_ST_HAnchor_text)
+ || (m_nVertAlign && m_nVertAlign != NS_ooxml::LN_Value_doc_ST_YAlign_inline)
+ || (m_nVertAnchor && m_nVertAnchor != NS_ooxml::LN_Value_doc_ST_VAnchor_margin)
+ || (m_oWrap && *m_oWrap != NS_ooxml::LN_Value_doc_ST_Wrap_auto);
}
} // namespace writerfilter