summaryrefslogtreecommitdiffstats
path: root/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'writerfilter/source/ooxml/OOXMLFastContextHandler.cxx')
-rw-r--r--writerfilter/source/ooxml/OOXMLFastContextHandler.cxx2307
1 files changed, 2307 insertions, 0 deletions
diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
new file mode 100644
index 000000000..c4ee2c048
--- /dev/null
+++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
@@ -0,0 +1,2307 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/text/RelOrientation.hpp>
+#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
+#include <com/sun/star/xml/sax/SAXException.hpp>
+#include <ooxml/resourceids.hxx>
+#include <oox/mathml/import.hxx>
+#include <oox/token/namespaces.hxx>
+#include <sal/log.hxx>
+#include <comphelper/embeddedobjectcontainer.hxx>
+#include <comphelper/propertyvalue.hxx>
+#include <cppuhelper/exc_hlp.hxx>
+#include <tools/globname.hxx>
+#include <comphelper/classids.hxx>
+#include <sfx2/sfxbasemodel.hxx>
+#include "OOXMLFastContextHandler.hxx"
+#include "OOXMLFactory.hxx"
+#include "Handler.hxx"
+#include <dmapper/CommentProperties.hxx>
+#include <dmapper/PropertyIds.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+
+const sal_Unicode uCR = 0xd;
+const sal_Unicode uFtnEdnRef = 0x2;
+const sal_Unicode uFtnEdnSep = 0x3;
+const sal_Unicode uFtnSep = 0x5;
+const sal_Unicode uTab = 0x9;
+const sal_Unicode uPgNum = 0x0;
+const sal_Unicode uNoBreakHyphen = 0x2011;
+const sal_Unicode uSoftHyphen = 0xAD;
+
+const sal_uInt8 cFtnEdnCont = 0x4;
+
+namespace writerfilter::ooxml
+{
+using namespace ::com::sun::star;
+using namespace oox;
+using namespace ::std;
+using namespace ::com::sun::star::xml::sax;
+
+/*
+ class OOXMLFastContextHandler
+ */
+
+OOXMLFastContextHandler::OOXMLFastContextHandler
+(uno::Reference< uno::XComponentContext > const & context)
+: mpParent(nullptr),
+ mId(0),
+ mnDefine(0),
+ mnToken(oox::XML_TOKEN_COUNT),
+ mnMathJcVal(0),
+ mbIsMathPara(false),
+ mpStream(nullptr),
+ mnTableDepth(0),
+ inPositionV(false),
+ mbAllowInCell(true),
+ mbIsVMLfound(false),
+ m_xContext(context),
+ m_bDiscardChildren(false),
+ m_bTookChoice(false)
+{
+ if (!mpParserState)
+ mpParserState = new OOXMLParserState();
+
+ mpParserState->incContextCount();
+}
+
+OOXMLFastContextHandler::OOXMLFastContextHandler(OOXMLFastContextHandler * pContext)
+: mpParent(pContext),
+ mId(0),
+ mnDefine(0),
+ mnToken(oox::XML_TOKEN_COUNT),
+ mnMathJcVal(pContext->mnMathJcVal),
+ mbIsMathPara(pContext->mbIsMathPara),
+ mpStream(pContext->mpStream),
+ mpParserState(pContext->mpParserState),
+ mnTableDepth(pContext->mnTableDepth),
+ inPositionV(pContext->inPositionV),
+ mbAllowInCell(pContext->mbAllowInCell),
+ mbIsVMLfound(pContext->mbIsVMLfound),
+ m_xContext(pContext->m_xContext),
+ m_bDiscardChildren(pContext->m_bDiscardChildren),
+ m_bTookChoice(pContext->m_bTookChoice)
+{
+ if (!mpParserState)
+ mpParserState = new OOXMLParserState();
+
+ mpParserState->incContextCount();
+}
+
+OOXMLFastContextHandler::~OOXMLFastContextHandler()
+{
+}
+
+bool OOXMLFastContextHandler::prepareMceContext(Token_t nElement, const uno::Reference<xml::sax::XFastAttributeList>& rAttribs)
+{
+ switch (oox::getBaseToken(nElement))
+ {
+ case XML_AlternateContent:
+ {
+ SavedAlternateState aState;
+ aState.m_bDiscardChildren = m_bDiscardChildren;
+ m_bDiscardChildren = false;
+ aState.m_bTookChoice = m_bTookChoice;
+ m_bTookChoice = false;
+ mpParserState->getSavedAlternateStates().push_back(aState);
+ }
+ break;
+ case XML_Choice:
+ {
+ OUString aRequires = rAttribs->getOptionalValue(XML_Requires);
+ static const char* aFeatures[] = {
+ "wps",
+ "wpg",
+ "w14",
+ };
+ for (const char *p : aFeatures)
+ {
+ if (aRequires.equalsAscii(p))
+ {
+ m_bTookChoice = true;
+ return false;
+ }
+ }
+ return true;
+ }
+ break;
+ case XML_Fallback:
+ // If Choice is already taken, then let's ignore the Fallback.
+ return m_bTookChoice;
+ default:
+ SAL_WARN("writerfilter", "OOXMLFastContextHandler::prepareMceContext: unhandled element:" << oox::getBaseToken(nElement));
+ break;
+ }
+ return false;
+}
+
+// xml::sax::XFastContextHandler:
+void SAL_CALL OOXMLFastContextHandler::startFastElement
+(sal_Int32 Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ // Set xml:space value early, to allow child contexts use it when dealing with strings.
+ if (Attribs && Attribs->hasAttribute(oox::NMSP_xml | oox::XML_space))
+ {
+ mbPreserveSpace = Attribs->getValue(oox::NMSP_xml | oox::XML_space) == "preserve";
+ mbPreserveSpaceSet = true;
+ }
+ if (Element == W_TOKEN(footnote) || Element == W_TOKEN(endnote))
+ {
+ // send uFtnSep to sign new footnote content, but skip footnote separators
+ if (!Attribs->hasAttribute(W_TOKEN(type)) ||
+ ( Attribs->getValue(W_TOKEN(type)) != "separator" &&
+ Attribs->getValue(W_TOKEN(type)) != "continuationSeparator" &&
+ Attribs->getValue(W_TOKEN(type)) != "continuationNotice" ))
+ {
+ mpParserState->setStartFootnote(true);
+ }
+ }
+ else if (Element == (NMSP_officeMath | XML_oMathPara))
+ {
+ mnMathJcVal = eMathParaJc::CENTER;
+ mbIsMathPara = true;
+ }
+ else if (Element == (NMSP_officeMath | XML_jc) && mpParent && mpParent->mpParent )
+ {
+ mbIsMathPara = true;
+ auto aAttrLst = Attribs->getFastAttributes();
+ if (aAttrLst[0].Value == "center") mpParent->mpParent->mnMathJcVal = eMathParaJc::CENTER;
+ if (aAttrLst[0].Value == "left") mpParent->mpParent->mnMathJcVal = eMathParaJc::LEFT;
+ if (aAttrLst[0].Value == "right") mpParent->mpParent->mnMathJcVal = eMathParaJc::RIGHT;
+ }
+
+ if (oox::getNamespace(Element) == NMSP_mce)
+ m_bDiscardChildren = prepareMceContext(Element, Attribs);
+
+ else if (!m_bDiscardChildren)
+ {
+ attributes(Attribs);
+ lcl_startFastElement(Element, Attribs);
+ }
+}
+
+void SAL_CALL OOXMLFastContextHandler::startUnknownElement
+(const OUString & /*Namespace*/, const OUString & /*Name*/,
+ const uno::Reference< xml::sax::XFastAttributeList > & /*Attribs*/)
+{
+}
+
+void SAL_CALL OOXMLFastContextHandler::endFastElement(sal_Int32 Element)
+{
+ if (Element == (NMSP_mce | XML_Choice) || Element == (NMSP_mce | XML_Fallback))
+ m_bDiscardChildren = false;
+ else if (Element == (NMSP_mce | XML_AlternateContent))
+ {
+ SavedAlternateState aState(mpParserState->getSavedAlternateStates().back());
+ mpParserState->getSavedAlternateStates().pop_back();
+ m_bDiscardChildren = aState.m_bDiscardChildren;
+ m_bTookChoice = aState.m_bTookChoice;
+ }
+ else if (!m_bDiscardChildren)
+ lcl_endFastElement(Element);
+}
+
+void OOXMLFastContextHandler::lcl_startFastElement
+(Token_t Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & /*Attribs*/)
+{
+ OOXMLFactory::startAction(this);
+ if( Element == (NMSP_dmlWordDr|XML_positionV) )
+ inPositionV = true;
+ else if( Element == (NMSP_dmlWordDr|XML_positionH) )
+ inPositionV = false;
+
+}
+
+void OOXMLFastContextHandler::lcl_endFastElement
+(Token_t /*Element*/)
+{
+ OOXMLFactory::endAction(this);
+}
+
+void SAL_CALL OOXMLFastContextHandler::endUnknownElement
+(const OUString & , const OUString & )
+{
+}
+
+uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
+ OOXMLFastContextHandler::createFastChildContext
+(sal_Int32 Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ uno::Reference< xml::sax::XFastContextHandler > xResult;
+ if (oox::getNamespace(Element) != NMSP_mce && !m_bDiscardChildren)
+ xResult.set(lcl_createFastChildContext(Element, Attribs));
+ else if (oox::getNamespace(Element) == NMSP_mce)
+ xResult = this;
+
+ return xResult;
+}
+
+uno::Reference< xml::sax::XFastContextHandler >
+ OOXMLFastContextHandler::lcl_createFastChildContext
+(Token_t Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & /*Attribs*/)
+{
+ return OOXMLFactory::createFastChildContext(this, Element);
+}
+
+uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
+OOXMLFastContextHandler::createUnknownChildContext
+(const OUString &,
+ const OUString &,
+ const uno::Reference< xml::sax::XFastAttributeList > & /*Attribs*/)
+{
+ return uno::Reference< xml::sax::XFastContextHandler >
+ (new OOXMLFastContextHandler(*const_cast<const OOXMLFastContextHandler *>(this)));
+}
+
+void SAL_CALL OOXMLFastContextHandler::characters
+(const OUString & aChars)
+{
+ lcl_characters(aChars);
+}
+
+void OOXMLFastContextHandler::lcl_characters
+(const OUString & rString)
+{
+ if (!m_bDiscardChildren)
+ OOXMLFactory::characters(this, rString);
+}
+
+void OOXMLFastContextHandler::setStream(Stream * pStream)
+{
+ mpStream = pStream;
+}
+
+OOXMLValue::Pointer_t OOXMLFastContextHandler::getValue() const
+{
+ return OOXMLValue::Pointer_t();
+}
+
+void OOXMLFastContextHandler::attributes
+(const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ OOXMLFactory::attributes(this, Attribs);
+}
+
+void OOXMLFastContextHandler::startAction()
+{
+ OOXMLFactory::startAction(this);
+}
+
+void OOXMLFastContextHandler::endAction()
+{
+ OOXMLFactory::endAction(this);
+}
+
+void OOXMLFastContextHandler::setId(Id rId)
+{
+ mId = rId;
+}
+
+Id OOXMLFastContextHandler::getId() const
+{
+ return mId;
+}
+
+void OOXMLFastContextHandler::setDefine(Id nDefine)
+{
+ mnDefine = nDefine;
+}
+
+
+void OOXMLFastContextHandler::setToken(Token_t nToken)
+{
+ mnToken = nToken;
+}
+
+Token_t OOXMLFastContextHandler::getToken() const
+{
+ return mnToken;
+}
+
+void OOXMLFastContextHandler::sendTableDepth() const
+{
+ if (mnTableDepth <= 0)
+ return;
+
+ OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(mnTableDepth);
+ pProps->add(NS_ooxml::LN_tblDepth, pVal, OOXMLProperty::SPRM);
+ }
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
+ pProps->add(NS_ooxml::LN_inTbl, pVal, OOXMLProperty::SPRM);
+ }
+
+ mpStream->props(pProps.get());
+}
+
+void OOXMLFastContextHandler::setHandle()
+{
+ mpParserState->setHandle();
+ mpStream->info(mpParserState->getHandle());
+}
+
+void OOXMLFastContextHandler::startCharacterGroup()
+{
+ if (!isForwardEvents())
+ return;
+
+ if (mpParserState->isInCharacterGroup())
+ endCharacterGroup();
+
+ if (! mpParserState->isInParagraphGroup())
+ startParagraphGroup();
+
+ if (! mpParserState->isInCharacterGroup())
+ {
+ mpStream->startCharacterGroup();
+ mpParserState->setInCharacterGroup(true);
+ mpParserState->resolveCharacterProperties(*mpStream);
+ if (mpParserState->isStartFootnote())
+ {
+ mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uFtnSep), 1);
+ mpParserState->setStartFootnote(false);
+ }
+ }
+
+ // tdf#108714 : if we have a postponed break information,
+ // then apply it now, before any other paragraph content.
+ mpParserState->resolvePostponedBreak(*mpStream);
+}
+
+void OOXMLFastContextHandler::endCharacterGroup()
+{
+ if (isForwardEvents() && mpParserState->isInCharacterGroup())
+ {
+ mpStream->endCharacterGroup();
+ mpParserState->setInCharacterGroup(false);
+ }
+}
+
+void OOXMLFastContextHandler::pushBiDiEmbedLevel() {}
+
+void OOXMLFastContextHandler::popBiDiEmbedLevel() {}
+
+void OOXMLFastContextHandler::startParagraphGroup()
+{
+ if (!isForwardEvents())
+ return;
+
+ if (mpParserState->isInParagraphGroup())
+ endParagraphGroup();
+
+ if (! mpParserState->isInSectionGroup())
+ startSectionGroup();
+
+ if ( mpParserState->isInParagraphGroup())
+ return;
+
+ mpStream->startParagraphGroup();
+ mpParserState->setInParagraphGroup(true);
+
+ if (const auto& pPropSet = getPropertySet())
+ {
+ OOXMLPropertySetEntryToString aHandler(NS_ooxml::LN_AG_Parids_paraId);
+ pPropSet->resolve(aHandler);
+ if (const OUString& sText = aHandler.getString(); !sText.isEmpty())
+ {
+ OOXMLStringValue::Pointer_t pVal = new OOXMLStringValue(sText);
+ OOXMLPropertySet::Pointer_t pPropertySet(new OOXMLPropertySet);
+ pPropertySet->add(NS_ooxml::LN_AG_Parids_paraId, pVal, OOXMLProperty::ATTRIBUTE);
+ mpStream->props(pPropertySet.get());
+ }
+ }
+}
+
+void OOXMLFastContextHandler::endParagraphGroup()
+{
+ if (isForwardEvents())
+ {
+ if (mpParserState->isInCharacterGroup())
+ endCharacterGroup();
+
+ if (mpParserState->isInParagraphGroup())
+ {
+ mpStream->endParagraphGroup();
+ mpParserState->setInParagraphGroup(false);
+ }
+ }
+}
+
+void OOXMLFastContextHandler::startSdt()
+{
+ OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
+ pProps->add(NS_ooxml::LN_CT_SdtBlock_sdtContent, pVal, OOXMLProperty::ATTRIBUTE);
+ mpStream->props(pProps.get());
+}
+
+void OOXMLFastContextHandler::endSdt()
+{
+ OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
+ pProps->add(NS_ooxml::LN_CT_SdtBlock_sdtEndContent, pVal, OOXMLProperty::ATTRIBUTE);
+ mpStream->props(pProps.get());
+}
+
+void OOXMLFastContextHandler::startSdtRun()
+{
+ OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
+ pProps->add(NS_ooxml::LN_CT_SdtRun_sdtContent, pVal, OOXMLProperty::ATTRIBUTE);
+ mpStream->props(pProps.get());
+}
+
+void OOXMLFastContextHandler::endSdtRun()
+{
+ OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
+ pProps->add(NS_ooxml::LN_CT_SdtRun_sdtEndContent, pVal, OOXMLProperty::ATTRIBUTE);
+ mpStream->props(pProps.get());
+}
+
+void OOXMLFastContextHandler::startSectionGroup()
+{
+ if (isForwardEvents())
+ {
+ if (mpParserState->isInSectionGroup())
+ endSectionGroup();
+
+ if (! mpParserState->isInSectionGroup())
+ {
+ mpStream->info(mpParserState->getHandle());
+ mpStream->startSectionGroup();
+ mpParserState->setInSectionGroup(true);
+ }
+ }
+}
+
+void OOXMLFastContextHandler::endSectionGroup()
+{
+ if (isForwardEvents())
+ {
+ if (mpParserState->isInParagraphGroup())
+ endParagraphGroup();
+
+ if (mpParserState->isInSectionGroup())
+ {
+ mpStream->endSectionGroup();
+ mpParserState->setInSectionGroup(false);
+ }
+ }
+}
+
+void OOXMLFastContextHandler::setLastParagraphInSection()
+{
+ mpParserState->setLastParagraphInSection(true);
+ mpStream->markLastParagraphInSection( );
+}
+
+void OOXMLFastContextHandler::setLastSectionGroup()
+{
+ mpStream->markLastSectionGroup( );
+}
+
+void OOXMLFastContextHandler::newProperty
+(Id /*nId*/, const OOXMLValue::Pointer_t& /*pVal*/)
+{
+}
+
+void OOXMLFastContextHandler::setPropertySet
+(const OOXMLPropertySet::Pointer_t& /* pPropertySet */)
+{
+}
+
+OOXMLPropertySet::Pointer_t OOXMLFastContextHandler::getPropertySet() const
+{
+ return OOXMLPropertySet::Pointer_t();
+}
+
+void OOXMLFastContextHandler::startField()
+{
+ startCharacterGroup();
+ if (isForwardEvents())
+ mpStream->text(&cFieldStart, 1);
+ endCharacterGroup();
+}
+
+void OOXMLFastContextHandler::fieldSeparator()
+{
+ startCharacterGroup();
+ if (isForwardEvents())
+ mpStream->text(&cFieldSep, 1);
+ endCharacterGroup();
+}
+
+void OOXMLFastContextHandler::endField()
+{
+ startCharacterGroup();
+ if (isForwardEvents())
+ mpStream->text(&cFieldEnd, 1);
+ endCharacterGroup();
+}
+
+void OOXMLFastContextHandler::lockField()
+{
+ startCharacterGroup();
+ if (isForwardEvents())
+ mpStream->text(&cFieldLock, 1);
+ endCharacterGroup();
+}
+
+void OOXMLFastContextHandler::ftnednref()
+{
+ if (isForwardEvents())
+ mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uFtnEdnRef), 1);
+}
+
+void OOXMLFastContextHandler::ftnednsep()
+{
+ if (isForwardEvents())
+ mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uFtnEdnSep), 1);
+}
+
+void OOXMLFastContextHandler::ftnedncont()
+{
+ if (isForwardEvents())
+ mpStream->text(&cFtnEdnCont, 1);
+}
+
+void OOXMLFastContextHandler::pgNum()
+{
+ if (isForwardEvents())
+ mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uPgNum), 1);
+}
+
+void OOXMLFastContextHandler::tab()
+{
+ if (isForwardEvents())
+ mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uTab), 1);
+}
+
+void OOXMLFastContextHandler::symbol()
+{
+ if (isForwardEvents())
+ sendPropertiesWithId(NS_ooxml::LN_EG_RunInnerContent_sym);
+}
+
+void OOXMLFastContextHandler::cr()
+{
+ if (isForwardEvents())
+ mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uCR), 1);
+}
+
+void OOXMLFastContextHandler::noBreakHyphen()
+{
+ if (isForwardEvents())
+ mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uNoBreakHyphen), 1);
+}
+
+void OOXMLFastContextHandler::softHyphen()
+{
+ if (isForwardEvents())
+ mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uSoftHyphen), 1);
+}
+
+void OOXMLFastContextHandler::handleLastParagraphInSection()
+{
+ if (mpParserState->isLastParagraphInSection())
+ {
+ mpParserState->setLastParagraphInSection(false);
+ startSectionGroup();
+ }
+}
+
+void OOXMLFastContextHandler::endOfParagraph()
+{
+ if (! mpParserState->isInCharacterGroup())
+ startCharacterGroup();
+ if (isForwardEvents())
+ mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uCR), 1);
+
+ mpParserState->getDocument()->incrementProgress();
+}
+
+void OOXMLFastContextHandler::startTxbxContent()
+{
+/*
+ This usually means there are recursive <w:p> elements, and the ones
+ inside and outside of w:txbxContent should not interfere (e.g.
+ the lastParagraphInSection setting). So save the whole state
+ and possibly start new groups for the nested content (not section
+ group though, as that'd cause the txbxContent to be moved onto
+ another page, I'm not sure how that should work exactly).
+*/
+ mpParserState->startTxbxContent();
+ startParagraphGroup();
+}
+
+void OOXMLFastContextHandler::endTxbxContent()
+{
+ endParagraphGroup();
+ mpParserState->endTxbxContent();
+}
+
+namespace {
+// XML schema defines white space as one of four characters:
+// #x9 (tab), #xA (line feed), #xD (carriage return), and #x20 (space)
+bool IsXMLWhitespace(sal_Unicode cChar)
+{
+ return cChar == 0x9 || cChar == 0xA || cChar == 0xD || cChar == 0x20;
+}
+
+OUString TrimXMLWhitespace(const OUString & sText)
+{
+ sal_Int32 nTrimmedStart = 0;
+ const sal_Int32 nLen = sText.getLength();
+ sal_Int32 nTrimmedEnd = nLen - 1;
+ while (nTrimmedStart < nLen && IsXMLWhitespace(sText[nTrimmedStart]))
+ ++nTrimmedStart;
+ while (nTrimmedStart <= nTrimmedEnd && IsXMLWhitespace(sText[nTrimmedEnd]))
+ --nTrimmedEnd;
+ if ((nTrimmedStart == 0) && (nTrimmedEnd == nLen - 1))
+ return sText;
+ else if (nTrimmedStart > nTrimmedEnd)
+ return OUString();
+ else
+ return sText.copy(nTrimmedStart, nTrimmedEnd-nTrimmedStart+1);
+}
+}
+
+void OOXMLFastContextHandler::text(const OUString & sText)
+{
+ if (!isForwardEvents())
+ return;
+
+ // tdf#108806: CRLFs in XML were converted to \n before this point.
+ // These must be converted to spaces before further processing.
+ OUString sNormalizedText = sText.replaceAll("\n", " ");
+ // tdf#108995: by default, leading and trailing white space is ignored;
+ // tabs are converted to spaces
+ if (!IsPreserveSpace())
+ {
+ sNormalizedText = TrimXMLWhitespace(sNormalizedText).replaceAll("\t", " ");
+ }
+ mpStream->utext(reinterpret_cast < const sal_uInt8 * >
+ (sNormalizedText.getStr()),
+ sNormalizedText.getLength());
+}
+
+void OOXMLFastContextHandler::positionOffset(const OUString& rText)
+{
+ if (isForwardEvents())
+ mpStream->positionOffset(rText, inPositionV);
+}
+
+void OOXMLFastContextHandler::ignore()
+{
+}
+
+void OOXMLFastContextHandler::alignH(const OUString& rText)
+{
+ if (isForwardEvents())
+ mpStream->align(rText, /*bVertical=*/false);
+}
+
+void OOXMLFastContextHandler::alignV(const OUString& rText)
+{
+ if (isForwardEvents())
+ mpStream->align(rText, /*bVertical=*/true);
+}
+
+void OOXMLFastContextHandler::positivePercentage(const OUString& rText)
+{
+ if (isForwardEvents())
+ mpStream->positivePercentage(rText);
+}
+
+void OOXMLFastContextHandler::startGlossaryEntry()
+{
+ if (isForwardEvents())
+ mpStream->startGlossaryEntry();
+}
+
+void OOXMLFastContextHandler::endGlossaryEntry()
+{
+ if (isForwardEvents())
+ mpStream->endGlossaryEntry();
+}
+
+void OOXMLFastContextHandler::propagateCharacterProperties()
+{
+ mpParserState->setCharacterProperties(getPropertySet());
+}
+
+void OOXMLFastContextHandler::propagateCellProperties()
+{
+ mpParserState->setCellProperties(getPropertySet());
+}
+
+void OOXMLFastContextHandler::propagateRowProperties()
+{
+ mpParserState->setRowProperties(getPropertySet());
+}
+
+void OOXMLFastContextHandler::propagateTableProperties()
+{
+ OOXMLPropertySet::Pointer_t pProps = getPropertySet();
+
+ mpParserState->setTableProperties(pProps);
+}
+
+void OOXMLFastContextHandler::sendCellProperties()
+{
+ mpParserState->resolveCellProperties(*mpStream);
+}
+
+void OOXMLFastContextHandler::sendRowProperties()
+{
+ mpParserState->resolveRowProperties(*mpStream);
+}
+
+void OOXMLFastContextHandler::sendTableProperties()
+{
+ mpParserState->resolveTableProperties(*mpStream);
+}
+
+void OOXMLFastContextHandler::clearTableProps()
+{
+ mpParserState->setTableProperties(new OOXMLPropertySet());
+}
+
+void OOXMLFastContextHandler::sendPropertiesWithId(Id nId)
+{
+ OOXMLValue::Pointer_t pValue(new OOXMLPropertySetValue(getPropertySet()));
+ OOXMLPropertySet::Pointer_t pPropertySet(new OOXMLPropertySet);
+
+ pPropertySet->add(nId, pValue, OOXMLProperty::SPRM);
+ mpStream->props(pPropertySet.get());
+}
+
+void OOXMLFastContextHandler::clearProps()
+{
+ setPropertySet(new OOXMLPropertySet());
+}
+
+void OOXMLFastContextHandler::setDefaultBooleanValue()
+{
+}
+
+void OOXMLFastContextHandler::setDefaultIntegerValue()
+{
+}
+
+void OOXMLFastContextHandler::setDefaultHexValue()
+{
+}
+
+void OOXMLFastContextHandler::setDefaultStringValue()
+{
+}
+
+void OOXMLFastContextHandler::setDocument(OOXMLDocumentImpl* pDocument)
+{
+ mpParserState->setDocument(pDocument);
+}
+
+OOXMLDocumentImpl* OOXMLFastContextHandler::getDocument()
+{
+ return mpParserState->getDocument();
+}
+
+void OOXMLFastContextHandler::setForwardEvents(bool bForwardEvents)
+{
+ mpParserState->setForwardEvents(bForwardEvents);
+}
+
+bool OOXMLFastContextHandler::isForwardEvents() const
+{
+ return mpParserState->isForwardEvents();
+}
+
+void OOXMLFastContextHandler::setXNoteId(const sal_Int32 nId)
+{
+ mpParserState->setXNoteId(nId);
+}
+
+void OOXMLFastContextHandler::setXNoteId(const OOXMLValue::Pointer_t& pValue)
+{
+ mpParserState->setXNoteId(sal_Int32(pValue->getInt()));
+}
+
+sal_Int32 OOXMLFastContextHandler::getXNoteId() const
+{
+ return mpParserState->getXNoteId();
+}
+
+void OOXMLFastContextHandler::resolveFootnote
+(const sal_Int32 nId)
+{
+ mpParserState->getDocument()->resolveFootnote
+ (*mpStream, 0, nId);
+}
+
+void OOXMLFastContextHandler::resolveEndnote(const sal_Int32 nId)
+{
+ mpParserState->getDocument()->resolveEndnote
+ (*mpStream, 0, nId);
+}
+
+void OOXMLFastContextHandler::resolveComment(const sal_Int32 nId)
+{
+ mpParserState->getDocument()->resolveComment(*mpStream, nId);
+}
+
+void OOXMLFastContextHandler::resolvePicture(const OUString & rId)
+{
+ mpParserState->getDocument()->resolvePicture(*mpStream, rId);
+}
+
+void OOXMLFastContextHandler::resolveHeader
+(const sal_Int32 type, const OUString & rId)
+{
+ mpParserState->getDocument()->resolveHeader(*mpStream, type, rId);
+}
+
+void OOXMLFastContextHandler::resolveFooter
+(const sal_Int32 type, const OUString & rId)
+{
+ mpParserState->getDocument()->resolveFooter(*mpStream, type, rId);
+}
+
+// Add the data pointed to by the reference as another property.
+void OOXMLFastContextHandler::resolveData(const OUString & rId)
+{
+ OOXMLDocument * objDocument = getDocument();
+ SAL_WARN_IF(!objDocument, "writerfilter", "no document to resolveData");
+ if (!objDocument)
+ return;
+
+ uno::Reference<io::XInputStream> xInputStream
+ (objDocument->getInputStreamForId(rId));
+
+ OOXMLValue::Pointer_t aValue(new OOXMLInputStreamValue(xInputStream));
+
+ newProperty(NS_ooxml::LN_inputstream, aValue);
+}
+
+OUString OOXMLFastContextHandler::getTargetForId
+(const OUString & rId)
+{
+ return mpParserState->getDocument()->getTargetForId(rId);
+}
+
+void OOXMLFastContextHandler::sendPropertyToParent()
+{
+ if (mpParent != nullptr)
+ {
+ OOXMLPropertySet::Pointer_t pProps(mpParent->getPropertySet());
+
+ if (pProps)
+ {
+ pProps->add(mId, getValue(), OOXMLProperty::SPRM);
+ }
+ }
+}
+
+void OOXMLFastContextHandler::sendPropertiesToParent()
+{
+ if (mpParent == nullptr)
+ return;
+
+ OOXMLPropertySet::Pointer_t pParentProps(mpParent->getPropertySet());
+
+ if (!pParentProps)
+ return;
+
+ OOXMLPropertySet::Pointer_t pProps(getPropertySet());
+
+ if (pProps)
+ {
+ OOXMLValue::Pointer_t pValue
+ (new OOXMLPropertySetValue(getPropertySet()));
+
+ pParentProps->add(getId(), pValue, OOXMLProperty::SPRM);
+
+ }
+}
+
+bool OOXMLFastContextHandler::IsPreserveSpace() const
+{
+ // xml:space attribute applies to all elements within the content of the element where it is specified,
+ // unless overridden with another instance of the xml:space attribute
+ if (mbPreserveSpaceSet)
+ return mbPreserveSpace;
+ if (mpParent)
+ return mpParent->IsPreserveSpace();
+ return false; // default value
+}
+
+/*
+ class OOXMLFastContextHandlerStream
+ */
+
+OOXMLFastContextHandlerStream::OOXMLFastContextHandlerStream
+(OOXMLFastContextHandler * pContext)
+: OOXMLFastContextHandler(pContext),
+ mpPropertySetAttrs(new OOXMLPropertySet)
+{
+}
+
+OOXMLFastContextHandlerStream::~OOXMLFastContextHandlerStream()
+{
+}
+
+void OOXMLFastContextHandlerStream::newProperty(Id nId,
+ const OOXMLValue::Pointer_t& pVal)
+{
+ if (nId != 0x0)
+ {
+ mpPropertySetAttrs->add(nId, pVal, OOXMLProperty::ATTRIBUTE);
+ }
+}
+
+void OOXMLFastContextHandlerStream::sendProperty(Id nId)
+{
+ OOXMLPropertySetEntryToString aHandler(nId);
+ getPropertySetAttrs()->resolve(aHandler);
+ const OUString & sText = aHandler.getString();
+ mpStream->utext(reinterpret_cast < const sal_uInt8 * >
+ (sText.getStr()),
+ sText.getLength());
+}
+
+
+OOXMLPropertySet::Pointer_t OOXMLFastContextHandlerStream::getPropertySet()
+ const
+{
+ return getPropertySetAttrs();
+}
+
+void OOXMLFastContextHandlerStream::handleHyperlink()
+{
+ OOXMLHyperlinkHandler aHyperlinkHandler(this);
+ getPropertySetAttrs()->resolve(aHyperlinkHandler);
+ aHyperlinkHandler.writetext();
+}
+
+/*
+ class OOXMLFastContextHandlerProperties
+ */
+OOXMLFastContextHandlerProperties::OOXMLFastContextHandlerProperties
+(OOXMLFastContextHandler * pContext)
+: OOXMLFastContextHandler(pContext), mpPropertySet(new OOXMLPropertySet),
+ mbResolve(false)
+{
+ if (pContext->getResource() == STREAM)
+ mbResolve = true;
+}
+
+OOXMLFastContextHandlerProperties::~OOXMLFastContextHandlerProperties()
+{
+}
+
+void OOXMLFastContextHandlerProperties::lcl_endFastElement
+(Token_t /*Element*/)
+{
+ try
+ {
+ endAction();
+
+ if (mbResolve)
+ {
+ if (isForwardEvents())
+ {
+ mpStream->props(mpPropertySet.get());
+ }
+ }
+ else
+ {
+ sendPropertiesToParent();
+ }
+ }
+ catch (const uno::RuntimeException&)
+ {
+ throw;
+ }
+ catch (const xml::sax::SAXException&)
+ {
+ throw;
+ }
+ catch (const uno::Exception& e)
+ {
+ auto a = cppu::getCaughtException();
+ throw lang::WrappedTargetRuntimeException(e.Message, e.Context, a);
+ }
+}
+
+OOXMLValue::Pointer_t OOXMLFastContextHandlerProperties::getValue() const
+{
+ return OOXMLValue::Pointer_t(new OOXMLPropertySetValue(mpPropertySet));
+}
+
+void OOXMLFastContextHandlerProperties::newProperty
+(Id nId, const OOXMLValue::Pointer_t& pVal)
+{
+ if (nId != 0x0)
+ {
+ mpPropertySet->add(nId, pVal, OOXMLProperty::ATTRIBUTE);
+ }
+}
+
+void OOXMLFastContextHandlerProperties::handleXNotes()
+{
+ switch (mnToken)
+ {
+ case W_TOKEN(footnoteReference):
+ {
+ OOXMLFootnoteHandler aFootnoteHandler(this);
+ mpPropertySet->resolve(aFootnoteHandler);
+ }
+ break;
+ case W_TOKEN(endnoteReference):
+ {
+ OOXMLEndnoteHandler aEndnoteHandler(this);
+ mpPropertySet->resolve(aEndnoteHandler);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void OOXMLFastContextHandlerProperties::handleHdrFtr()
+{
+ switch (mnToken)
+ {
+ case W_TOKEN(footerReference):
+ {
+ OOXMLFooterHandler aFooterHandler(this);
+ mpPropertySet->resolve(aFooterHandler);
+ aFooterHandler.finalize();
+ }
+ break;
+ case W_TOKEN(headerReference):
+ {
+ OOXMLHeaderHandler aHeaderHandler(this);
+ mpPropertySet->resolve(aHeaderHandler);
+ aHeaderHandler.finalize();
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void OOXMLFastContextHandlerProperties::handleComment()
+{
+ OOXMLCommentHandler aCommentHandler(this);
+ getPropertySet()->resolve(aCommentHandler);
+}
+
+void OOXMLFastContextHandlerProperties::handlePicture()
+{
+ OOXMLPictureHandler aPictureHandler(this);
+ getPropertySet()->resolve(aPictureHandler);
+}
+
+void OOXMLFastContextHandlerProperties::handleBreak()
+{
+ if(isForwardEvents())
+ {
+ OOXMLBreakHandler aBreakHandler(this, *mpStream);
+ getPropertySet()->resolve(aBreakHandler);
+ }
+}
+
+// tdf#108714 : allow <w:br> at block level (despite this is illegal according to ECMA-376-1:2016)
+void OOXMLFastContextHandlerProperties::handleOutOfOrderBreak()
+{
+ if(isForwardEvents())
+ {
+ mpParserState->setPostponedBreak(getPropertySet());
+ }
+}
+
+void OOXMLFastContextHandlerProperties::handleOLE()
+{
+ OOXMLOLEHandler aOLEHandler(this);
+ getPropertySet()->resolve(aOLEHandler);
+}
+
+void OOXMLFastContextHandlerProperties::handleFontRel()
+{
+ OOXMLEmbeddedFontHandler handler(this);
+ getPropertySet()->resolve(handler);
+}
+
+void OOXMLFastContextHandlerProperties::handleHyperlinkURL() {
+ OOXMLHyperlinkURLHandler aHyperlinkURLHandler(this);
+ getPropertySet()->resolve(aHyperlinkURLHandler);
+}
+
+void OOXMLFastContextHandlerProperties::handleAltChunk()
+{
+ OOXMLAltChunkHandler aHandler(this);
+ getPropertySet()->resolve(aHandler);
+}
+
+void OOXMLFastContextHandlerProperties::setPropertySet
+(const OOXMLPropertySet::Pointer_t& pPropertySet)
+{
+ if (pPropertySet)
+ mpPropertySet = pPropertySet;
+}
+
+OOXMLPropertySet::Pointer_t
+OOXMLFastContextHandlerProperties::getPropertySet() const
+{
+ return mpPropertySet;
+}
+
+/*
+ * class OOXMLFasContextHandlerPropertyTable
+ */
+
+OOXMLFastContextHandlerPropertyTable::OOXMLFastContextHandlerPropertyTable
+(OOXMLFastContextHandler * pContext)
+: OOXMLFastContextHandlerProperties(pContext)
+{
+}
+
+OOXMLFastContextHandlerPropertyTable::~OOXMLFastContextHandlerPropertyTable()
+{
+}
+
+void OOXMLFastContextHandlerPropertyTable::lcl_endFastElement
+(Token_t /*Element*/)
+{
+ OOXMLPropertySet::Pointer_t pPropSet(mpPropertySet->clone());
+ OOXMLTable::ValuePointer_t pTmpVal
+ (new OOXMLPropertySetValue(pPropSet));
+
+ mTable.add(pTmpVal);
+
+ writerfilter::Reference<Table>::Pointer_t pTable(mTable.clone());
+
+ mpStream->table(mId, pTable);
+
+ endAction();
+}
+
+/*
+ class OOXMLFastContextHandlerValue
+*/
+
+OOXMLFastContextHandlerValue::OOXMLFastContextHandlerValue
+(OOXMLFastContextHandler * pContext)
+: OOXMLFastContextHandler(pContext)
+{
+}
+
+OOXMLFastContextHandlerValue::~OOXMLFastContextHandlerValue()
+{
+}
+
+void OOXMLFastContextHandlerValue::setValue(const OOXMLValue::Pointer_t& pValue)
+{
+ mpValue = pValue;
+}
+
+OOXMLValue::Pointer_t OOXMLFastContextHandlerValue::getValue() const
+{
+ return mpValue;
+}
+
+void OOXMLFastContextHandlerValue::lcl_endFastElement
+(Token_t /*Element*/)
+{
+ sendPropertyToParent();
+
+ endAction();
+}
+
+void OOXMLFastContextHandlerValue::setDefaultBooleanValue()
+{
+ if (!mpValue)
+ {
+ OOXMLValue::Pointer_t pValue = OOXMLBooleanValue::Create(true);
+ setValue(pValue);
+ }
+}
+
+void OOXMLFastContextHandlerValue::setDefaultIntegerValue()
+{
+ if (!mpValue)
+ {
+ OOXMLValue::Pointer_t pValue = OOXMLIntegerValue::Create(0);
+ setValue(pValue);
+ }
+}
+
+void OOXMLFastContextHandlerValue::setDefaultHexValue()
+{
+ if (!mpValue)
+ {
+ OOXMLValue::Pointer_t pValue(new OOXMLHexValue(sal_uInt32(0)));
+ setValue(pValue);
+ }
+}
+
+void OOXMLFastContextHandlerValue::setDefaultStringValue()
+{
+ if (!mpValue)
+ {
+ OOXMLValue::Pointer_t pValue(new OOXMLStringValue(OUString()));
+ setValue(pValue);
+ }
+}
+
+// ECMA-376-1:2016 17.3.2.8; https://www.unicode.org/reports/tr9/#Explicit_Directional_Embeddings
+void OOXMLFastContextHandlerValue::pushBiDiEmbedLevel()
+{
+ const bool bRtl
+ = mpValue && mpValue->getInt() == NS_ooxml::LN_Value_ST_Direction_rtl;
+ OOXMLFactory::characters(this, bRtl ? OUString(u"\u202B") : OUString(u"\u202A")); // RLE / LRE
+}
+
+void OOXMLFastContextHandlerValue::popBiDiEmbedLevel()
+{
+ OOXMLFactory::characters(this, u"\u202C"); // PDF (POP DIRECTIONAL FORMATTING)
+}
+
+void OOXMLFastContextHandlerValue::handleGridAfter()
+{
+ if (!getValue())
+ return;
+
+ if (OOXMLFastContextHandler* pTableRowProperties = getParent())
+ {
+ if (OOXMLFastContextHandler* pTableRow = pTableRowProperties->getParent())
+ // Save the value into the table row context, so it can be handled
+ // right before the end of the row.
+ pTableRow->setGridAfter(getValue());
+ }
+}
+
+/*
+ class OOXMLFastContextHandlerTable
+*/
+
+OOXMLFastContextHandlerTable::OOXMLFastContextHandlerTable
+(OOXMLFastContextHandler * pContext)
+: OOXMLFastContextHandler(pContext)
+{
+}
+
+OOXMLFastContextHandlerTable::~OOXMLFastContextHandlerTable()
+{
+}
+
+uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
+OOXMLFastContextHandlerTable::createFastChildContext
+(sal_Int32 Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ addCurrentChild();
+
+ mCurrentChild.set(OOXMLFastContextHandler::createFastChildContext(Element, Attribs));
+
+ return mCurrentChild;
+}
+
+void OOXMLFastContextHandlerTable::lcl_endFastElement
+(Token_t /*Element*/)
+{
+ addCurrentChild();
+
+ writerfilter::Reference<Table>::Pointer_t pTable(mTable.clone());
+ if (isForwardEvents() && mId != 0x0)
+ {
+ mpStream->table(mId, pTable);
+ }
+}
+
+void OOXMLFastContextHandlerTable::addCurrentChild()
+{
+ OOXMLFastContextHandler * pHandler = dynamic_cast<OOXMLFastContextHandler*>(mCurrentChild.get());
+ if (pHandler != nullptr)
+ {
+ OOXMLValue::Pointer_t pValue(pHandler->getValue());
+
+ if (pValue)
+ {
+ OOXMLTable::ValuePointer_t pTmpVal(pValue->clone());
+ mTable.add(pTmpVal);
+ }
+ }
+}
+
+/*
+ class OOXMLFastContextHandlerXNote
+ */
+
+OOXMLFastContextHandlerXNote::OOXMLFastContextHandlerXNote
+ (OOXMLFastContextHandler * pContext)
+ : OOXMLFastContextHandlerProperties(pContext)
+ , mbForwardEventsSaved(false)
+ , mnMyXNoteId(0)
+ , mnMyXNoteType(0)
+{
+}
+
+OOXMLFastContextHandlerXNote::~OOXMLFastContextHandlerXNote()
+{
+}
+
+void OOXMLFastContextHandlerXNote::lcl_startFastElement
+(Token_t /*Element*/,
+ const uno::Reference< xml::sax::XFastAttributeList > & /*Attribs*/)
+{
+ mbForwardEventsSaved = isForwardEvents();
+
+ // If this is the note we're looking for or this is the footnote separator one.
+ if (mnMyXNoteId == getXNoteId() ||
+ static_cast<sal_uInt32>(mnMyXNoteType) == NS_ooxml::LN_Value_doc_ST_FtnEdn_separator ||
+ mpParserState->isStartFootnote())
+ setForwardEvents(true);
+ else
+ setForwardEvents(false);
+
+ startAction();
+}
+
+void OOXMLFastContextHandlerXNote::lcl_endFastElement
+(Token_t Element)
+{
+ endAction();
+
+ OOXMLFastContextHandlerProperties::lcl_endFastElement(Element);
+
+ setForwardEvents(mbForwardEventsSaved);
+}
+
+void OOXMLFastContextHandlerXNote::checkId(const OOXMLValue::Pointer_t& pValue)
+{
+ mnMyXNoteId = sal_Int32(pValue->getInt());
+ mpStream->checkId(mnMyXNoteId);
+}
+
+void OOXMLFastContextHandlerXNote::checkType(const OOXMLValue::Pointer_t& pValue)
+{
+ mnMyXNoteType = pValue->getInt();
+}
+
+/*
+ class OOXMLFastContextHandlerTextTableCell
+ */
+
+OOXMLFastContextHandlerTextTableCell::OOXMLFastContextHandlerTextTableCell
+(OOXMLFastContextHandler * pContext)
+: OOXMLFastContextHandler(pContext)
+{
+}
+
+OOXMLFastContextHandlerTextTableCell::~OOXMLFastContextHandlerTextTableCell()
+{
+}
+
+void OOXMLFastContextHandlerTextTableCell::startCell()
+{
+ if (isForwardEvents())
+ {
+ OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLBooleanValue::Create(mnTableDepth > 0);
+ pProps->add(NS_ooxml::LN_tcStart, pVal, OOXMLProperty::SPRM);
+ }
+
+ mpStream->props(pProps.get());
+ }
+}
+
+void OOXMLFastContextHandlerTextTableCell::endCell()
+{
+ if (!isForwardEvents())
+ return;
+
+ OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(mnTableDepth);
+ pProps->add(NS_ooxml::LN_tblDepth, pVal, OOXMLProperty::SPRM);
+ }
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
+ pProps->add(NS_ooxml::LN_inTbl, pVal, OOXMLProperty::SPRM);
+ }
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLBooleanValue::Create(mnTableDepth > 0);
+ pProps->add(NS_ooxml::LN_tblCell, pVal, OOXMLProperty::SPRM);
+ }
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLBooleanValue::Create(mnTableDepth > 0);
+ pProps->add(NS_ooxml::LN_tcEnd, pVal, OOXMLProperty::SPRM);
+ }
+
+ mpStream->props(pProps.get());
+}
+
+/*
+ class OOXMLFastContextHandlerTextTableRow
+ */
+
+OOXMLFastContextHandlerTextTableRow::OOXMLFastContextHandlerTextTableRow
+(OOXMLFastContextHandler * pContext)
+: OOXMLFastContextHandler(pContext)
+{
+}
+
+OOXMLFastContextHandlerTextTableRow::~OOXMLFastContextHandlerTextTableRow()
+{
+}
+
+void OOXMLFastContextHandlerTextTableRow::startRow()
+{
+}
+
+void OOXMLFastContextHandlerTextTableRow::endRow()
+{
+ if (mpGridAfter)
+ {
+ // Grid after is the same as grid before, the empty cells are just
+ // inserted after the real ones, not before.
+ handleGridBefore(mpGridAfter);
+ mpGridAfter = nullptr;
+ }
+
+ startParagraphGroup();
+
+ if (isForwardEvents())
+ {
+ OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(mnTableDepth);
+ pProps->add(NS_ooxml::LN_tblDepth, pVal, OOXMLProperty::SPRM);
+ }
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
+ pProps->add(NS_ooxml::LN_inTbl, pVal, OOXMLProperty::SPRM);
+ }
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
+ pProps->add(NS_ooxml::LN_tblRow, pVal, OOXMLProperty::SPRM);
+ }
+
+ mpStream->props(pProps.get());
+ }
+
+ startCharacterGroup();
+
+ if (isForwardEvents())
+ mpStream->utext(reinterpret_cast<const sal_uInt8*>(&uCR), 1);
+
+ endCharacterGroup();
+ endParagraphGroup();
+}
+
+namespace {
+OOXMLValue::Pointer_t fakeNoBorder()
+{
+ OOXMLPropertySet::Pointer_t pProps( new OOXMLPropertySet );
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(0);
+ pProps->add(NS_ooxml::LN_CT_Border_val, pVal, OOXMLProperty::ATTRIBUTE);
+ OOXMLValue::Pointer_t pValue( new OOXMLPropertySetValue( pProps ));
+ return pValue;
+}
+}
+
+// Handle w:gridBefore here by faking necessary input that'll fake cells. I'm apparently
+// not insane enough to find out how to add cells in dmapper.
+void OOXMLFastContextHandlerTextTableRow::handleGridBefore( const OOXMLValue::Pointer_t& val )
+{
+ // start removing: disable for w:gridBefore
+ if (!mpGridAfter)
+ return;
+
+ int count = val->getInt();
+ for( int i = 0;
+ i < count;
+ ++i )
+ {
+ endOfParagraph();
+
+ if (isForwardEvents())
+ {
+ // This whole part is OOXMLFastContextHandlerTextTableCell::endCell() .
+ OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(mnTableDepth);
+ pProps->add(NS_ooxml::LN_tblDepth, pVal, OOXMLProperty::SPRM);
+ }
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(1);
+ pProps->add(NS_ooxml::LN_inTbl, pVal, OOXMLProperty::SPRM);
+ }
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLBooleanValue::Create(mnTableDepth > 0);
+ pProps->add(NS_ooxml::LN_tblCell, pVal, OOXMLProperty::SPRM);
+ }
+
+ mpStream->props(pProps.get());
+
+ // fake <w:tcBorders> with no border
+ OOXMLPropertySet::Pointer_t pCellProps( new OOXMLPropertySet );
+ {
+ OOXMLPropertySet::Pointer_t pBorderProps( new OOXMLPropertySet );
+ static Id borders[] = { NS_ooxml::LN_CT_TcBorders_top, NS_ooxml::LN_CT_TcBorders_bottom,
+ NS_ooxml::LN_CT_TcBorders_start, NS_ooxml::LN_CT_TcBorders_end };
+ for(sal_uInt32 border : borders)
+ pBorderProps->add(border, fakeNoBorder(), OOXMLProperty::SPRM);
+ OOXMLValue::Pointer_t pValue( new OOXMLPropertySetValue( pBorderProps ));
+ pCellProps->add(NS_ooxml::LN_CT_TcPrBase_tcBorders, pValue, OOXMLProperty::SPRM);
+ mpParserState->setCellProperties(pCellProps);
+ }
+ }
+
+ sendCellProperties();
+ endParagraphGroup();
+ }
+}
+
+/*
+ class OOXMLFastContextHandlerTextTable
+ */
+
+OOXMLFastContextHandlerTextTable::OOXMLFastContextHandlerTextTable
+(OOXMLFastContextHandler * pContext)
+: OOXMLFastContextHandler(pContext)
+{
+}
+
+OOXMLFastContextHandlerTextTable::~OOXMLFastContextHandlerTextTable()
+{
+ clearTableProps();
+}
+
+void OOXMLFastContextHandlerTextTable::lcl_startFastElement
+(Token_t /*Element*/,
+ const uno::Reference< xml::sax::XFastAttributeList > & /*Attribs*/)
+{
+ mpParserState->startTable();
+ mnTableDepth++;
+
+ OOXMLPropertySet::Pointer_t pProps( new OOXMLPropertySet );
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(mnTableDepth);
+ pProps->add(NS_ooxml::LN_tblStart, pVal, OOXMLProperty::SPRM);
+ }
+ mpParserState->setCharacterProperties(pProps);
+
+ startAction();
+}
+
+void OOXMLFastContextHandlerTextTable::lcl_endFastElement
+(Token_t /*Element*/)
+{
+ endAction();
+
+ OOXMLPropertySet::Pointer_t pProps( new OOXMLPropertySet );
+ {
+ OOXMLValue::Pointer_t pVal = OOXMLIntegerValue::Create(mnTableDepth);
+ pProps->add(NS_ooxml::LN_tblEnd, pVal, OOXMLProperty::SPRM);
+ }
+ mpParserState->setCharacterProperties(pProps);
+
+ mnTableDepth--;
+ mpParserState->endTable();
+}
+
+// tdf#111550
+void OOXMLFastContextHandlerTextTable::start_P_Tbl()
+{
+ // Normally, when one paragraph ends, and another begins,
+ // in OOXMLFactory_wml::endAction handler for <w:p>,
+ // pHandler->endOfParagraph() is called, which (among other things)
+ // calls TableManager::setHandle() to update current cell's starting point.
+ // Then, in OOXMLFactory_wml::startAction for next <w:p>,
+ // pHandler->startParagraphGroup() is called, which ends previous group,
+ // and there, it pushes cells to row in TableManager::endParagraphGroup()
+ // (cells have correct bounds defined by mCurHandle).
+ // When a table is child of a <w:p>, that paragraph doesn't end before nested
+ // paragraph begins. So, pHandler->endOfParagraph() was not (and should not be)
+ // called. But as next paragraph starts, is the previous group is closed, then
+ // cells will have wrong boundings. Here, we know that we *are* in paragraph
+ // group, but it should not be finished.
+ mpParserState->setInParagraphGroup(false);
+}
+
+/*
+ class OOXMLFastContextHandlerShape
+ */
+
+OOXMLFastContextHandlerShape::OOXMLFastContextHandlerShape
+(OOXMLFastContextHandler * pContext)
+: OOXMLFastContextHandlerProperties(pContext), m_bShapeSent( false ),
+ m_bShapeStarted(false), m_bShapeContextPushed(false)
+{
+}
+
+OOXMLFastContextHandlerShape::~OOXMLFastContextHandlerShape()
+{
+ if (m_bShapeContextPushed)
+ getDocument()->popShapeContext();
+}
+
+void OOXMLFastContextHandlerShape::lcl_startFastElement
+(Token_t Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ startAction();
+
+ if (mrShapeContext.is())
+ {
+ mrShapeContext->startFastElement(Element, Attribs);
+ }
+}
+
+void SAL_CALL OOXMLFastContextHandlerShape::startUnknownElement
+(const OUString & Namespace,
+ const OUString & Name,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ if (mrShapeContext.is())
+ mrShapeContext->startUnknownElement(Namespace, Name, Attribs);
+}
+
+void OOXMLFastContextHandlerShape::setToken(Token_t nToken)
+{
+ if (nToken == Token_t(NMSP_wps | XML_wsp) || nToken == Token_t(NMSP_dmlPicture | XML_pic))
+ {
+ // drawingML shapes are independent, <wps:bodyPr> is not parsed after
+ // shape contents without pushing/popping the stack.
+ m_bShapeContextPushed = true;
+ getDocument()->pushShapeContext();
+ }
+
+ mrShapeContext = getDocument()->getShapeContext();
+ if (!mrShapeContext.is())
+ {
+ // Define the shape context for the whole document
+ mrShapeContext = new oox::shape::ShapeContextHandler(getDocument()->getShapeFilterBase());
+ getDocument()->setShapeContext(mrShapeContext);
+ auto pThemePtr = getDocument()->getTheme();
+ if (pThemePtr)
+ mrShapeContext->setTheme(pThemePtr);
+ }
+
+ mrShapeContext->setModel(getDocument()->getModel());
+ uno::Reference<document::XDocumentPropertiesSupplier> xDocSupplier(getDocument()->getModel(), uno::UNO_QUERY_THROW);
+ mrShapeContext->setDocumentProperties(xDocSupplier->getDocumentProperties());
+ mrShapeContext->setDrawPage(getDocument()->getDrawPage());
+ mrShapeContext->setMediaDescriptor(getDocument()->getMediaDescriptor());
+
+ mrShapeContext->setRelationFragmentPath(mpParserState->getTarget());
+
+ // Floating tables (table inside a textframe) have issues with fullWPG,
+ // so disable the fullWPGsupport in tables until that issue is not fixed.
+ mrShapeContext->setFullWPGSupport(!mnTableDepth);
+
+ auto xGraphicMapper = getDocument()->getGraphicMapper();
+
+ if (xGraphicMapper.is())
+ mrShapeContext->setGraphicMapper(xGraphicMapper);
+
+ OOXMLFastContextHandler::setToken(nToken);
+
+ if (mrShapeContext.is())
+ mrShapeContext->pushStartToken(nToken);
+}
+
+void OOXMLFastContextHandlerShape::sendShape( Token_t Element )
+{
+ if ( !mrShapeContext.is() || m_bShapeSent )
+ return;
+
+ awt::Point aPosition = mpStream->getPositionOffset();
+ mrShapeContext->setPosition(aPosition);
+ uno::Reference<drawing::XShape> xShape(mrShapeContext->getShape());
+ m_bShapeSent = true;
+ if (!xShape.is())
+ return;
+
+ OOXMLValue::Pointer_t
+ pValue(new OOXMLShapeValue(xShape));
+ newProperty(NS_ooxml::LN_shape, pValue);
+
+ bool bIsPicture = Element == ( NMSP_dmlPicture | XML_pic );
+
+ //tdf#87569: Fix table layout with correcting anchoring
+ //If anchored object is in table, Word calculates its position from cell border
+ //instead of page (what is set in the sample document)
+ uno::Reference<beans::XPropertySet> xShapePropSet(xShape, uno::UNO_QUERY);
+ if (mnTableDepth > 0 && xShapePropSet.is() && mbIsVMLfound) //if we had a table
+ {
+ xShapePropSet->setPropertyValue(dmapper::getPropertyName(dmapper::PROP_FOLLOW_TEXT_FLOW),
+ uno::Any(mbAllowInCell));
+ }
+ // Notify the dmapper that the shape is ready to use
+ if ( !bIsPicture )
+ {
+ mpStream->startShape( xShape );
+ m_bShapeStarted = true;
+ }
+}
+
+bool OOXMLFastContextHandlerShape::isDMLGroupShape() const
+{
+ return (mrShapeContext->getFullWPGSupport() && mrShapeContext->isWordProcessingGroupShape());
+};
+
+void OOXMLFastContextHandlerShape::lcl_endFastElement
+(Token_t Element)
+{
+ if (!isForwardEvents())
+ return;
+
+ if (mrShapeContext.is())
+ {
+ mrShapeContext->endFastElement(Element);
+ sendShape( Element );
+ }
+
+ OOXMLFastContextHandlerProperties::lcl_endFastElement(Element);
+
+ // Ending the shape should be the last thing to do
+ bool bIsPicture = Element == ( NMSP_dmlPicture | XML_pic );
+ if ( !bIsPicture && m_bShapeStarted)
+ mpStream->endShape( );
+}
+
+void SAL_CALL OOXMLFastContextHandlerShape::endUnknownElement
+(const OUString & Namespace,
+ const OUString & Name)
+{
+ if (mrShapeContext.is())
+ mrShapeContext->endUnknownElement(Namespace, Name);
+}
+
+uno::Reference< xml::sax::XFastContextHandler >
+OOXMLFastContextHandlerShape::lcl_createFastChildContext
+(Token_t Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ // we need to share a single theme across all the shapes, but we parse it
+ // in ShapeContextHandler. So if it has been parsed there, propagate it to
+ // the document.
+ if (mrShapeContext && mrShapeContext->getTheme() && !getDocument()->getTheme())
+ {
+ auto pThemePtr = mrShapeContext->getTheme();
+ getDocument()->setTheme(pThemePtr);
+ }
+
+ uno::Reference< xml::sax::XFastContextHandler > xContextHandler;
+
+ bool bGroupShape = Element == Token_t(NMSP_vml | XML_group);
+ // drawingML version also counts as a group shape.
+ if (!mrShapeContext->getFullWPGSupport())
+ bGroupShape |= mrShapeContext->getStartToken() == Token_t(NMSP_wpg | XML_wgp);
+ mbIsVMLfound = (getNamespace(Element) == NMSP_vmlOffice) || (getNamespace(Element) == NMSP_vml);
+ switch (oox::getNamespace(Element))
+ {
+ case NMSP_doc:
+ case NMSP_vmlWord:
+ case NMSP_vmlOffice:
+ if (!bGroupShape)
+ xContextHandler.set(OOXMLFactory::createFastChildContextFromStart(this, Element));
+ [[fallthrough]];
+ default:
+ if (!xContextHandler.is())
+ {
+ if (mrShapeContext.is())
+ {
+ uno::Reference<XFastContextHandler> pChildContext =
+ mrShapeContext->createFastChildContext(Element, Attribs);
+
+ rtl::Reference<OOXMLFastContextHandlerWrapper> pWrapper =
+ new OOXMLFastContextHandlerWrapper(this,
+ pChildContext,
+ this);
+
+ //tdf129888 store allowincell attribute of the VML shape
+ if (Attribs->hasAttribute(NMSP_vmlOffice | XML_allowincell))
+ mbAllowInCell
+ = !(Attribs->getValue(NMSP_vmlOffice | XML_allowincell) == "f");
+
+ if (!bGroupShape)
+ {
+ pWrapper->addNamespace(NMSP_doc);
+ pWrapper->addNamespace(NMSP_vmlWord);
+ pWrapper->addNamespace(NMSP_vmlOffice);
+ pWrapper->addToken( NMSP_vml|XML_textbox );
+ }
+ xContextHandler.set(pWrapper);
+ }
+ else
+ xContextHandler.set(this);
+ }
+ break;
+ }
+
+ // VML import of shape text is already handled by
+ // OOXMLFastContextHandlerWrapper::lcl_createFastChildContext(), here we
+ // handle the WPS import of shape text, as there the parent context is a
+ // Shape one, so a different situation.
+ if (Element == static_cast<sal_Int32>(NMSP_wps | XML_txbx) ||
+ Element == static_cast<sal_Int32>(NMSP_wps | XML_linkedTxbx) )
+ sendShape(Element);
+
+ return xContextHandler;
+}
+
+uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
+OOXMLFastContextHandlerShape::createUnknownChildContext
+(const OUString & Namespace,
+ const OUString & Name,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ uno::Reference< xml::sax::XFastContextHandler > xResult;
+
+ if (mrShapeContext.is())
+ xResult.set(mrShapeContext->createUnknownChildContext
+ (Namespace, Name, Attribs));
+
+ return xResult;
+}
+
+void OOXMLFastContextHandlerShape::lcl_characters
+(const OUString & aChars)
+{
+ if (mrShapeContext.is())
+ mrShapeContext->characters(aChars);
+}
+
+/*
+ class OOXMLFastContextHandlerWrapper
+*/
+
+OOXMLFastContextHandlerWrapper::OOXMLFastContextHandlerWrapper
+(OOXMLFastContextHandler * pParent,
+ uno::Reference<XFastContextHandler> const & xContext,
+ rtl::Reference<OOXMLFastContextHandlerShape> const & xShapeHandler)
+ : OOXMLFastContextHandler(pParent),
+ mxWrappedContext(xContext),
+ mxShapeHandler(xShapeHandler)
+{
+ setId(pParent->getId());
+ setToken(pParent->getToken());
+ setPropertySet(pParent->getPropertySet());
+}
+
+OOXMLFastContextHandlerWrapper::~OOXMLFastContextHandlerWrapper()
+{
+}
+
+void SAL_CALL OOXMLFastContextHandlerWrapper::startUnknownElement
+(const OUString & Namespace,
+ const OUString & Name,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ if (mxWrappedContext.is())
+ mxWrappedContext->startUnknownElement(Namespace, Name, Attribs);
+}
+
+void SAL_CALL OOXMLFastContextHandlerWrapper::endUnknownElement
+(const OUString & Namespace,
+ const OUString & Name)
+{
+ if (mxWrappedContext.is())
+ mxWrappedContext->endUnknownElement(Namespace, Name);
+}
+
+uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
+OOXMLFastContextHandlerWrapper::createUnknownChildContext
+(const OUString & Namespace,
+ const OUString & Name,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ uno::Reference< xml::sax::XFastContextHandler > xResult;
+
+ if (mxWrappedContext.is())
+ xResult = mxWrappedContext->createUnknownChildContext
+ (Namespace, Name, Attribs);
+ else
+ xResult.set(this);
+
+ return xResult;
+}
+
+void OOXMLFastContextHandlerWrapper::attributes
+(const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ if (mxWrappedContext.is())
+ {
+ OOXMLFastContextHandler * pHandler = getFastContextHandler();
+ if (pHandler != nullptr)
+ pHandler->attributes(Attribs);
+ }
+}
+
+OOXMLFastContextHandler::ResourceEnum_t
+OOXMLFastContextHandlerWrapper::getResource() const
+{
+ return UNKNOWN;
+}
+
+void OOXMLFastContextHandlerWrapper::addNamespace(Id nId)
+{
+ mMyNamespaces.insert(nId);
+}
+
+void OOXMLFastContextHandlerWrapper::addToken( Token_t Token )
+{
+ mMyTokens.insert( Token );
+}
+
+void OOXMLFastContextHandlerWrapper::lcl_startFastElement
+(Token_t Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ if (mxWrappedContext.is())
+ mxWrappedContext->startFastElement(Element, Attribs);
+
+ if (mxShapeHandler->isDMLGroupShape()
+ && (Element == Token_t(NMSP_wps | XML_txbx)
+ || Element == Token_t(NMSP_wps | XML_linkedTxbx)))
+ {
+ mpStream->startTextBoxContent();
+ }
+}
+
+void OOXMLFastContextHandlerWrapper::lcl_endFastElement
+(Token_t Element)
+{
+ if (mxWrappedContext.is())
+ mxWrappedContext->endFastElement(Element);
+
+ if (mxShapeHandler->isDMLGroupShape()
+ && (Element == Token_t(NMSP_wps | XML_txbx)
+ || Element == Token_t(NMSP_wps | XML_linkedTxbx)))
+ {
+ mpStream->endTextBoxContent();
+ }
+}
+
+uno::Reference< xml::sax::XFastContextHandler >
+OOXMLFastContextHandlerWrapper::lcl_createFastChildContext
+(Token_t Element,
+ const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
+{
+ uno::Reference< xml::sax::XFastContextHandler > xResult;
+
+ bool bInNamespaces = mMyNamespaces.find(oox::getNamespace(Element)) != mMyNamespaces.end();
+ bool bInTokens = mMyTokens.find( Element ) != mMyTokens.end( );
+
+ // We have methods to _add_ individual tokens or whole namespaces to be
+ // processed by writerfilter (instead of oox), but we have no method to
+ // filter out a single token. Just hardwire the 'wrap' and 'signatureline' tokens
+ // here until we need a more generic solution.
+ bool bIsWrap = Element == static_cast<sal_Int32>(NMSP_vmlWord | XML_wrap);
+ bool bIsSignatureLine = Element == static_cast<sal_Int32>(NMSP_vmlOffice | XML_signatureline);
+ bool bSkipImages = getDocument()->IsSkipImages() && oox::getNamespace(Element) == NMSP_dml &&
+ (oox::getBaseToken(Element) != XML_linkedTxbx) && (oox::getBaseToken(Element) != XML_txbx);
+
+ if ( bInNamespaces && ((!bIsWrap && !bIsSignatureLine)
+ || mxShapeHandler->isShapeSent()) )
+ {
+ xResult.set(OOXMLFactory::createFastChildContextFromStart(this, Element));
+ }
+ else if (mxWrappedContext.is() && !bSkipImages)
+ {
+ rtl::Reference<OOXMLFastContextHandlerWrapper> pWrapper =
+ new OOXMLFastContextHandlerWrapper
+ (this, mxWrappedContext->createFastChildContext(Element, Attribs),
+ mxShapeHandler);
+ pWrapper->mMyNamespaces = mMyNamespaces;
+ pWrapper->mMyTokens = mMyTokens;
+ pWrapper->setPropertySet(getPropertySet());
+ xResult.set(pWrapper);
+ }
+ else
+ {
+ xResult.set(this);
+ }
+
+ if ( bInTokens )
+ mxShapeHandler->sendShape( Element );
+
+ return xResult;
+}
+
+void OOXMLFastContextHandlerWrapper::lcl_characters
+(const OUString & aChars)
+{
+ if (mxWrappedContext.is())
+ mxWrappedContext->characters(aChars);
+}
+
+OOXMLFastContextHandler *
+OOXMLFastContextHandlerWrapper::getFastContextHandler() const
+{
+ if (mxWrappedContext.is())
+ return dynamic_cast<OOXMLFastContextHandler *>(mxWrappedContext.get());
+
+ return nullptr;
+}
+
+void OOXMLFastContextHandlerWrapper::newProperty
+(Id nId, const OOXMLValue::Pointer_t& pVal)
+{
+ if (mxWrappedContext.is())
+ {
+ OOXMLFastContextHandler * pHandler = getFastContextHandler();
+ if (pHandler != nullptr)
+ pHandler->newProperty(nId, pVal);
+ }
+}
+
+void OOXMLFastContextHandlerWrapper::setPropertySet
+(const OOXMLPropertySet::Pointer_t& pPropertySet)
+{
+ if (mxWrappedContext.is())
+ {
+ OOXMLFastContextHandler * pHandler = getFastContextHandler();
+ if (pHandler != nullptr)
+ pHandler->setPropertySet(pPropertySet);
+ }
+
+ mpPropertySet = pPropertySet;
+}
+
+OOXMLPropertySet::Pointer_t OOXMLFastContextHandlerWrapper::getPropertySet()
+ const
+{
+ OOXMLPropertySet::Pointer_t pResult(mpPropertySet);
+
+ if (mxWrappedContext.is())
+ {
+ OOXMLFastContextHandler * pHandler = getFastContextHandler();
+ if (pHandler != nullptr)
+ pResult = pHandler->getPropertySet();
+ }
+
+ return pResult;
+}
+
+string OOXMLFastContextHandlerWrapper::getType() const
+{
+ string sResult = "Wrapper(";
+
+ if (mxWrappedContext.is())
+ {
+ OOXMLFastContextHandler * pHandler = getFastContextHandler();
+ if (pHandler != nullptr)
+ sResult += pHandler->getType();
+ }
+
+ sResult += ")";
+
+ return sResult;
+}
+
+void OOXMLFastContextHandlerWrapper::setId(Id rId)
+{
+ OOXMLFastContextHandler::setId(rId);
+
+ if (mxWrappedContext.is())
+ {
+ OOXMLFastContextHandler * pHandler = getFastContextHandler();
+ if (pHandler != nullptr)
+ pHandler->setId(rId);
+ }
+}
+
+Id OOXMLFastContextHandlerWrapper::getId() const
+{
+ Id nResult = OOXMLFastContextHandler::getId();
+
+ if (mxWrappedContext.is())
+ {
+ OOXMLFastContextHandler * pHandler = getFastContextHandler();
+ if (pHandler != nullptr && pHandler->getId() != 0)
+ nResult = pHandler->getId();
+ }
+
+ return nResult;
+}
+
+void OOXMLFastContextHandlerWrapper::setToken(Token_t nToken)
+{
+ OOXMLFastContextHandler::setToken(nToken);
+
+ if (mxWrappedContext.is())
+ {
+ OOXMLFastContextHandler * pHandler = getFastContextHandler();
+ if (pHandler != nullptr)
+ pHandler->setToken(nToken);
+ }
+}
+
+Token_t OOXMLFastContextHandlerWrapper::getToken() const
+{
+ Token_t nResult = OOXMLFastContextHandler::getToken();
+
+ if (mxWrappedContext.is())
+ {
+ OOXMLFastContextHandler * pHandler = getFastContextHandler();
+ if (pHandler != nullptr)
+ nResult = pHandler->getToken();
+ }
+
+ return nResult;
+}
+
+
+/*
+ class OOXMLFastContextHandlerLinear
+ */
+
+OOXMLFastContextHandlerLinear::OOXMLFastContextHandlerLinear(OOXMLFastContextHandler* pContext)
+ : OOXMLFastContextHandlerProperties(pContext)
+ , depthCount( 0 )
+{
+}
+
+void OOXMLFastContextHandlerLinear::lcl_startFastElement(Token_t Element,
+ const uno::Reference< xml::sax::XFastAttributeList >& Attribs)
+{
+ buffer.appendOpeningTag( Element, Attribs );
+ ++depthCount;
+}
+
+void OOXMLFastContextHandlerLinear::lcl_endFastElement(Token_t Element)
+{
+ buffer.appendClosingTag( Element );
+ if( --depthCount == 0 )
+ process();
+}
+
+uno::Reference< xml::sax::XFastContextHandler >
+OOXMLFastContextHandlerLinear::lcl_createFastChildContext(Token_t,
+ const uno::Reference< xml::sax::XFastAttributeList >&)
+{
+ uno::Reference< xml::sax::XFastContextHandler > xContextHandler;
+ xContextHandler.set( this );
+ return xContextHandler;
+}
+
+void OOXMLFastContextHandlerLinear::lcl_characters(const OUString& aChars)
+{
+ buffer.appendCharacters( aChars );
+}
+
+/*
+ class OOXMLFastContextHandlerLinear
+ */
+
+OOXMLFastContextHandlerMath::OOXMLFastContextHandlerMath(OOXMLFastContextHandler* pContext)
+ : OOXMLFastContextHandlerLinear(pContext)
+{
+}
+
+void OOXMLFastContextHandlerMath::process()
+{
+ SvGlobalName name( SO3_SM_CLASSID );
+ comphelper::EmbeddedObjectContainer container;
+ OUString aName;
+ uno::Sequence<beans::PropertyValue> objArgs{ comphelper::makePropertyValue(
+ "DefaultParentBaseURL", getDocument()->GetDocumentBaseURL()) };
+ uno::Reference<embed::XEmbeddedObject> ref =
+ container.CreateEmbeddedObject(name.GetByteSequence(), objArgs, aName);
+ assert(ref.is());
+ if (!ref.is())
+ return;
+ uno::Reference< uno::XInterface > component(ref->getComponent(), uno::UNO_QUERY_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.
+ oox::FormulaImportBase& import = dynamic_cast<oox::FormulaImportBase&>(dynamic_cast<SfxBaseModel&>(*component));
+ import.readFormulaOoxml(buffer);
+ if (!isForwardEvents())
+ return;
+
+ OOXMLPropertySet::Pointer_t pProps(new OOXMLPropertySet);
+ OOXMLValue::Pointer_t pVal( new OOXMLStarMathValue( ref ));
+ if (mbIsMathPara)
+ {
+ switch (mnMathJcVal)
+ {
+ case eMathParaJc::CENTER:
+ pProps->add(NS_ooxml::LN_Value_math_ST_Jc_centerGroup, pVal,
+ OOXMLProperty::ATTRIBUTE);
+ break;
+ case eMathParaJc::LEFT:
+ pProps->add(NS_ooxml::LN_Value_math_ST_Jc_left, pVal,
+ OOXMLProperty::ATTRIBUTE);
+ break;
+ case eMathParaJc::RIGHT:
+ pProps->add(NS_ooxml::LN_Value_math_ST_Jc_right, pVal,
+ OOXMLProperty::ATTRIBUTE);
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ pProps->add(NS_ooxml::LN_starmath, pVal, OOXMLProperty::ATTRIBUTE);
+ mpStream->props( pProps.get() );
+}
+
+OOXMLFastContextHandlerCommentEx::OOXMLFastContextHandlerCommentEx(
+ OOXMLFastContextHandler* pContext)
+ : OOXMLFastContextHandler(pContext)
+{
+}
+
+void OOXMLFastContextHandlerCommentEx::lcl_endFastElement(Token_t /*Element*/)
+{
+ mpStream->commentProps(m_sParaId, { m_bDone });
+}
+
+void OOXMLFastContextHandlerCommentEx::att_paraId(const OOXMLValue::Pointer_t& pValue)
+{
+ m_sParaId = pValue->getString();
+}
+
+void OOXMLFastContextHandlerCommentEx::att_done(const OOXMLValue::Pointer_t& pValue)
+{
+ if (pValue->getInt())
+ m_bDone = true;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */