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               |   15 +
 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 +++++++++++
 11 files changed, 491 insertions(+), 21 deletions(-)

New commits:
commit 5fb8e29926a5c0dd1ae027f05d48826399cc31a1
Author:     Oliver Specht <oliver.spe...@cib.de>
AuthorDate: Mon Oct 14 14:50:06 2024 +0200
Commit:     Thorsten Behrens <thorsten.behr...@allotropia.de>
CommitDate: Tue Dec 10 17:18:10 2024 +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 <thorsten.behr...@allotropia.de>
    Tested-by: Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>

diff --git a/include/oox/vml/vmlshape.hxx b/include/oox/vml/vmlshape.hxx
index 64259c554caf..6348b539f689 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 1f5a8f27c59e..7908dd7527c4 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)
 {
 }
 
@@ -859,6 +860,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 daedc527f465..85c70347e0e8 100644
--- a/oox/source/vml/vmlshapecontext.cxx
+++ b/oox/source/vml/vmlshapecontext.cxx
@@ -548,7 +548,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);
@@ -591,6 +598,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 207568ee8b76..0447f0b78f12 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport21.cxx
@@ -17,6 +17,7 @@
 #include <com/sun/star/text/XDocumentIndex.hpp>
 #include <com/sun/star/text/XTextTable.hpp>
 #include <com/sun/star/text/XTextField.hpp>
+#include <com/sun/star/table/XCellRange.hpp>
 #include <com/sun/star/style/LineSpacing.hpp>
 #include <com/sun/star/style/LineSpacingMode.hpp>
 #include <com/sun/star/packages/zip/ZipFileAccess.hpp>
@@ -1189,6 +1190,20 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf146269)
     }
 }
 
+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 046d8c6aacb0..ab01166040fe 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;
@@ -1973,7 +1975,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());
@@ -2001,6 +2022,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,
@@ -2051,12 +2180,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();
+        }
     }
 }
 
@@ -2066,11 +2200,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();
+        }
     }
 }
 
@@ -2080,6 +2219,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( );
@@ -2100,11 +2243,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);
@@ -2243,7 +2409,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;
+};
+}

Reply via email to