sw/CppunitTest_sw_writerfilter_ooxml.mk        |   12 ++++++++++
 sw/qa/writerfilter/ooxml/data/nested-runs.docx |binary
 sw/qa/writerfilter/ooxml/ooxml.cxx             |   30 ++++++++++++++++++++++---
 sw/source/writerfilter/ooxml/model.xml         |    4 +++
 4 files changed, 43 insertions(+), 3 deletions(-)

New commits:
commit a414d7d884bc49f6d4028ad2fcf4186998a5a67e
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed May 28 10:10:08 2025 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed May 28 17:52:21 2025 +0200

    tdf#166680 DOCX import: handle nested <w:r> runs
    
    Regression from commit 57450afb768c085df0ba2344aa94b5f843060178 (DOCX
    import: declare wps as a supported feature, 2013-12-03), the bugdoc has
    a shape that has invalid (but well-formed) <w:r> elements inside a <w:r>
    element and Word imports this fine.
    
    We used to be compatible, because <mc:AlternateContent> has
    <mc:Choice> and <mc:Fallback> branches and the fallback didn't have
    these nested runs and we used to read the fallback.
    
    Fix the problem by extending the generated tokenizer to also accept
    <w:r> inside <w:r>.
    
    Note that while this is invalid, not only old Writer but also Word
    accepts this.
    
    Change-Id: I52e573f921e95dcc6e2b76b2d46bf2b3a03a88ac
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185972
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sw/CppunitTest_sw_writerfilter_ooxml.mk 
b/sw/CppunitTest_sw_writerfilter_ooxml.mk
index cfae3bc41a9f..002b3a791a46 100644
--- a/sw/CppunitTest_sw_writerfilter_ooxml.mk
+++ b/sw/CppunitTest_sw_writerfilter_ooxml.mk
@@ -13,6 +13,15 @@ $(eval $(call 
gb_CppunitTest_CppunitTest,sw_writerfilter_ooxml))
 
 $(eval $(call gb_CppunitTest_use_externals,sw_writerfilter_ooxml,\
        boost_headers \
+       libxml2 \
+))
+
+$(eval $(call gb_CppunitTest_set_include,sw_writerfilter_ooxml,\
+    -I$(SRCDIR)/sw/inc \
+    -I$(SRCDIR)/sw/source/core/inc \
+    -I$(SRCDIR)/sw/source/uibase/inc \
+    -I$(SRCDIR)/sw/qa/inc \
+    $$(INCLUDE) \
 ))
 
 $(eval $(call gb_CppunitTest_add_exception_objects,sw_writerfilter_ooxml, \
@@ -27,6 +36,9 @@ $(eval $(call 
gb_CppunitTest_use_libraries,sw_writerfilter_ooxml, \
     oox \
     sal \
     subsequenttest \
+    sw \
+    swqahelper \
+    svl \
     test \
     unotest \
     utl \
diff --git a/sw/qa/writerfilter/ooxml/data/nested-runs.docx 
b/sw/qa/writerfilter/ooxml/data/nested-runs.docx
new file mode 100644
index 000000000000..4d787788bedc
Binary files /dev/null and b/sw/qa/writerfilter/ooxml/data/nested-runs.docx 
differ
diff --git a/sw/qa/writerfilter/ooxml/ooxml.cxx 
b/sw/qa/writerfilter/ooxml/ooxml.cxx
index f0ce47aa1e0c..c5f9af177a13 100644
--- a/sw/qa/writerfilter/ooxml/ooxml.cxx
+++ b/sw/qa/writerfilter/ooxml/ooxml.cxx
@@ -7,7 +7,7 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include <test/unoapi_test.hxx>
+#include <swmodeltestbase.hxx>
 
 #include <com/sun/star/beans/XPropertySet.hpp>
 #include <com/sun/star/style/LineSpacing.hpp>
@@ -15,16 +15,19 @@
 #include <com/sun/star/text/XTextTablesSupplier.hpp>
 #include <com/sun/star/text/XTextDocument.hpp>
 
+#include <fmtcntnt.hxx>
+#include <ndtxt.hxx>
+
 using namespace ::com::sun::star;
 
 namespace
 {
 /// Tests for sw/source/writerfilter/ooxml/.
-class Test : public UnoApiTest
+class Test : public SwModelTestBase
 {
 public:
     Test()
-        : UnoApiTest(u"/sw/qa/writerfilter/ooxml/data/"_ustr)
+        : SwModelTestBase(u"/sw/qa/writerfilter/ooxml/data/"_ustr)
     {
     }
 };
@@ -85,6 +88,27 @@ CPPUNIT_TEST_FIXTURE(Test, testRecursiveHeaderRels)
     CPPUNIT_ASSERT_EQUAL_MESSAGE("Default para style has 1.08 line-spacing", 
sal_Int16(108),
                                  aLineSpacing.Height);
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testNestedRuns)
+{
+    // Given a document with nested <w:r> in a shape text:
+    // When importing that document:
+    createSwDoc("nested-runs.docx");
+
+    // Then make sure the shape text is not lost:
+    SwDoc* pDoc = getSwDoc();
+    sw::FrameFormats<sw::SpzFrameFormat*>& rFlys = *pDoc->GetSpzFrameFormats();
+    CPPUNIT_ASSERT(!rFlys.empty());
+    sw::SpzFrameFormat* pFly = rFlys[0];
+    const SwNodeIndex* pFlyStartIndex = pFly->GetContent().GetContentIdx();
+    CPPUNIT_ASSERT(pFlyStartIndex);
+    SwNodeIndex aNodeIndex(*pFlyStartIndex);
+    ++aNodeIndex;
+    SwTextNode* pTextNode = aNodeIndex.GetNode().GetTextNode();
+    CPPUNIT_ASSERT(pTextNode);
+    // Without the accompanying fix in place, this test would have failed, the 
shape was empty.
+    CPPUNIT_ASSERT_EQUAL(u"Test text box"_ustr, pTextNode->GetText());
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/writerfilter/ooxml/model.xml 
b/sw/source/writerfilter/ooxml/model.xml
index 52ee1dadfbbd..133dd0f2f48d 100644
--- a/sw/source/writerfilter/ooxml/model.xml
+++ b/sw/source/writerfilter/ooxml/model.xml
@@ -13507,6 +13507,9 @@
           <element name="t">
             <ref name="CT_Text"/>
           </element>
+          <element name="r">
+            <ref name="CT_R"/>
+          </element>
           <element name="delText">
             <ref name="CT_delText"/>
           </element>
@@ -18197,6 +18200,7 @@
     <resource name="EG_RunInnerContent" resource="Stream">
       <element name="br" tokenid="ooxml:EG_RunInnerContent_br"/>
       <element name="t" tokenid="ooxml:EG_RunInnerContent_t"/>
+      <element name="r" tokenid="ooxml:EG_RunInnerContent_r"/>
       <element name="delText" tokenid="ooxml:EG_RunInnerContent_delText"/>
       <element name="instrText" tokenid="ooxml:EG_RunInnerContent_instrText"/>
       <element name="delInstrText" 
tokenid="ooxml:EG_RunInnerContent_delInstrText"/>

Reply via email to