include/oox/shape/ShapeContextHandler.hxx             |   18 +++++++---
 oox/source/shape/ShapeContextHandler.cxx              |   31 +++++++++++-------
 sw/qa/extras/ooxmlexport/data/tdf146802.docx          |binary
 sw/qa/extras/ooxmlexport/ooxmlexport17.cxx            |   13 +++++++
 writerfilter/source/ooxml/OOXMLFastContextHandler.cxx |    5 +-
 5 files changed, 48 insertions(+), 19 deletions(-)

New commits:
commit 4a38ca4035ac03571925e72cb47e0beb8da2003a
Author:     Attila Bakos (NISZ) <bakos.attilakar...@nisz.hu>
AuthorDate: Wed Jan 19 17:43:54 2022 +0100
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Thu Feb 3 09:12:20 2022 +0100

    tdf#146802 OOXML import: fix embedded VML in grouped textbox
    
    E.g. OLE formulas inside them broke document load.
    
    Regression from 121cbc250b36290f0f8c7265fea57256dad69553
    "tdf#66039 DOCX: import textboxes (with tables, images etc.)
    in group shapes".
    
    Note: now embedded VML OLE is loaded in WPG shapes, thanks to
    that the ShapeHandler in oox/ has a stack having the start
    token inside for each shape.
    
    Change-Id: I973d78ed88c5c83efffd9629061e2a2c6fdd25e4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/128627
    Tested-by: László Németh <nem...@numbertext.org>
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/include/oox/shape/ShapeContextHandler.hxx 
b/include/oox/shape/ShapeContextHandler.hxx
index 27b70d2cf2c4..a245224730ed 100644
--- a/include/oox/shape/ShapeContextHandler.hxx
+++ b/include/oox/shape/ShapeContextHandler.hxx
@@ -19,6 +19,7 @@
 #pragma once
 
 #include <memory>
+#include <stack>
 #include <cppuhelper/implbase.hxx>
 #include <oox/drawingml/graphicshapecontext.hxx>
 #include <oox/core/fragmenthandler2.hxx>
@@ -90,12 +91,15 @@ public:
     void setRelationFragmentPath(const OUString & the_value);
 
     sal_Int32 getStartToken() const;
-    void setStartToken( sal_Int32 _starttoken );
+    void popStartToken();
+    void pushStartToken( sal_Int32 _starttoken );
 
     void setPosition(const css::awt::Point& rPosition);
 
-    const bool& getFullWPGSupport() { return m_bFullWPGSUpport; };
-    void setFullWPGSupport(const bool& rbUse) { m_bFullWPGSUpport = rbUse; };
+    const bool& getFullWPGSupport() { return m_bFullWPGSUpport; }
+    void setFullWPGSupport(const bool& rbUse) { m_bFullWPGSUpport = rbUse; }
+
+    bool isWordProcessingGroupShape() const { return mxWpgContext ? true : 
false; }
 
     void setDocumentProperties(const 
css::uno::Reference<css::document::XDocumentProperties>& xDocProps);
     void setMediaDescriptor(const 
css::uno::Sequence<css::beans::PropertyValue>& rMediaDescriptor);
@@ -109,9 +113,13 @@ private:
     ShapeContextHandler(ShapeContextHandler const &) = delete;
     void operator =(ShapeContextHandler const &) = delete;
 
-    ::sal_uInt32 mnStartToken;
+    // Special stack which always has at least one element.
+    // In case of group shapes with embedded content it will have more element 
than one.
+    std::stack<sal_uInt32> mnStartTokenStack;
+
     css::awt::Point maPosition;
-    bool m_bFullWPGSUpport;
+    bool m_bFullWPGSUpport; // Is this DrawingML shape supposed to be 
proccessed as WPG?
+
     drawingml::ShapePtr mpShape;
     std::shared_ptr< vml::Drawing > mpDrawing;
 
diff --git a/oox/source/shape/ShapeContextHandler.cxx 
b/oox/source/shape/ShapeContextHandler.cxx
index 6eb9e5ce9083..cacd46d82d14 100644
--- a/oox/source/shape/ShapeContextHandler.cxx
+++ b/oox/source/shape/ShapeContextHandler.cxx
@@ -44,7 +44,6 @@ using namespace core;
 using namespace drawingml;
 
 ShapeContextHandler::ShapeContextHandler(const 
rtl::Reference<ShapeFilterBase>& xFilterBase) :
-  mnStartToken(0),
   m_bFullWPGSUpport(false),
   mxShapeFilterBase(xFilterBase)
 
