sw/qa/extras/layout/data/tdf169320-list_item_hidden_by_para_mark.fodt |   70 
++++++++++
 sw/qa/extras/layout/layout5.cxx                                       |   46 
++++++
 sw/source/core/text/redlnitr.cxx                                      |   10 -
 3 files changed, 122 insertions(+), 4 deletions(-)

New commits:
commit 9297d151ffb1bf59cc5f9153f55cae0edb5d9d99
Author:     Mike Kaganski <[email protected]>
AuthorDate: Fri Nov 7 20:01:37 2025 +0500
Commit:     Xisco Fauli <[email protected]>
CommitDate: Mon Nov 10 11:41:40 2025 +0100

    tdf#169320: Don't treat hidden-paragraph-mark as redline
    
    The "hidden paragraph mark" feature is implemented to match the
    feature of MS Word. In Writer, it is implemented using the same
    "merged paragraphs" machinery as redlines; and some code doesn't
    make distinction between the two.
    
    The code, that calculates a number string, uses three internal
    lists in SwTextNode to take redlines into account: mpNodeNum,
    mpNodeNumRLHidden, mpNodeNumOrig, which reflect the hierarchy
    effective for each mode. In "hidden redlines" mode, there are
    no removed elements in the respective list. Therefore, number
    string will be calculated from a different structure, and will
    differ from the string generated from the original structure.
    That is considered in SwTextFormatter::NewNumberPortion, which
    calls SwTextNode::GetNumString with SwListRedlineType::HIDDEN
    and SwListRedlineType::ORIGTEXT flags, compare the results, and
    add the original text in [] after the current text.
    
    Removal of elements hidden by redlines from mpNodeNumRLHidden
    happens in CheckParaRedlineMerge, which finds fidden nodes, and
    calls SwTextNode::RemoveFromListRLHidden for them. This change
    makes sure that it is not called, when a node is not hidden by
    a redline.
    
    Change-Id: I93bc2c47bfefca115c1cbe47e53c7b0f7a119e4b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193583
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <[email protected]>
    (cherry picked from commit 814a437a0dae0b5c07154844cd08563501807cb7)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193725
    Reviewed-by: Xisco Fauli <[email protected]>

