configure.ac | 2 include/oox/vml/vmlshape.hxx | 3 include/oox/vml/vmlshapecontext.hxx | 9 oox/source/vml/vmlshape.cxx | 8 oox/source/vml/vmlshapecontext.cxx | 13 sw/Library_sw_writerfilter.mk | 1 sw/qa/extras/ooxmlexport/data/tdf164065.docx |binary sw/qa/extras/ooxmlexport/ooxmlexport21.cxx | 14 + sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx | 199 +++++++++++++-- sw/source/writerfilter/ooxml/OOXMLFastContextHandler.hxx | 12 sw/source/writerfilter/ooxml/ShadowContext.cxx | 96 +++++++ sw/source/writerfilter/ooxml/ShadowContext.hxx | 156 +++++++++++ 12 files changed, 491 insertions(+), 22 deletions(-)
New commits: commit 6167c553e7a0693223abb4bb41d4126c71170063 Author: Andras Timar <[email protected]> AuthorDate: Wed Feb 4 15:40:32 2026 +0100 Commit: Andras Timar <[email protected]> CommitDate: Wed Feb 4 15:40:32 2026 +0100 Bump version to 25.04.9.1 Change-Id: Id0f5fb8735c973f84e825d3aa38ede819603e498 diff --git a/configure.ac b/configure.ac index fa35b8148446..5d90822f7f58 100644 --- a/configure.ac +++ b/configure.ac @@ -9,7 +9,7 @@ dnl in order to create a configure script. # several non-alphanumeric characters, those are split off and used only for the # ABOUTBOXPRODUCTVERSIONSUFFIX in openoffice.lst. Why that is necessary, no idea. -AC_INIT([Collabora Office],[25.04.9.0],[],[],[https://collaboraoffice.com/]) +AC_INIT([Collabora Office],[25.04.9.1],[],[],[https://collaboraoffice.com/]) dnl libnumbertext needs autoconf 2.68, but that can pick up autoconf268 just fine if it is installed dnl whereas aclocal (as run by autogen.sh) insists on using autoconf and fails hard commit d5d1560dc6bd54e8b8fb1853e350a315b215b801 Author: Oliver Specht <[email protected]> AuthorDate: Mon Oct 14 14:50:06 2024 +0200 Commit: Andras Timar <[email protected]> CommitDate: Wed Feb 4 15:40:01 2026 +0100 tdf#164065 load vml textbox in a group shape Store (vml) textbox elements to determine whether to load shape text or Writer frame. Replay elements in second step and process depending on the outcome. - result flag not yet available while processing - The text shape in docx bugdoc of tdf#152878 can now be loaded as Writer frame but with wrong size/position. - should also be applied to drawing ml shapes currently always loaded as Writer frame Change-Id: I0778057f9985f5523d91a9d757e00f2968aba350 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/174902 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <[email protected]> Tested-by: Gabor Kelemen <[email protected]> diff --git a/include/oox/vml/vmlshape.hxx b/include/oox/vml/vmlshape.hxx index 2d5ba7bcd124..c960d9d8da46 100644 --- a/include/oox/vml/vmlshape.hxx +++ b/include/oox/vml/vmlshape.hxx @@ -145,6 +145,8 @@ public: OUString getGraphicPath() const; const Drawing& getDrawing() const { return mrDrawing; } + void setTextBox(bool bSet) {mbTextBox = bSet;} + bool isTextBox() const {return mbTextBox;} protected: /** Returns the coordinate system of this shape. */ @@ -159,6 +161,7 @@ protected: protected: Drawing& mrDrawing; ///< The VML drawing page that contains this shape. ShapeTypeModel maTypeModel; ///< The model structure containing shape type data. + bool mbTextBox; //will be set if the shape contains a text box }; diff --git a/include/oox/vml/vmlshapecontext.hxx b/include/oox/vml/vmlshapecontext.hxx index 8252e0e6ebe6..6f7a2eff7d5b 100644 --- a/include/oox/vml/vmlshapecontext.hxx +++ b/include/oox/vml/vmlshapecontext.hxx @@ -24,6 +24,7 @@ #include <oox/core/contexthandler2.hxx> #include <rtl/ustring.hxx> #include <sal/types.h> +//#include <oox/dllapi.h> #include <optional> @@ -79,7 +80,7 @@ private: }; -class ShapeContextBase : public ::oox::core::ContextHandler2 +class SAL_DLLPUBLIC_RTTI ShapeContextBase : public ::oox::core::ContextHandler2 { public: static ::oox::core::ContextHandlerRef @@ -94,7 +95,7 @@ protected: }; -class ShapeTypeContext : public ShapeContextBase +class SAL_DLLPUBLIC_RTTI ShapeTypeContext : public ShapeContextBase { public: explicit ShapeTypeContext( @@ -118,7 +119,7 @@ private: }; -class ShapeContext : public ShapeTypeContext +class SAL_DLLPUBLIC_RTTI ShapeContext : public ShapeTypeContext { public: explicit ShapeContext(::oox::core::ContextHandler2Helper const& rParent, @@ -127,6 +128,8 @@ public: virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) override; + void OOX_DLLPUBLIC setWriterShape(); + private: /** Processes the 'points' attribute. */ void setPoints( std::u16string_view rPoints ); diff --git a/oox/source/vml/vmlshape.cxx b/oox/source/vml/vmlshape.cxx index 3ddcda38825f..bf4a06c32993 100644 --- a/oox/source/vml/vmlshape.cxx +++ b/oox/source/vml/vmlshape.cxx @@ -150,6 +150,7 @@ void ShapeTypeModel::assignUsed( const ShapeTypeModel& rSource ) ShapeType::ShapeType( Drawing& rDrawing ) : mrDrawing( rDrawing ) + , mbTextBox(false) { } @@ -861,6 +862,13 @@ Reference< XShape > SimpleShape::implConvertAndInsert( const Reference< XShapes PropertySet(xShape).setAnyProperty(PROP_TextLowerDistance, Any(sal_Int32(getTextBox()->borderDistanceBottom))); xShape->setSize(aSize); } + + if (mbTextBox) + { + // similar to drawingml::Shape::createAndInsert(...) + PropertySet(xShape).setAnyProperty(PROP_TextBox, Any(true)); + } + } } diff --git a/oox/source/vml/vmlshapecontext.cxx b/oox/source/vml/vmlshapecontext.cxx index 46e19c328c78..01e2054bb078 100644 --- a/oox/source/vml/vmlshapecontext.cxx +++ b/oox/source/vml/vmlshapecontext.cxx @@ -612,7 +612,14 @@ ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 nElement, const Attri if (mrShapeModel.mbInGroup) // FIXME: without this a text will be added into the group-shape instead of its // parent shape - dynamic_cast<SimpleShape&>(mrShape).setService(u"com.sun.star.drawing.TextShape"_ustr); + { + if (mrShape.isTextBox()) + dynamic_cast<SimpleShape&>(mrShape).setService( + u"com.sun.star.drawing.CustomShape"_ustr); + else + dynamic_cast<SimpleShape&>(mrShape).setService( + u"com.sun.star.drawing.TextShape"_ustr); + } else // FIXME: without this we does not handle some properties like shadow dynamic_cast<SimpleShape&>(mrShape).setService(u"com.sun.star.text.TextFrame"_ustr); @@ -660,6 +667,10 @@ ContextHandlerRef ShapeContext::onCreateContext( sal_Int32 nElement, const Attri // handle remaining stuff in base class return ShapeTypeContext::onCreateContext( nElement, rAttribs ); } +void ShapeContext::setWriterShape() +{ + mrShape.setTextBox(true); +} void ShapeContext::setPoints(std::u16string_view rPoints) { diff --git a/sw/Library_sw_writerfilter.mk b/sw/Library_sw_writerfilter.mk index a51650ce9bf2..224b73de5cc7 100644 --- a/sw/Library_sw_writerfilter.mk +++ b/sw/Library_sw_writerfilter.mk @@ -134,6 +134,7 @@ $(eval $(call gb_Library_add_exception_objects,sw_writerfilter,\ sw/source/writerfilter/ooxml/OOXMLParserState \ sw/source/writerfilter/ooxml/OOXMLPropertySet \ sw/source/writerfilter/ooxml/OOXMLStreamImpl \ + sw/source/writerfilter/ooxml/ShadowContext \ )) $(eval $(call gb_Library_add_generated_exception_objects,sw_writerfilter,\ diff --git a/sw/qa/extras/ooxmlexport/data/tdf164065.docx b/sw/qa/extras/ooxmlexport/data/tdf164065.docx new file mode 100644 index 000000000000..b66a6cdb2da4 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf164065.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx index 90eeb788cccb..5f43e0b4a3df 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx @@ -1280,6 +1280,20 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf164474) } } +CPPUNIT_TEST_FIXTURE(Test, testTdf164065) +{ + loadAndSave("tdf164065.docx"); + CPPUNIT_ASSERT_EQUAL(1, getShapes()); + + uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(), + uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xTables->getCount()); + uno::Reference<table::XCellRange> xTable(xTables->getByIndex(0), uno::UNO_QUERY); + uno::Reference<text::XText> xCell(xTable->getCellByPosition(0, 0), uno::UNO_QUERY); + CPPUNIT_ASSERT_EQUAL(u"a"_ustr, xCell->getString()); +} + } // end of anonymous namespace CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx b/sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx index 10491799f703..8664b529e019 100644 --- a/sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx +++ b/sw/source/writerfilter/ooxml/OOXMLFastContextHandler.cxx @@ -25,6 +25,7 @@ #include <oox/mathml/imexport.hxx> #include <oox/token/namespaces.hxx> #include <oox/shape/ShapeFilterBase.hxx> +#include <oox/vml/vmlshapecontext.hxx> #include <sal/log.hxx> #include <comphelper/embeddedobjectcontainer.hxx> #include <comphelper/propertyvalue.hxx> @@ -42,6 +43,7 @@ #include "OOXMLPropertySet.hxx" #include <dmapper/GraphicHelpers.hxx> #include <unodraw.hxx> +#include "ShadowContext.hxx" const sal_Unicode uCR = 0xd; const sal_Unicode uFtnEdnRef = 0x2; @@ -2025,7 +2027,26 @@ OOXMLFastContextHandlerWrapper::OOXMLFastContextHandlerWrapper rtl::Reference<OOXMLFastContextHandlerShape> const & xShapeHandler) : OOXMLFastContextHandler(pParent), mxWrappedContext(xContext), - mxShapeHandler(xShapeHandler) + mxShapeHandler(xShapeHandler), + mbIsWriterFrameDetected(false), + mbIsReplayTextBox(false) +{ + setId(pParent->getId()); + setToken(pParent->getToken()); + setPropertySet(pParent->getPropertySet()); +} + +OOXMLFastContextHandlerWrapper::OOXMLFastContextHandlerWrapper(OOXMLFastContextHandler * pParent, + rtl::Reference<ShadowContext> const & xShadowContext, + uno::Reference<XFastContextHandler> const& xParentContext, + rtl::Reference<OOXMLFastContextHandlerShape> const & xShapeHandler) + : OOXMLFastContextHandler(pParent), + mxWrappedContext(xShadowContext), + mxShapeHandler(xShapeHandler), + mxShadowContext(xShadowContext), + mxReplayParentContext(xParentContext), + mbIsWriterFrameDetected(false), + mbIsReplayTextBox(false) { setId(pParent->getId()); setToken(pParent->getToken()); @@ -2053,6 +2074,114 @@ void SAL_CALL OOXMLFastContextHandlerWrapper::endUnknownElement mxWrappedContext->endUnknownElement(Namespace, Name); } +void SAL_CALL OOXMLFastContextHandlerWrapper::endFastElement(::sal_Int32 Element) +{ + OOXMLFastContextHandler::endFastElement(Element); + if (mxShadowContext.is()) + { + mxWrappedContext = mxReplayParentContext; + mbIsReplayTextBox = true; + mbIsWriterFrameDetected = mxShadowContext->isWriterFrame(); + sal_uInt16 nLevel = mxShadowContext->getElementLevel(); + if (!nLevel) + { + std::deque<CallData>& callDataDeque = mxShadowContext->getCallData(); + std::deque<uno::Reference<xml::sax::XFastContextHandler>> aLocalHandlers; + for (auto callDataIt = callDataDeque.begin(); callDataIt != callDataDeque.end(); ++callDataIt) + { + switch (callDataIt->getType()) + { + case Init: + { + sal_Int32 nElement = callDataIt->getElement(); + css::uno::Reference<css::xml::sax::XFastAttributeList> rAttribs + = callDataIt->getAttributes(); + if (mbIsWriterFrameDetected) + { + oox::vml::ShapeContext* pShapeContext = dynamic_cast<oox::vml::ShapeContext*>(mxWrappedContext.get()); + if (pShapeContext) + pShapeContext->setWriterShape(); + } + uno::Reference< xml::sax::XFastContextHandler > newWrapper = lcl_createFastChildContext(nElement, rAttribs); + static_cast<OOXMLFastContextHandlerWrapper*>(newWrapper.get())->mbIsWriterFrameDetected = mbIsWriterFrameDetected; + aLocalHandlers.push_back(newWrapper); + } + break; + case ElementAttr: + { + sal_Int32 nElement = callDataIt->getElement(); + css::uno::Reference<css::xml::sax::XFastAttributeList> rAttrs + = callDataIt->getAttributes(); + auto xHandler = aLocalHandlers.back(); + if (xHandler) + xHandler->startFastElement(nElement, rAttrs); + } + break; + case Char: + { + const ::rtl::OUString& chars = callDataIt->getChars(); + auto xHandler = aLocalHandlers.back(); + if (xHandler) + xHandler->characters(chars); + } + break; + case EndElementAttr: + { + sal_Int32 nElement = callDataIt->getElement(); + auto xHandler = aLocalHandlers.back(); + if (xHandler) + xHandler->endFastElement(nElement); + aLocalHandlers.pop_back(); + } + break; + case Unknown: + { + const ::rtl::OUString& rNameSpace = callDataIt->getUnknownNameSpace(); + const ::rtl::OUString& rElement = callDataIt->getUnknownElement(); + css::uno::Reference<css::xml::sax::XFastAttributeList> rAttrs + = callDataIt->getAttributes(); + auto xHandler = aLocalHandlers.back(); + if (xHandler) + xHandler->startUnknownElement(rNameSpace, rElement, rAttrs); + } + break; + case EndUnknown: + { + const ::rtl::OUString& rNameSpace = callDataIt->getUnknownNameSpace(); + const ::rtl::OUString& rElement = callDataIt->getUnknownElement(); + auto xHandler = aLocalHandlers.back(); + if (xHandler) + xHandler->endUnknownElement(rNameSpace, rElement); + aLocalHandlers.pop_back(); + } + break; + case ElementContext: + { + sal_Int32 nElement = callDataIt->getElement(); + css::uno::Reference<css::xml::sax::XFastAttributeList> rAttrs + = callDataIt->getAttributes(); + uno::Reference< xml::sax::XFastContextHandler > newContext = aLocalHandlers.back()->createFastChildContext(nElement, rAttrs); + if (nElement == Token_t(NMSP_vml | XML_textbox)) + static_cast<OOXMLFastContextHandlerWrapper*>(newContext.get())->mbIsWriterFrameDetected = mbIsWriterFrameDetected; + aLocalHandlers.push_back(newContext); + } + break; + case UnknownContext: + { + const ::rtl::OUString& rNameSpace = callDataIt->getUnknownNameSpace(); + const ::rtl::OUString& rElement = callDataIt->getUnknownElement(); + css::uno::Reference<css::xml::sax::XFastAttributeList> rAttrs + = callDataIt->getAttributes(); + uno::Reference< xml::sax::XFastContextHandler > newContext = aLocalHandlers.back()->createUnknownChildContext(rNameSpace, rElement, rAttrs); + aLocalHandlers.push_back(newContext); + } + break; + } + } + } + } +} + uno::Reference< xml::sax::XFastContextHandler > SAL_CALL OOXMLFastContextHandlerWrapper::createUnknownChildContext (const OUString & Namespace, @@ -2103,12 +2232,17 @@ void OOXMLFastContextHandlerWrapper::lcl_startFastElement { 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(); + if (!mxShadowContext.is()) + { + bool bInTokens = mMyTokens.find(Element) != mMyTokens.end(); + if ((mxShapeHandler->isDMLGroupShape() + && (Element == Token_t(NMSP_wps | XML_txbx) + || Element == Token_t(NMSP_wps | XML_linkedTxbx))) + //TODO: why check for bInTokens + || (!bInTokens && mbIsWriterFrameDetected && Element == Token_t(NMSP_vml | XML_textbox))) + { + mpStream->startTextBoxContent(); + } } } @@ -2118,11 +2252,16 @@ void OOXMLFastContextHandlerWrapper::lcl_endFastElement if (mxWrappedContext.is()) mxWrappedContext->endFastElement(Element); - if (mxShapeHandler->isDMLGroupShape() - && (Element == Token_t(NMSP_wps | XML_txbx) - || Element == Token_t(NMSP_wps | XML_linkedTxbx))) + if (!mxShadowContext.is()) { - mpStream->endTextBoxContent(); + bool bInTokens = mMyTokens.find(Element) != mMyTokens.end(); + if ((mxShapeHandler->isDMLGroupShape() + && (Element == Token_t(NMSP_wps | XML_txbx) + || Element == Token_t(NMSP_wps | XML_linkedTxbx))) + || (!bInTokens && mbIsWriterFrameDetected && Element == Token_t(NMSP_vml | XML_textbox))) + { + mpStream->endTextBoxContent(); + } } } @@ -2132,6 +2271,10 @@ OOXMLFastContextHandlerWrapper::lcl_createFastChildContext const uno::Reference< xml::sax::XFastAttributeList > & Attribs) { uno::Reference< xml::sax::XFastContextHandler > xResult; + if (mxShadowContext.is() && !mbIsReplayTextBox) + { + return mxShadowContext->createFastChildContext(Element, Attribs); + } bool bInNamespaces = mMyNamespaces.find(oox::getNamespace(Element)) != mMyNamespaces.end(); bool bInTokens = mMyTokens.find( Element ) != mMyTokens.end( ); @@ -2152,11 +2295,34 @@ OOXMLFastContextHandlerWrapper::lcl_createFastChildContext } else if (mxWrappedContext.is() && !bSkipImages) { - rtl::Reference<OOXMLFastContextHandlerWrapper> pWrapper = - new OOXMLFastContextHandlerWrapper - (this, mxWrappedContext->createFastChildContext(Element, Attribs), - mxShapeHandler); - pWrapper->mMyNamespaces = mMyNamespaces; + rtl::Reference<OOXMLFastContextHandlerWrapper> pWrapper; + if (Element == (NMSP_vml | XML_textbox) && !mbIsReplayTextBox) + { + //TODO: change handling of drawingml, currently Writer frame only + rtl::Reference<ShadowContext> xShadowContext + = new ShadowContext(Element, Attribs); + pWrapper = new OOXMLFastContextHandlerWrapper(this, xShadowContext, mxWrappedContext, mxShapeHandler); + pWrapper->mMyNamespaces = mMyNamespaces; + //don't send shape here + bInTokens = false; + } + else + { + pWrapper = + new OOXMLFastContextHandlerWrapper + (this, mxWrappedContext->createFastChildContext(Element, Attribs), + mxShapeHandler); + if (mbIsWriterFrameDetected) + { + pWrapper->addNamespace(NMSP_doc); + pWrapper->addNamespace(NMSP_vmlWord); + pWrapper->addNamespace(NMSP_vmlOffice); + } + else + { + pWrapper->mMyNamespaces = mMyNamespaces; + } + } pWrapper->mMyTokens = mMyTokens; pWrapper->setPropertySet(getPropertySet()); xResult.set(pWrapper); @@ -2295,7 +2461,6 @@ Token_t OOXMLFastContextHandlerWrapper::getToken() const return nResult; } - /* class OOXMLFastContextHandlerLinear */ diff --git a/sw/source/writerfilter/ooxml/OOXMLFastContextHandler.hxx b/sw/source/writerfilter/ooxml/OOXMLFastContextHandler.hxx index 03a4d40e5c2f..49abfde529ce 100644 --- a/sw/source/writerfilter/ooxml/OOXMLFastContextHandler.hxx +++ b/sw/source/writerfilter/ooxml/OOXMLFastContextHandler.hxx @@ -27,6 +27,7 @@ #include <rtl/ref.hxx> #include "OOXMLParserState.hxx" #include "OOXMLPropertySet.hxx" +#include "ShadowContext.hxx" namespace writerfilter::ooxml { @@ -494,9 +495,14 @@ public: OOXMLFastContextHandlerWrapper(OOXMLFastContextHandler * pParent, css::uno::Reference<css::xml::sax::XFastContextHandler> const & xContext, rtl::Reference<OOXMLFastContextHandlerShape> const & xShapeHandler); + OOXMLFastContextHandlerWrapper(OOXMLFastContextHandler * pParent, + rtl::Reference<ShadowContext> const & xContext, + css::uno::Reference<css::xml::sax::XFastContextHandler> const & xParentContext, + rtl::Reference<OOXMLFastContextHandlerShape> const & xShapeHandler); virtual ~OOXMLFastContextHandlerWrapper() override; // css::xml::sax::XFastContextHandler: + virtual void SAL_CALL endFastElement( ::sal_Int32 Element ) override; virtual void SAL_CALL startUnknownElement(const OUString & Namespace, const OUString & Name, const css::uno::Reference< css::xml::sax::XFastAttributeList > & Attribs) override; virtual void SAL_CALL endUnknownElement(const OUString & Namespace, const OUString & Name) override; @@ -532,12 +538,18 @@ protected: virtual void setToken(Token_t nToken) override; virtual Token_t getToken() const override; + bool isWriterFrameDetected() const { return mbIsWriterFrameDetected;} + private: css::uno::Reference<css::xml::sax::XFastContextHandler> mxWrappedContext; rtl::Reference<OOXMLFastContextHandlerShape> mxShapeHandler; std::set<Id> mMyNamespaces; std::set<Token_t> mMyTokens; OOXMLPropertySet::Pointer_t mpPropertySet; + rtl::Reference<ShadowContext> const mxShadowContext; + css::uno::Reference<css::xml::sax::XFastContextHandler> mxReplayParentContext; + bool mbIsWriterFrameDetected; + bool mbIsReplayTextBox; OOXMLFastContextHandler * getFastContextHandler() const; }; diff --git a/sw/source/writerfilter/ooxml/ShadowContext.cxx b/sw/source/writerfilter/ooxml/ShadowContext.cxx new file mode 100644 index 000000000000..d850092c9adc --- /dev/null +++ b/sw/source/writerfilter/ooxml/ShadowContext.cxx @@ -0,0 +1,96 @@ +/* -*- 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 "ShadowContext.hxx" +#include <ooxml/resourceids.hxx> +#include <oox/token/namespaces.hxx> + +namespace writerfilter::ooxml +{ +using namespace ::com::sun::star; +using namespace oox; +using namespace ::com::sun::star::xml::sax; + +ShadowContext::ShadowContext(::sal_Int32 nElement, + const uno::Reference<XFastAttributeList>& rAttribs) + : m_nElementLevel(0) + , m_bImportAsWriterFrame(false) +{ + CallData callData(m_nElementLevel, nElement, rAttribs, CallDataType::Init); + m_aCallDataDeque.push_back(callData); +} +ShadowContext::~ShadowContext() {} + +void ShadowContext::startFastElement( + ::sal_Int32 nElement, + const ::css::uno::Reference<::css::xml::sax::XFastAttributeList>& rAttribs) +{ + ++m_nElementLevel; + CallData callData(m_nElementLevel, nElement, rAttribs, CallDataType::ElementAttr); + m_aCallDataDeque.push_back(callData); + if (nElement == (oox::NMSP_doc | oox::XML_tbl)) + { + m_bImportAsWriterFrame = true; + } +} + +void ShadowContext::startUnknownElement( + const ::rtl::OUString& rNamespace, const ::rtl::OUString& rElement, + const ::css::uno::Reference<::css::xml::sax::XFastAttributeList>& rAttribs) +{ + ++m_nElementLevel; + CallData callData(m_nElementLevel, rNamespace, rElement, rAttribs, CallDataType::Unknown); + m_aCallDataDeque.push_back(callData); +} +void ShadowContext::endFastElement(::sal_Int32 nElement) +{ + --m_nElementLevel; + CallData callData(m_nElementLevel, nElement); + m_aCallDataDeque.push_back(callData); +} +void ShadowContext::endUnknownElement(const ::rtl::OUString& rNamespace, + const ::rtl::OUString& rElement) +{ + --m_nElementLevel; + CallData callData(m_nElementLevel, rNamespace, rElement); + m_aCallDataDeque.push_back(callData); +} +::css::uno::Reference<::css::xml::sax::XFastContextHandler> ShadowContext::createFastChildContext( + ::sal_Int32 nElement, + const ::css::uno::Reference<::css::xml::sax::XFastAttributeList>& rAttribs) +{ + CallData callData(m_nElementLevel, nElement, rAttribs, CallDataType::ElementContext); + m_aCallDataDeque.push_back(callData); + return this; +} +::css::uno::Reference<::css::xml::sax::XFastContextHandler> +ShadowContext::createUnknownChildContext( + const ::rtl::OUString& rNamespace, const ::rtl::OUString& rElement, + const ::css::uno::Reference<::css::xml::sax::XFastAttributeList>& rAttribs) +{ + CallData callData(m_nElementLevel, rNamespace, rElement, rAttribs, + CallDataType::UnknownContext); + m_aCallDataDeque.push_back(callData); + return this; +} +void ShadowContext::characters(const ::rtl::OUString& aChars) +{ + CallData callData(m_nElementLevel, aChars); + m_aCallDataDeque.push_back(callData); +} +} //namespace diff --git a/sw/source/writerfilter/ooxml/ShadowContext.hxx b/sw/source/writerfilter/ooxml/ShadowContext.hxx new file mode 100644 index 000000000000..d7e389d10abd --- /dev/null +++ b/sw/source/writerfilter/ooxml/ShadowContext.hxx @@ -0,0 +1,156 @@ +/* -*- 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 . + */ + +#pragma once + +#include <cppuhelper/implbase.hxx> +#include <com/sun/star/xml/sax/XFastContextHandler.hpp> +#include <sax/fastattribs.hxx> +#include <oox/helper/attributelist.hxx> +#include <oox/core/contexthandler.hxx> +#include <queue> + +namespace writerfilter::ooxml +{ +enum CallDataType +{ + Init, + ElementAttr, + Char, + EndElementAttr, + Unknown, + EndUnknown, + ElementContext, + UnknownContext +}; + +class CallData +{ + sal_uInt32 m_nLevel; + CallDataType m_eType; + sal_Int32 m_nElement; + css::uno::Reference<css::xml::sax::XFastAttributeList> m_aAttributes; + + //char + ::rtl::OUString m_aChars; + + //unknwon + ::rtl::OUString m_sNameSpace; + ::rtl::OUString m_sElement; + +public: + //Start unknown element or context + CallData(sal_uInt32 nLevel, const ::rtl::OUString& rNameSpace, const ::rtl::OUString& rElement, + const css::uno::Reference<css::xml::sax::XFastAttributeList>& rAttributes, + CallDataType eType) + : m_nLevel(nLevel) + , m_eType(eType) + , m_aAttributes(new sax_fastparser::FastAttributeList(rAttributes)) + , m_sNameSpace(rNameSpace) + , m_sElement(rElement) + { + } + + //end unknown element + CallData(sal_uInt32 nLevel, const ::rtl::OUString& rNameSpace, const ::rtl::OUString& rElement) + : m_nLevel(nLevel) + , m_eType(CallDataType::EndUnknown) + , m_sNameSpace(rNameSpace) + , m_sElement(rElement) + { + } + + // start fast element + CallData(sal_uInt32 nLevel, sal_Int32 nElement, + const css::uno::Reference<css::xml::sax::XFastAttributeList>& rAttributes, + CallDataType eType) + : m_nLevel(nLevel) + , m_eType(eType) + , m_nElement(nElement) + , m_aAttributes(new sax_fastparser::FastAttributeList(rAttributes)) + { + } + + // end fast element + CallData(sal_uInt32 nLevel, sal_Int32 nElement) + : m_nLevel(nLevel) + , m_eType(CallDataType::EndElementAttr) + , m_nElement(nElement) + { + } + + //chars + CallData(sal_uInt32 nLevel, const ::rtl::OUString& rChars) + : m_nLevel(nLevel) + , m_eType(CallDataType::Char) + , m_aChars(rChars) + { + } + + CallData(CallData const&) = default; + + sal_uInt32 getLevel() const { return m_nLevel; } + CallDataType getType() const { return m_eType; } + sal_Int32 getElement() const { return m_nElement; } + const ::rtl::OUString& getChars() { return m_aChars; } + css::uno::Reference<css::xml::sax::XFastAttributeList> getAttributes() const + { + return m_aAttributes; + } + const ::rtl::OUString& getUnknownNameSpace() const { return m_sNameSpace; } + const ::rtl::OUString& getUnknownElement() const { return m_sElement; } +}; +class ShadowContext : public ::oox::core::ContextHandler_BASE +{ +public: + explicit ShadowContext(::sal_Int32 Element, + const css::uno::Reference<css::xml::sax::XFastAttributeList>& rAttribs); + virtual ~ShadowContext() override; + + //XFastContextHandler + virtual void SAL_CALL startFastElement( + ::sal_Int32 Element, + const ::css::uno::Reference<::css::xml::sax::XFastAttributeList>& Attribs) override; + virtual void SAL_CALL startUnknownElement( + const ::rtl::OUString& Namespace, const ::rtl::OUString& Name, + const ::css::uno::Reference<::css::xml::sax::XFastAttributeList>& Attribs) override; + virtual void SAL_CALL endFastElement(::sal_Int32 Element) override; + virtual void SAL_CALL endUnknownElement(const ::rtl::OUString& Namespace, + const ::rtl::OUString& Name) override; + virtual ::css::uno::Reference<::css::xml::sax::XFastContextHandler> + SAL_CALL createFastChildContext( + ::sal_Int32 Element, + const ::css::uno::Reference<::css::xml::sax::XFastAttributeList>& Attribs) override; + virtual ::css::uno::Reference<::css::xml::sax::XFastContextHandler> + SAL_CALL createUnknownChildContext( + const ::rtl::OUString& Namespace, const ::rtl::OUString& Name, + const ::css::uno::Reference<::css::xml::sax::XFastAttributeList>& Attribs) override; + virtual void SAL_CALL characters(const ::rtl::OUString& aChars) override; + + sal_uInt16 getElementLevel() const { return m_nElementLevel; } + bool isWriterFrame() const { return m_bImportAsWriterFrame; } + + std::deque<CallData>& getCallData() { return m_aCallDataDeque; } + +private: + std::deque<CallData> m_aCallDataDeque; + sal_uInt16 m_nElementLevel; + bool m_bImportAsWriterFrame; +}; +}
