sw/qa/extras/ooxmlexport/data/del-then-format.docx |binary sw/qa/extras/ooxmlexport/ooxmlexport22.cxx | 14 +++++++++ sw/source/filter/ww8/docxattributeoutput.cxx | 32 ++++++++++++++++++++- 3 files changed, 45 insertions(+), 1 deletion(-)
New commits: commit 97066d4f5a89ad89d81a45c0b20ce404f9712fc7 Author: Miklos Vajna <[email protected]> AuthorDate: Wed May 14 08:35:56 2025 +0200 Commit: Miklos Vajna <[email protected]> CommitDate: Wed May 14 13:39:13 2025 +0200 tdf#166319 sw interdependent redlines: fix DOCX export of delete under format The bugdoc has <del>AA<format>BB</format>CC</del> in it, DOCX import works fine, but exporting back to DOCX results in a document Word can't open. It seems that the problem is: this is a "format on top of a delete" redline, so we kept writing <w:t> for the format redline content, while Word considers "format on top of a delete" essentially a type of delete, so it requires <w:delText> instead. Fix the problem by extending DocxAttributeOutput::RunText() to consider both "delete" and "delete, then something on top of it" as a delete redline, that results in the correct markup. Keep our own DOCX import unchanged to still accept both <w:t> and <w:delText> for text inside a delete redline. Change-Id: Id64fcad322bc58dc0ef3e453445f83248d6f3cff Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185301 Reviewed-by: Miklos Vajna <[email protected]> Tested-by: Jenkins diff --git a/sw/qa/extras/ooxmlexport/data/del-then-format.docx b/sw/qa/extras/ooxmlexport/data/del-then-format.docx new file mode 100644 index 000000000000..866201f7fb18 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/del-then-format.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx index c58845529817..5f49dabd5e60 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx @@ -235,6 +235,20 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf165933_noDelTextOnMove) assertXPath(pXmlDoc, "//w:moveFrom/w:r/w:delText", 0); } +CPPUNIT_TEST_FIXTURE(Test, testDelThenFormatDocxExport) +{ + // Given a document with <del>A<format>B</format>C</del> style redlines: + // When exporting that document: + loadAndSave("del-then-format.docx"); + + // Then make sure delete "under" format uses the <w:delText> markup: + // Without the accompanying fix in place, this test would have failed with: + // - In <>, XPath '/w:document/w:body/w:p/w:del[2]/w:r/w:delText' not found + // i.e. <w:t> was used, not <w:delText>. + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:del[2]/w:r/w:delText", u"BBB"); +} + DECLARE_OOXMLEXPORT_TEST(testTdf139418, "tdf139418.docx") { uno::Reference<beans::XPropertySet> xPropertySet( diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 8e9177170c7f..1c9fa4d07dfe 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -3850,6 +3850,36 @@ static bool impl_WriteRunText( FSHelperPtr const & pSerializer, sal_Int32 nTextT return true; } +namespace +{ +/// Decides if pRedlineData is a delete or is something on a delete. +RedlineType GetRedlineTypeForTextToken(const SwRedlineData* pRedlineData) +{ + if (!pRedlineData) + { + return RedlineType::None; + } + + if (pRedlineData->GetType() == RedlineType::Delete) + { + return RedlineType::Delete; + } + + const SwRedlineData* pNext = pRedlineData->Next(); + if (!pNext) + { + return RedlineType::None; + } + + if (pNext->GetType() == RedlineType::Delete) + { + return RedlineType::Delete; + } + + return RedlineType::None; +} +} + void DocxAttributeOutput::RunText( const OUString& rText, rtl_TextEncoding /*eCharSet*/, const OUString& rSymbolFont ) { if( m_closeHyperlinkInThisRun ) @@ -3886,7 +3916,7 @@ void DocxAttributeOutput::RunText( const OUString& rText, rtl_TextEncoding /*eCh // tdf#150166 save tracked moving around TOC as w:ins, w:del SwDoc::GetCurTOX(*m_rExport.m_pCurPam->GetPoint()) == nullptr; - if ( m_pRedlineData && m_pRedlineData->GetType() == RedlineType::Delete && !bMoved ) + if (GetRedlineTypeForTextToken(m_pRedlineData) == RedlineType::Delete && !bMoved) { nTextToken = XML_delText; }