diff --git 
a/sw/qa/extras/layout/data/tdf169320-list_item_hidden_by_para_mark.fodt 
b/sw/qa/extras/layout/data/tdf169320-list_item_hidden_by_para_mark.fodt
new file mode 100644
index 000000000000..276d350d694a
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf169320-list_item_hidden_by_para_mark.fodt
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" 
xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 xmlns:ooow="http://openoffice.org/2004/writer"; office:version="1.4" 
office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:settings>
+  <config:config-item-set config:name="ooo:view-settings">
+   <config:config-item config:name="ShowRedlineChanges" 
config:type="boolean">true</config:config-item>
+  </config:config-item-set>
+ </office:settings>
+ <office:styles>
+  <style:style style:name="Standard" style:family="paragraph" 
style:class="text"/>
+  <text:list-style style:name="MyList">
+   <text:list-level-style-number text:level="1" style:num-suffix="." 
style:num-format="1">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab" 
fo:text-indent="-15mm" fo:margin-left="15mm"/>
+    </style:list-level-properties>
+   </text:list-level-style-number>
+   <text:list-level-style-number text:level="2" style:num-format="1" 
text:display-levels="2">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab" 
fo:text-indent="-15mm" fo:margin-left="15mm"/>
+    </style:list-level-properties>
+   </text:list-level-style-number>
+  </text:list-style>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="P1" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:text-properties text:display="none"/>
+  </style:style>
+  <style:style style:name="T1" style:family="text">
+   <style:text-properties text:display="none"/>
+  </style:style>
+ </office:automatic-styles>
+ <office:body>
+  <office:text>
+   <text:tracked-changes text:track-changes="false">
+    <text:changed-region xml:id="ct1" text:id="ct1">
+     <text:format-change>
+      <office:change-info>
+       <dc:creator>Unknown Author</dc:creator>
+       <dc:date>2000-01-01T00:00:00</dc:date>
+      </office:change-info>
+     </text:format-change>
+    </text:changed-region>
+   </text:tracked-changes>
+   <text:list text:style-name="MyList">
+    <text:list-item>
+     <text:p>item 1<text:change-start text:change-id="ct1"/> added 
text<text:change-end text:change-id="ct1"/></text:p>
+    </text:list-item>
+    <text:list-item>
+     <text:p>item 2</text:p>
+    </text:list-item>
+    <text:list-item>
+     <text:p text:style-name="P1">item 3</text:p>
+     <text:list>
+      <text:list-item>
+       <text:p>subitem 3.1</text:p>
+      </text:list-item>
+     </text:list>
+    </text:list-item>
+    <text:list-item>
+     <text:p text:style-name="P1" loext:marker-style-name="T1">item 4</text:p>
+     <text:list>
+      <text:list-item>
+       <text:p>subitem 4.1</text:p>
+      </text:list-item>
+     </text:list>
+    </text:list-item>
+   </text:list>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/layout/layout5.cxx b/sw/qa/extras/layout/layout5.cxx
index 89b6fe9f07e1..632ce2baa2c5 100644
--- a/sw/qa/extras/layout/layout5.cxx
+++ b/sw/qa/extras/layout/layout5.cxx
@@ -2148,6 +2148,52 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf169158)
     assertXPath(pXmlDoc, "//page/anchored/fly/tab/row/cell/txt/infos/bounds", 
"top", u"2698");
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter5, testTdf169320)
+{
+    // A list with one item hidden by usual hidden text property, and another 
having a hidden
+    // paragraph mark:
+    createSwDoc("tdf169320-list_item_hidden_by_para_mark.fodt");
+    auto pXmlDoc = parseLayoutDump();
+    assertXPath(pXmlDoc, "//page", 1);
+    assertXPath(pXmlDoc, "//body/txt", 5);
+
+    // This node has a redline
+    CPPUNIT_ASSERT_GREATER(sal_Int32(200),
+                           getXPath(pXmlDoc, "//body/txt[1]/infos/bounds", 
"height").toInt32());
+    assertXPath(pXmlDoc, "//body/txt[1]/merged", 0);
+    assertXPathContent(pXmlDoc, "//body/txt[1]", u"item 1 added text");
+    assertXPath(pXmlDoc, "//body/txt[1]//SwFieldPortion", "expand", u"1.");
+
+    CPPUNIT_ASSERT_GREATER(sal_Int32(200),
+                           getXPath(pXmlDoc, "//body/txt[2]/infos/bounds", 
"height").toInt32());
+    assertXPath(pXmlDoc, "//body/txt[2]/merged", 0);
+    assertXPathContent(pXmlDoc, "//body/txt[2]", u"item 2");
+    assertXPath(pXmlDoc, "//body/txt[2]//SwFieldPortion", "expand", u"2.");
+
+    // Compare the layout structure of a hidden paragraph (txt[3]) to a merged 
one (txt[5]).
+
+    // This is hidden:
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
+                         getXPath(pXmlDoc, "//body/txt[3]/infos/bounds", 
"height").toInt32());
+    assertXPath(pXmlDoc, "//body/txt[3]/merged", 0);
+    assertXPathContent(pXmlDoc, "//body/txt[3]", u"item 3");
+    assertXPath(pXmlDoc, "//body/txt[3]//SwFieldPortion", 0);
+
+    CPPUNIT_ASSERT_GREATER(sal_Int32(200),
+                           getXPath(pXmlDoc, "//body/txt[4]/infos/bounds", 
"height").toInt32());
+    assertXPath(pXmlDoc, "//body/txt[4]/merged", 0);
+    assertXPathContent(pXmlDoc, "//body/txt[4]", u"subitem 3.1");
+    assertXPath(pXmlDoc, "//body/txt[4]//SwFieldPortion", "expand", u"3.1");
+
+    // This is merged:
+    CPPUNIT_ASSERT_GREATER(sal_Int32(200),
+                           getXPath(pXmlDoc, "//body/txt[5]/infos/bounds", 
"height").toInt32());
+    assertXPath(pXmlDoc, "//body/txt[5]/merged", 1);
+    assertXPathContent(pXmlDoc, "//body/txt[5]", u"item 4subitem 4.1");
+    // Without a fix, this was "3.2[4.1]":
+    assertXPath(pXmlDoc, "//body/txt[5]//SwFieldPortion", "expand", u"4.1");
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index 87564e2a3fbb..7719c96ffef0 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -487,10 +487,12 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & 
rTextNode,
     }
     for (auto const pTextNode : nodes)
     {
-        if (pTextNode != pRet->pParaPropsNode)
-        {
-            pTextNode->RemoveFromListRLHidden();
-        }
+        if (pTextNode == pRet->pParaPropsNode)
+            continue;
+        auto& rIDRA = pTextNode->getIDocumentRedlineAccess();
+        if (rIDRA.GetRedlinePos(*pTextNode, RedlineType::Delete) == 
SwRedlineTable::npos)
+            continue; // This is hidden by paragraph mark, not by a redline
+        pTextNode->RemoveFromListRLHidden();
     }
     if (eMode == FrameMode::Existing)
     {

Reply via email to