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;
+};
+}

Reply via email to