sw/source/core/unocore/unoframe.cxx |    7 +++++++
 xmloff/source/text/txtparae.cxx     |   31 ++++++++++++++++++++++++++++---
 2 files changed, 35 insertions(+), 3 deletions(-)

New commits:
commit 801debfc365b4c5e6bf63324aaef82f449ddb443
Author:     Mike Kaganski <[email protected]>
AuthorDate: Mon Jun 16 12:37:30 2025 +0500
Commit:     Mike Kaganski <[email protected]>
CommitDate: Mon Jun 16 13:36:41 2025 +0200

    tdf#167033: allow double processing of Writer shapes' text frame nodes
    
    It turns out, that these are naturally processed twice.
    
    When enumerating paragraph's content, CollectFrameAtNode would find both
    the shape and the shape's text frame anchored to the paragraph node.
    Then, XMLTextParagraphExport::exportTextContentEnumeration will process
    the shape; and in XMLShapeExport::collectShapeAutoStyles, the shape will
    be queried for XText, which will return the text frame, which will then
    be processed.
    And finally, XMLTextParagraphExport::exportTextContentEnumeration will
    process the text frame, for the second time - at which point, the frame's
    paragraphs will be processed again.
    
    I don't know if it's possible to avoid the repeated processing; here I
    only add a debug check for this, and skip adding duplicate node index.
    
    Change-Id: I84275f233554a6b4923ddaabc336bec7a94ec2fa
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/186546
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/sw/source/core/unocore/unoframe.cxx 
b/sw/source/core/unocore/unoframe.cxx
index a5c4fb9cf86b..32651e47bf08 100644
--- a/sw/source/core/unocore/unoframe.cxx
+++ b/sw/source/core/unocore/unoframe.cxx
@@ -3339,6 +3339,13 @@ uno::Reference<container::XNameReplace > SAL_CALL 
SwXTextFrame::getEvents()
         if(!IsDescriptor())
             aRet = SwXText::getPropertyValue(rPropertyName);
     }
+#ifndef NDEBUG
+    else if (rPropertyName == "DbgIsShapesTextFrame")
+    {
+        aRet <<= SwTextBoxHelper::isTextBox(GetFrameFormat(), RES_FLYFRMFMT)
+                 || SwTextBoxHelper::isTextBox(GetFrameFormat(), 
RES_DRAWFRMFMT);
+    }
+#endif
     else
         aRet = SwXFrame::getPropertyValue(rPropertyName);
     return aRet;
diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx
index 1d02d84964d2..3ac362785ad5 100644
--- a/xmloff/source/text/txtparae.cxx
+++ b/xmloff/source/text/txtparae.cxx
@@ -1772,6 +1772,30 @@ bool XMLTextParagraphExport::ExportListId() const
            && GetExport().getSaneDefaultVersion() >= 
SvtSaveOptions::ODFSVER_012;
 }
 
+#ifndef NDEBUG
+static bool isInShapesTextFrame(const 
css::uno::Reference<css::text::XTextContent>& xTextContent)
+{
+    auto xTextRange = xTextContent.query<css::text::XTextRange>();
+    if (!xTextRange)
+        return false;
+    auto xParentTextProps = 
xTextRange->getText().query<css::beans::XPropertySet>();
+    if (!xParentTextProps)
+        return false;
+    try
+    {
+        // see SwXTextFrame::getEvents
+        css::uno::Any ret = 
xParentTextProps->getPropertyValue(u"DbgIsShapesTextFrame"_ustr);
+        if (bool result; ret >>= result)
+            return result;
+        return false;
+    }
+    catch (css::beans::UnknownPropertyException&)
+    {
+        return false;
+    }
+}
+#endif
+
 void XMLTextParagraphExport::RecordNodeIndex(const 
css::uno::Reference<css::text::XTextContent>& xTextContent)
 {
     if (!bInDocumentNodeOrderCollection)
@@ -1783,9 +1807,10 @@ void XMLTextParagraphExport::RecordNodeIndex(const 
css::uno::Reference<css::text
             sal_Int32 index = 0;
             // See SwXParagraph::Impl::GetPropertyValues_Impl
             xPropSet->getPropertyValue(u"ODFExport_NodeIndex"_ustr) >>= index;
-            assert(std::find(maDocumentNodeOrder.begin(), 
maDocumentNodeOrder.end(), index)
-                   == maDocumentNodeOrder.end());
-            maDocumentNodeOrder.push_back(index);
+            auto it = std::find(maDocumentNodeOrder.begin(), 
maDocumentNodeOrder.end(), index);
+            assert(it == maDocumentNodeOrder.end() || 
isInShapesTextFrame(xTextContent));
+            if (it == maDocumentNodeOrder.end())
+                maDocumentNodeOrder.push_back(index);
         }
         catch (css::beans::UnknownPropertyException&)
         {

Reply via email to