sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx | 8 +++++++- sw/source/filter/ww8/wrtw8nds.cxx | 16 +++++++++++++--- 2 files changed, 20 insertions(+), 4 deletions(-)
New commits: commit fe07499d7ca032972715c6d518f2558bfd99b9ff Author: Justin Luth <[email protected]> AuthorDate: Tue Feb 10 12:13:59 2026 -0500 Commit: Miklos Vajna <[email protected]> CommitDate: Thu Feb 12 13:33:38 2026 +0100 tdf#170686 docx export: end SDT before writing final flies A plainText-y content control is reported as corrupt by Microsoft Word if it contains a floating frame. When a runSdt was at the end of the paragraph, the export was dumping any flies at the end into the Sdt run. Instead, the Sdt should first be closed, and then the remaining flies should be placed into their own separate run. Possibly, this should happen for fields as well? Or even for any paragraph, like we did in bug tdf#170516? It probably also belongs in the other 'if nNextAttr == nEnd' but I couldn't find any example unit tests to confirm. make CppunitTest_sw_ooxmlfieldexport \ CPPUNIT_TEST_NAME=testContentControlShape Change-Id: Ic1c160ed9c9985d4fcc308a271ee168fe00ea82b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199092 Tested-by: Jenkins Reviewed-by: Justin Luth <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199202 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Miklos Vajna <[email protected]> diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx index c6af7434cf10..64df72739eae 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx @@ -1033,7 +1033,13 @@ CPPUNIT_TEST_FIXTURE(Test, testContentControlShape) // When exporting that document back to DOCX: // Then make sure that completes without an assertion failure, which would mean not-well-formed // output was produced, since the <w:sdt> was conditional but the </w:sdt> was unconditional: - save(u"Office Open XML Text"_ustr); + save(TestFilter::DOCX); + + // tdf#170686: floating shapes are not allowed inside plainText date controls + xmlDocUniquePtr pXmlDoc = parseExport(u"word/document.xml"_ustr); + assertXPath(pXmlDoc, "//w:sdt", 1); // only one sdt + assertXPath(pXmlDoc, "//mc:AlternateContent", 1); // only one drawing + assertXPath(pXmlDoc, "//w:body/w:p/w:r/mc:AlternateContent", 1); // and it is not inside the sdt } CPPUNIT_TEST_FIXTURE(Test, testTdf104823) diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx index 217a22e81536..9bfa4ad7e5b6 100644 --- a/sw/source/filter/ww8/wrtw8nds.cxx +++ b/sw/source/filter/ww8/wrtw8nds.cxx @@ -2513,10 +2513,10 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode ) OUString aSavedSnippet ; // Don't redline content-controls--Word doesn't do them. - SwTextAttr* pAttr = rNode.GetTextAttrAt(nCurrentPos, RES_TXTATR_CONTENTCONTROL, - sw::GetTextAttrMode::Default); + const SwTextAttr* pSdt = rNode.GetTextAttrAt(nCurrentPos, RES_TXTATR_CONTENTCONTROL, + sw::GetTextAttrMode::Default); bool bIsStartOfContentControl = false; - if (pAttr && pAttr->GetStart() == nCurrentPos) + if (pSdt && pSdt->GetStart() == nCurrentPos) { pRedlineData = nullptr; bIsStartOfContentControl = true; @@ -2845,6 +2845,16 @@ void MSWordExportBase::OutputTextNode( SwTextNode& rNode ) else { // insert final graphic anchors if any before CR + if (pSdt && *pSdt->GetEnd() == nEnd && aAttrIter.HasFlysAt(nEnd)) + { + // Close the content control run before exporting final flies, + // otherwise the flies will be moved into the Sdt run, + // which (for a non-richText Sdt) will be considered corrupt in MS Word. + AttrOutput().EndRun(&rNode, nCurrentPos, nLen, /*bLastRun=*/false); + nLen = 0; + nCurrentPos = nEnd; + AttrOutput().StartRun(pRedlineData, nCurrentPos, bSingleEmptyRun); + } nStateOfFlyFrame = aAttrIter.OutFlys( nEnd ); // insert final bookmarks if any before CR and after flys AppendBookmarks( rNode, nEnd, 1 );
