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"/>