@@ -225,8 +224,9 @@ uno::Reference<xml::sax::XFastContextHandler>
 ShapeContextHandler::getContextHandler(sal_Int32 nElement)
 {
     uno::Reference<xml::sax::XFastContextHandler> xResult;
+    const sal_uInt32 nStartToken = getStartToken();
 
-    switch (getNamespace( mnStartToken ))
+    switch (getNamespace( nStartToken ))
     {
         case NMSP_doc:
         case NMSP_vml:
@@ -236,19 +236,19 @@ ShapeContextHandler::getContextHandler(sal_Int32 nElement)
             xResult.set(getDiagramShapeContext());
             break;
         case NMSP_dmlLockedCanvas:
-            xResult.set(getLockedCanvasContext(mnStartToken));
+            xResult.set(getLockedCanvasContext(nStartToken));
             break;
         case NMSP_dmlChart:
-            xResult.set(getChartShapeContext(mnStartToken));
+            xResult.set(getChartShapeContext(nStartToken));
             break;
         case NMSP_wps:
-            xResult.set(getWpsContext(mnStartToken, nElement));
+            xResult.set(getWpsContext(nStartToken, nElement));
             break;
         case NMSP_wpg:
-            xResult.set(getWpgContext(mnStartToken));
+            xResult.set(getWpgContext(nStartToken));
             break;
         default:
-            xResult.set(getGraphicShapeContext(mnStartToken));
+            xResult.set(getGraphicShapeContext(nStartToken));
             break;
     }
 
@@ -456,7 +456,7 @@ ShapeContextHandler::getShape()
         //NMSP_dmlChart == getNamespace( mnStartToken ) check is introduced to 
make sure that
         //mnStartToken is set as NMSP_dmlChart in setStartToken.
         //Only in case it is set then only the below block of code for 
ChartShapeContext should be executed.
-        else if (mxChartShapeContext.is() && (NMSP_dmlChart == getNamespace( 
mnStartToken )))
+        else if (mxChartShapeContext.is() && (NMSP_dmlChart == getNamespace( 
getStartToken() )))
         {
             ChartGraphicDataContext* pChartGraphicDataContext = 
dynamic_cast<ChartGraphicDataContext*>(mxChartShapeContext.get());
             if (pChartGraphicDataContext)
@@ -514,6 +514,8 @@ ShapeContextHandler::getShape()
         }
     }
 
+    if (xResult)
+        popStartToken();
     return xResult;
 }
 
@@ -537,12 +539,19 @@ void ShapeContextHandler::setRelationFragmentPath(const 
OUString & the_value)
 
 sal_Int32 ShapeContextHandler::getStartToken() const
 {
-    return mnStartToken;
+    assert(mnStartTokenStack.size() && "This stack must not be empty!");
+    return mnStartTokenStack.top();
 }
 
-void ShapeContextHandler::setStartToken( sal_Int32 _starttoken )
+void ShapeContextHandler::popStartToken()
 {
-    mnStartToken = _starttoken;
+    if (mnStartTokenStack.size() > 1)
+        mnStartTokenStack.pop();
+}
+
+void ShapeContextHandler::pushStartToken( sal_Int32 _starttoken )
+{
+    mnStartTokenStack.push(_starttoken);
 }
 
 void ShapeContextHandler::setPosition(const awt::Point& rPosition)
diff --git a/sw/qa/extras/ooxmlexport/data/tdf146802.docx 
b/sw/qa/extras/ooxmlexport/data/tdf146802.docx
new file mode 100644
index 000000000000..80d2ee17a0bc
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf146802.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index 6feb92b15149..ee7b37dfc151 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
@@ -51,6 +51,19 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf135906)
     // just test round-tripping. The document was exported as corrupt and 
didn't re-load.
 }
 
+CPPUNIT_TEST_FIXTURE(Test, TestTdf146802)
+{
+    load(DATA_DIRECTORY, "tdf146802.docx");
+
+    // First check if the load failed, as before the fix.
+    CPPUNIT_ASSERT(mxComponent);
+
+    // There is a group shape with text box inside having an embedded VML 
formula,
+    // check if something missing.
+    CPPUNIT_ASSERT_EQUAL_MESSAGE("Where is the formula?", 2, getShapes());
+    // Before the fix the bugdoc failed to load or the formula was missing.
+}
+
 CPPUNIT_TEST_FIXTURE(Test, testParaStyleNumLevel)
 {
     loadAndSave("para-style-num-level.docx");
diff --git a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx 
b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
index e245e37b4772..aa9de6408202 100644
--- a/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
+++ b/writerfilter/source/ooxml/OOXMLFastContextHandler.cxx
@@ -1721,7 +1721,7 @@ void OOXMLFastContextHandlerShape::setToken(Token_t 
nToken)
     OOXMLFastContextHandler::setToken(nToken);
 
     if (mrShapeContext.is())
-        mrShapeContext->setStartToken(nToken);
+        mrShapeContext->pushStartToken(nToken);
 }
 
 void OOXMLFastContextHandlerShape::sendShape( Token_t Element )
@@ -1761,8 +1761,7 @@ void OOXMLFastContextHandlerShape::sendShape( Token_t 
Element )
 
 bool OOXMLFastContextHandlerShape::isDMLGroupShape() const
 {
-    return (mrShapeContext->getFullWPGSupport() &&
-           (mrShapeContext->getStartToken() == Token_t(oox::NMSP_wpg | 
oox::XML_wgp)));
+    return (mrShapeContext->getFullWPGSupport() && 
mrShapeContext->isWordProcessingGroupShape());
 };
 
 void OOXMLFastContextHandlerShape::lcl_endFastElement

Reply via email to