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 4d24374bf686d7637148355f6d9a9165469f062d
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed May 14 08:35:56 2025 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Wed May 14 10:55:46 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/+/185293
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

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 2d77c7155ed5..01f0220cd676 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport22.cxx
@@ -199,6 +199,20 @@ CPPUNIT_TEST_FIXTURE(Test, testBadFormulaResult)
     assertXPathContent(pXmlDoc, 
"/w:document/w:body/w:tbl/w:tr[4]/w:tc/w:p/w:r[4]/w:t", u"6");
 }
 
+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 3498494aac8a..702f2d7f8b26 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -3852,6 +3852,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 )
@@ -3888,7 +3918,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;
     }

Reply via email to