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) {
