sw/inc/list.hxx                         |   23 +++++++-
 sw/inc/ndtxt.hxx                        |   15 ++++-
 sw/qa/extras/layout/data/tdf115523.fodt |   42 +++++++++++++++
 sw/qa/extras/layout/layout2.cxx         |   27 ++++++++--
 sw/source/core/doc/list.cxx             |   13 +++-
 sw/source/core/text/txtfld.cxx          |   43 +++++++++++++---
 sw/source/core/txtnode/ndtxt.cxx        |   86 ++++++++++++++++++++++++--------
 7 files changed, 208 insertions(+), 41 deletions(-)

New commits:
commit 2413f213625253a9c2b1787b3b9fe859d724a9bd
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Thu Jun 23 12:11:22 2022 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Fri Jun 24 09:16:47 2022 +0200

    tdf#115523 sw_redlinenum: show correct, also original numbering
    
    in Show Changes mode, according to the name "Show Changes" and
    according to the interoperability requirements.
    
    Instead of the fake numbering which counted the deleted list items
    in Show Changes mode, e.g.:
    
    "3. This was the third originally, but now it's the second list item."
    
    now show the correct number followed by the original number within braces:
    
    "2.[3.] This was the third originally, but now it's the second list item."
    
    Note: the tabulators after the longer numbering are replaced with spaces
    to avoid messy indentation in Show Changes mode.
    
    New enum values for the alternative lists:
    
    SwListRedlineType::SHOW     - the original (fake) numbering in Show Changes 
mode
    SwListRedlineType::HIDDEN   - the original numbering of Hide Changes mode, 
and
                                  new numbering in Show Changes mode
    SwListRedlineType::ORIGTEXT - the new numbering of Show Changes mode to show
                                  the original numbering of the deleted or 
inserted list items
    
    Follow-up to commit c180c9447256588fe5e7991e06642883574760ae
    "sw_redlinehide_3: add second SwNodeNum to SwTextNode".
    
    Change-Id: Ieaca550561c5d5a7ac5d9defb9c7fa283d6aa674
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136313
    Tested-by: Jenkins
    Reviewed-by: László Németh <nem...@numbertext.org>

diff --git a/sw/inc/list.hxx b/sw/inc/list.hxx
index 14acb303ae07..d62d3a46ea86 100644
--- a/sw/inc/list.hxx
+++ b/sw/inc/list.hxx
@@ -29,6 +29,13 @@ class SwDoc;
 class SwNumRule;
 class SwNodes;
 
+enum class SwListRedlineType
+{
+    SHOW,
+    HIDDEN,
+    ORIGTEXT,
+};
+
 class SwList
 {
     public:
@@ -44,7 +51,7 @@ class SwList
         void SetDefaultListStyleName(OUString const&);
 
         void InsertListItem(SwNodeNum& rNodeNum,
-                            bool isHiddenRedlines,
+                            SwListRedlineType eRedlines,
                             const int nLevel,
                             const SwDoc& rDoc);
         static void RemoveListItem(SwNodeNum& rNodeNum, const SwDoc& rDoc);
@@ -84,10 +91,20 @@ class SwList
             /// the previous node on the same level.
             /// The nodes of pRootRLHidden are a subset of the nodes of pRoot.
             std::unique_ptr<SwNodeNum> pRootRLHidden;
+            /// Tree that is missing those nodes that are merged or hidden
+            /// by insert redlines; this is only used if there is a layout
+            /// that has IsHideRedlines() disabled, and the numbering of the
+            /// original text is also shown.
+            /// A third tree is needed because not only are the numbers in
+            /// the nodes different, the structure of the tree may be different
+            /// The nodes of pRootOrigText are a subset of the nodes of pRoot.
+            std::unique_ptr<SwNodeNum> pRootOrigText;
             /// top-level SwNodes section
             std::unique_ptr<SwPaM> pSection;
-            tListTreeForRange(std::unique_ptr<SwNodeNum> p1, 
std::unique_ptr<SwNodeNum> p2, std::unique_ptr<SwPaM> p3)
-                : pRoot(std::move(p1)), pRootRLHidden(std::move(p2)), 
pSection(std::move(p3)) {}
+            tListTreeForRange(std::unique_ptr<SwNodeNum> p1, 
std::unique_ptr<SwNodeNum> p2,
+                                                std::unique_ptr<SwNodeNum> p3, 
std::unique_ptr<SwPaM> p4)
+                : pRoot(std::move(p1)), pRootRLHidden(std::move(p2)),
+                                                pRootOrigText(std::move(p3)), 
pSection(std::move(p4)) {}
         };
         std::vector<tListTreeForRange> maListTrees;
 
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index a2ca71ea197c..8007beff59cd 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -25,6 +25,7 @@
 #include "IDocumentContentOperations.hxx"
 #include "SwNumberTreeTypes.hxx"
 #include "hintids.hxx"
+#include "list.hxx"
 #include "modeltoviewhelper.hxx"
 #include "ndhints.hxx"
 #include "node.hxx"
@@ -94,6 +95,7 @@ class SW_DLLPUBLIC SwTextNode final
 
     mutable std::unique_ptr<SwNodeNum> mpNodeNum;  ///< Numbering for this 
paragraph.
     mutable std::unique_ptr<SwNodeNum> mpNodeNumRLHidden; ///< Numbering for 
this paragraph (hidden redlines)
+    mutable std::unique_ptr<SwNodeNum> mpNodeNumOrig; ///< Numbering for this 
paragraph (before changes)
 
     OUString m_Text;
 
@@ -439,10 +441,12 @@ public:
      */
     SwNumRule *GetNumRule(bool bInParent = true) const;
 
-    const SwNodeNum* GetNum(SwRootFrame const* pLayout = nullptr) const;
+    const SwNodeNum* GetNum(SwRootFrame const* pLayout = nullptr,
+             SwListRedlineType eRedline = SwListRedlineType::SHOW) const;
     void DoNum(std::function<void (SwNodeNum &)> const&);
 
-    SwNumberTree::tNumberVector GetNumberVector(SwRootFrame const* pLayout = 
nullptr) const;
+    SwNumberTree::tNumberVector GetNumberVector(SwRootFrame const* pLayout = 
nullptr,
+            SwListRedlineType eRedline = SwListRedlineType::SHOW) const;
 
     /**
        Returns if this text node is an outline.
@@ -477,7 +481,8 @@ public:
     */
     OUString GetNumString( const bool _bInclPrefixAndSuffixStrings = true,
             const unsigned int _nRestrictToThisLevel = MAXLEVEL,
-            SwRootFrame const* pLayout = nullptr) const;
+            SwRootFrame const* pLayout = nullptr,
+            SwListRedlineType eRedline = SwListRedlineType::SHOW) const;
 
     /**
        Returns the additional indents of this text node and its numbering.
@@ -572,7 +577,7 @@ public:
         @return the actual list level of this text node, if it is a list item,
                -1 otherwise
     */
-    int GetActualListLevel() const;
+    int GetActualListLevel(SwListRedlineType eRedline = 
SwListRedlineType::SHOW) const;
 
     /**
        Returns outline level of this text node.
@@ -787,8 +792,10 @@ public:
 
     void AddToList();
     void AddToListRLHidden();
+    void AddToListOrig();
     void RemoveFromList();
     void RemoveFromListRLHidden();
+    void RemoveFromListOrig();
     bool IsInList() const;
 
     bool IsFirstOfNumRule(SwRootFrame const& rLayout) const;
diff --git a/sw/qa/extras/layout/data/tdf115523.fodt 
b/sw/qa/extras/layout/data/tdf115523.fodt
new file mode 100644
index 000000000000..a9989995642f
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf115523.fodt
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:config="urn:oas
 is:names:tc:opendocument:xmlns:config:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:xforms="http://www.w3.org/2002/xforms"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:rpt="http://openoffice.org/2005/report"; 
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
xmlns:xhtml="http://www.w3.org/1999/xhtml"; 
xmlns:grddl="http://www.w3.org/2003/g/data-view#"; 
xmlns:officeooo="http://openoffice.org/2009/office"; 
xmlns:tableooo="http://openoffice.org/2009/table"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:formx="urn:openoffice:names:
 experimental:ooxml-odf-interop:xmlns:form:1.0" 
xmlns:css3t="http://www.w3.org/TR/css3-text/"; office:version="1.2" 
office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:automatic-styles>
+  <style:style style:name="P1" style:family="paragraph" 
style:parent-style-name="Standard" style:list-style-name="L1">
+   <style:text-properties officeooo:rsid="001fa9e2" 
officeooo:paragraph-rsid="001fa9e2"/>
+  </style:style>
+  <text:list-style style:name="L1">
+   <text:list-level-style-number text:level="1" 
text:style-name="Numbering_20_Symbols" 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" 
text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" 
fo:margin-left="1.27cm"/>
+    </style:list-level-properties>
+   </text:list-level-style-number>
+  </text:list-style>
+ </office:automatic-styles>
+ <office:body>
+  <office:text>
+   <office:forms form:automatic-focus="false" form:apply-design-mode="false"/>
+   <text:tracked-changes text:track-changes="false">
+    <text:changed-region xml:id="ct93898744546976" text:id="ct93898744546976">
+     <text:deletion>
+      <office:change-info>
+       <dc:creator>Unknown Author</dc:creator>
+       <dc:date>2019-10-22T08:48:10</dc:date>
+      </office:change-info>
+     </text:deletion>
+    </text:changed-region>
+   </text:tracked-changes>
+   <text:list text:style-name="L1">
+    <text:list-item>
+     <text:p text:style-name="P2">It<text:change-start 
text:change-id="ct93898744546976"/></text:p>
+    </text:list-item>
+    <text:list-item>
+     <text:p text:style-name="P2"><text:change-end 
text:change-id="ct93898744546976"/>em</text:p>
+    </text:list-item>
+    <text:list-item>
+     <text:p text:style-name="P2">Item</text:p>
+    </text:list-item>
+   </text:list>
+  </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index a47642acfb8d..57e06f05553e 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -304,13 +304,34 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, 
testRedlineNumberInNumbering)
     // (and not COL_GREEN color of the tracked text movement, see 
testRedlineMoving) elements
     assertXPath(
         pXmlDoc,
-        "/metafile/push/push/push/textcolor[not(@color='#000000') and 
not(@color='#008000')]", 6);
+        "/metafile/push/push/push/textcolor[not(@color='#000000') and 
not(@color='#008000')]", 5);
 
     // tdf#145068 numbering shows changes in the associated list item, not the 
next one
     // This was 1 (black numbering of the first list item previously)
     assertXPath(pXmlDoc, "/metafile/push/push/push/font[4][@color='#000000']", 
0);
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineNumbering)
+{
+    SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf115523.fodt");
+    SwDocShell* pShell = pDoc->GetDocShell();
+
+    // Dump the rendering of the first page as an XML file.
+    std::shared_ptr<GDIMetaFile> xMetaFile = pShell->GetPreviewMetaFile();
+    MetafileXmlDump dumper;
+
+    xmlDocUniquePtr pXmlDoc = dumpAndParse(dumper, *xMetaFile);
+    CPPUNIT_ASSERT(pXmlDoc);
+
+    // Show the correct and the original line numbering instead of counting
+    // the deleted list items in Show Changes mode, as part of the list
+    assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[1]/text", 
"1.");
+    // This was "2." (deleted text node, now its text content is part of the 
first list item)
+    assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[3]/text", 
"[2.] ");
+    // This was "3." (now it's the second list item)
+    assertXPathContent(pXmlDoc, "/metafile/push/push/push/textarray[5]/text", 
"2.[3.] ");
+}
+
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineNumberInFootnote)
 {
     SwDoc* pDoc = createSwDoc(DATA_DIRECTORY, "tdf85610.fodt");
@@ -488,8 +509,8 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, 
testTdf145225_RedlineMovingWithBadInsertio
     // insert a tracked paragraph break in middle of the second list item, 
i.e. split it
     dispatchCommand(mxComponent, ".uno:GoToStartOfDoc", {});
     dispatchCommand(mxComponent, ".uno:TrackChanges", {});
-    pWrtShell->Down(false, 1);
-    pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+    // positionate the cursor in the middle of the second list item
+    pWrtShell->Right(CRSR_SKIP_CHARS, /*bSelect=*/false, 4, 
/*bBasicCall=*/false);
     pWrtShell->SplitNode(false);
     CPPUNIT_ASSERT_EQUAL(static_cast<SwRedlineTable::size_type>(1), 
pEditShell->GetRedlineCount());
 
diff --git a/sw/source/core/doc/list.cxx b/sw/source/core/doc/list.cxx
index 7965856519cc..9543e083d711 100644
--- a/sw/source/core/doc/list.cxx
+++ b/sw/source/core/doc/list.cxx
@@ -37,6 +37,7 @@ SwList::SwList( const OUString& sListId,
         SwPaM aPam( *pNode, *pNode->EndOfSectionNode() );
 
         maListTrees.emplace_back(
+            std::make_unique<SwNodeNum>( &rDefaultListStyle ),
             std::make_unique<SwNodeNum>( &rDefaultListStyle ),
             std::make_unique<SwNodeNum>( &rDefaultListStyle ),
             std::make_unique<SwPaM>( *(aPam.Start()), *(aPam.End()) ));
@@ -58,6 +59,7 @@ SwList::~SwList() COVERITY_NOEXCEPT_FALSE
     {
         SwNodeNum::HandleNumberTreeRootNodeDelete(*(rNumberTree.pRoot));
         
SwNodeNum::HandleNumberTreeRootNodeDelete(*(rNumberTree.pRootRLHidden));
+        
SwNodeNum::HandleNumberTreeRootNodeDelete(*(rNumberTree.pRootOrigText));
     }
 }
 
@@ -73,7 +75,7 @@ bool SwList::HasNodes() const
     return false;
 }
 
-void SwList::InsertListItem(SwNodeNum& rNodeNum, bool const isHiddenRedlines,
+void SwList::InsertListItem(SwNodeNum& rNodeNum, SwListRedlineType const 
eRedline,
                             const int nLevel, const SwDoc& rDoc)
 {
     const SwPosition aPosOfNodeNum( rNodeNum.GetPosition() );
@@ -88,9 +90,11 @@ void SwList::InsertListItem(SwNodeNum& rNodeNum, bool const 
isHiddenRedlines,
         if ( pRangeNodes == pNodesOfNodeNum &&
              *pStart <= aPosOfNodeNum && aPosOfNodeNum <= *pEnd)
         {
-            auto const& pRoot(isHiddenRedlines
+            auto const& pRoot(SwListRedlineType::HIDDEN == eRedline
                     ? rNumberTree.pRootRLHidden
-                    : rNumberTree.pRoot);
+                    : SwListRedlineType::SHOW == eRedline
+                            ? rNumberTree.pRoot
+                            : rNumberTree.pRootOrigText);
             pRoot->AddChild(&rNodeNum, nLevel, rDoc);
             break;
         }
@@ -108,6 +112,7 @@ void SwList::InvalidateListTree()
     {
         rNumberTree.pRoot->InvalidateTree();
         rNumberTree.pRootRLHidden->InvalidateTree();
+        rNumberTree.pRootOrigText->InvalidateTree();
     }
 }
 
@@ -117,6 +122,7 @@ void SwList::ValidateListTree(const SwDoc& rDoc)
     {
         rNumberTree.pRoot->NotifyInvalidChildren(rDoc);
         rNumberTree.pRootRLHidden->NotifyInvalidChildren(rDoc);
+        rNumberTree.pRootOrigText->NotifyInvalidChildren(rDoc);
     }
 }
 
@@ -162,6 +168,7 @@ void SwList::NotifyItemsOnListLevel( const int nLevel )
     {
         rNumberTree.pRoot->NotifyNodesOnListLevel( nLevel );
         rNumberTree.pRootRLHidden->NotifyNodesOnListLevel( nLevel );
+        rNumberTree.pRootOrigText->NotifyNodesOnListLevel( nLevel );
     }
 }
 
diff --git a/sw/source/core/text/txtfld.cxx b/sw/source/core/text/txtfld.cxx
index 06cb7388378e..f935e8d8ab93 100644
--- a/sw/source/core/text/txtfld.cxx
+++ b/sw/source/core/text/txtfld.cxx
@@ -563,15 +563,15 @@ static const SwRangeRedline* 
lcl_GetRedlineAtNodeInsertionOrDeletion( const SwTe
     return nullptr;
 }
 
-static void lcl_setRedlineAttr( SwTextFormatInfo &rInf, const SwTextNode& 
rTextNode, const std::unique_ptr<SwFont>& pNumFnt )
+static bool lcl_setRedlineAttr( SwTextFormatInfo &rInf, const SwTextNode& 
rTextNode, const std::unique_ptr<SwFont>& pNumFnt )
 {
     if ( rInf.GetVsh()->GetLayout()->IsHideRedlines() )
-        return;
+        return false;
 
     bool bIsMoved;
     const SwRangeRedline* pRedlineNum = 
lcl_GetRedlineAtNodeInsertionOrDeletion( rTextNode, bIsMoved );
     if (!pRedlineNum)
-        return;
+        return false;
 
     // moved text: dark green with double underline or strikethrough
     if ( bIsMoved )
@@ -581,7 +581,7 @@ static void lcl_setRedlineAttr( SwTextFormatInfo &rInf, 
const SwTextNode& rTextN
             pNumFnt->SetStrikeout(STRIKEOUT_DOUBLE);
         else
             pNumFnt->SetUnderline(LINESTYLE_DOUBLE);
-        return;
+        return true;
     }
 
     SwAttrPool& rPool = rInf.GetVsh()->GetDoc()->GetAttrPool();
@@ -602,6 +602,8 @@ static void lcl_setRedlineAttr( SwTextFormatInfo &rInf, 
const SwTextNode& rTextN
         pNumFnt->SetUnderline(pItem->GetLineStyle());
     if (const SvxCrossedOutItem* pItem = 
aSet.GetItemIfSet(RES_CHRATR_CROSSEDOUT))
         pNumFnt->SetStrikeout( pItem->GetStrikeout() );
+
+    return true;
 }
 
 SwNumberPortion *SwTextFormatter::NewNumberPortion( SwTextFormatInfo &rInf ) 
const
@@ -730,11 +732,35 @@ SwNumberPortion *SwTextFormatter::NewNumberPortion( 
SwTextFormatInfo &rInf ) con
             }
             else
             {
-                OUString aText( pTextNd->GetNumString(true, MAXLEVEL, 
m_pFrame->getRootFrame()) );
-                if ( !aText.isEmpty() )
+                // Show Changes mode shows the actual numbering 
(SwListRedlineType::HIDDEN) and
+                // the original one (SwListRedlineType::ORIGTEXT) instead of 
the fake numbering
+                // (SwListRedlineType::SHOW, which counts removed and inserted 
numbered paragraphs
+                // in a single list)
+                bool bHasHiddenNum = false;
+                OUString aText( pTextNd->GetNumString(true, MAXLEVEL, 
m_pFrame->getRootFrame(), SwListRedlineType::HIDDEN) );
+                const SwDoc& rDoc = pTextNd->GetDoc();
+                const SwRedlineTable& rTable = 
rDoc.getIDocumentRedlineAccess().GetRedlineTable();
+                if ( rTable.size() && 
!rInf.GetVsh()->GetLayout()->IsHideRedlines() )
                 {
-                    aText += pTextNd->GetLabelFollowedBy();
+                    OUString aHiddenText( pTextNd->GetNumString(true, 
MAXLEVEL, m_pFrame->getRootFrame(), SwListRedlineType::ORIGTEXT) );
+
+                    if ( !aText.isEmpty() || !aHiddenText.isEmpty() )
+                    {
+                        if (aText != aHiddenText && !aHiddenText.isEmpty())
+                        {
+                            bHasHiddenNum = true;
+                            // show also original number after the actual one 
enclosed in [ and ],
+                            // and replace tabulator with space to avoid messy 
indentation
+                            // resulted by the longer numbering, e.g. "1.[2.]" 
instead of "1.".
+                            aText = aText +  "[" + aHiddenText + "]"
+                                     + 
pTextNd->GetLabelFollowedBy().replaceAll("\t", " ");
+                        }
+                        else if (!aText.isEmpty())
+                            aText += pTextNd->GetLabelFollowedBy();
+                    }
                 }
+                else if (!aText.isEmpty())
+                    aText += pTextNd->GetLabelFollowedBy();
 
                 // Not just an optimization ...
                 // A number portion without text will be assigned a width of 0.
@@ -763,7 +789,8 @@ SwNumberPortion *SwTextFormatter::NewNumberPortion( 
SwTextFormatInfo &rInf ) con
 
                     checkApplyParagraphMarkFormatToNumbering(pNumFnt.get(), 
rInf, pIDSA, pFormat);
 
-                    lcl_setRedlineAttr( rInf, *pTextNd, pNumFnt );
+                    if ( !lcl_setRedlineAttr( rInf, *pTextNd, pNumFnt ) && 
bHasHiddenNum )
+                        pNumFnt->SetColor(NON_PRINTING_CHARACTER_COLOR);
 
                     // we do not allow a vertical font
                     pNumFnt->SetVertical( pNumFnt->GetOrientation(), 
m_pFrame->IsVertical() );
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 691c42e3c900..72cd894e045e 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -72,7 +72,6 @@
 #include <SwNodeNum.hxx>
 #include <svl/grabbagitem.hxx>
 #include <svl/intitem.hxx>
-#include <list.hxx>
 #include <sortedobjs.hxx>
 #include <calbck.hxx>
 #include <attrhint.hxx>
@@ -3160,24 +3159,24 @@ bool SwTextNode::HasBullet() const
 //i53420 added max outline parameter
 OUString SwTextNode::GetNumString( const bool _bInclPrefixAndSuffixStrings,
         const unsigned int _nRestrictToThisLevel,
-        SwRootFrame const*const pLayout) const
+        SwRootFrame const*const pLayout, SwListRedlineType eRedline) const
 {
     if (GetDoc().IsClipBoard() && m_oNumStringCache)
     {
         // #i111677# do not expand number strings in clipboard documents
         return *m_oNumStringCache;
     }
-    const SwNumRule* pRule = GetNum(pLayout) ? GetNum(pLayout)->GetNumRule() : 
nullptr;
+    const SwNumRule* pRule = GetNum(pLayout, eRedline) ? GetNum(pLayout, 
eRedline)->GetNumRule() : nullptr;
     if ( pRule &&
          IsCountedInList() )
     {
         SvxNumberType const& rNumberType(
-                pRule->Get( lcl_BoundListLevel(GetActualListLevel()) ) );
+                pRule->Get( lcl_BoundListLevel(GetActualListLevel(eRedline)) ) 
);
         if (rNumberType.IsTextFormat() ||
 
             (style::NumberingType::NUMBER_NONE == 
rNumberType.GetNumberingType()))
         {
-            return pRule->MakeNumString( GetNum(pLayout)->GetNumberVector(),
+            return pRule->MakeNumString( GetNum(pLayout, 
eRedline)->GetNumberVector(),
                                      _bInclPrefixAndSuffixStrings,
                                      _nRestrictToThisLevel,
                                      nullptr,
@@ -3992,11 +3991,13 @@ SwFormatColl* SwTextNode::ChgFormatColl( SwFormatColl 
*pNewColl )
     return pOldColl;
 }
 
-const SwNodeNum* SwTextNode::GetNum(SwRootFrame const*const pLayout) const
+const SwNodeNum* SwTextNode::GetNum(SwRootFrame const*const pLayout, 
SwListRedlineType eRedline) const
 {
     // invariant: it's only in list in Hide mode if it's in list in normal mode
     assert(mpNodeNum || !mpNodeNumRLHidden);
-    return pLayout && pLayout->IsHideRedlines() ? mpNodeNumRLHidden.get() : 
mpNodeNum.get();
+    return (pLayout && pLayout->IsHideRedlines()) || SwListRedlineType::HIDDEN 
== eRedline
+            ? mpNodeNumRLHidden.get()
+            : ( SwListRedlineType::ORIGTEXT == eRedline ? mpNodeNumOrig.get() 
: mpNodeNum.get() );
 }
 
 void SwTextNode::DoNum(std::function<void (SwNodeNum &)> const& rFunc)
@@ -4014,9 +4015,9 @@ void SwTextNode::DoNum(std::function<void (SwNodeNum &)> 
const& rFunc)
 }
 
 SwNumberTree::tNumberVector
-SwTextNode::GetNumberVector(SwRootFrame const*const pLayout) const
+SwTextNode::GetNumberVector(SwRootFrame const*const pLayout, SwListRedlineType 
eRedline) const
 {
-    if (SwNodeNum const*const pNum = GetNum(pLayout))
+    if (SwNodeNum const*const pNum = GetNum(pLayout, eRedline))
     {
         return pNum->GetNumberVector();
     }
@@ -4137,11 +4138,13 @@ int SwTextNode::GetAttrListLevel() const
     return nAttrListLevel;
 }
 
-int SwTextNode::GetActualListLevel() const
+int SwTextNode::GetActualListLevel(SwListRedlineType eRedline) const
 {
-    assert(!GetNum() || !mpNodeNumRLHidden || // must be in sync
-        GetNum()->GetLevelInListTree() == 
mpNodeNumRLHidden->GetLevelInListTree());
-    return GetNum() ? GetNum()->GetLevelInListTree() : -1;
+    assert(SwListRedlineType::SHOW != eRedline ||
+        !GetNum(nullptr, SwListRedlineType::SHOW) || !mpNodeNumRLHidden || // 
must be in sync
+        GetNum(nullptr, SwListRedlineType::SHOW)->GetLevelInListTree() ==
+                                                        
mpNodeNumRLHidden->GetLevelInListTree());
+    return GetNum(nullptr, eRedline) ? GetNum(nullptr, 
eRedline)->GetLevelInListTree() : -1;
 }
 
 void SwTextNode::SetListRestart( bool bRestart )
@@ -4318,10 +4321,30 @@ void SwTextNode::AddToList()
 
     assert(!mpNodeNum);
     mpNodeNum.reset(new SwNodeNum(this, false));
-    pList->InsertListItem(*mpNodeNum, false, GetAttrListLevel(), GetDoc());
+    pList->InsertListItem(*mpNodeNum, SwListRedlineType::SHOW, 
GetAttrListLevel(), GetDoc());
+
+    // set redline lists
+    bool bRecordChanges = GetDoc().GetDocShell() && 
GetDoc().GetDocShell()->IsChangeRecording();
+    if (!bRecordChanges || GetDoc().IsInXMLImport() || 
GetDoc().IsInWriterfilterImport() )
+    {
+        const SwRedlineTable& rRedTable = 
GetDoc().getIDocumentRedlineAccess().GetRedlineTable();
+        SwRedlineTable::size_type nRedlPos = 
GetDoc().getIDocumentRedlineAccess().GetRedlinePos(*this, RedlineType::Insert);
+        // paragraph start is not in a tracked insertion
+        if ( SwRedlineTable::npos == nRedlPos || GetIndex() <= 
rRedTable[nRedlPos]->Start()->nNode.GetNode().GetIndex() )
+        {
+            AddToListOrig();
+
+            SwRedlineTable::size_type nRedlPosDel = 
GetDoc().getIDocumentRedlineAccess().GetRedlinePos(*this, RedlineType::Delete);
+            if ( SwRedlineTable::npos == nRedlPosDel )
+                AddToListRLHidden();
+        }
+    }
+    else if ( bRecordChanges )
+        AddToListRLHidden();
+
     // iterate all frames & if there's one with hidden layout...
     SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> 
iter(*this);
-    for (SwTextFrame* pFrame = iter.First(); pFrame; pFrame = iter.Next())
+    for (SwTextFrame* pFrame = iter.First(); pFrame && !mpNodeNumRLHidden; 
pFrame = iter.Next())
     {
         if (pFrame->getRootFrame()->IsHideRedlines())
         {
@@ -4337,18 +4360,28 @@ void SwTextNode::AddToList()
 void SwTextNode::AddToListRLHidden()
 {
     if (mpNodeNumRLHidden)
-    {
-        assert(false);
-        OSL_FAIL( "<SwTextNode::AddToListRLHidden()> - the text node is 
already added to a list. Serious defect" );
         return;
-    }
 
     SwList *const pList(FindList(this));
     if (pList)
     {
         assert(!mpNodeNumRLHidden);
         mpNodeNumRLHidden.reset(new SwNodeNum(this, true));
-        pList->InsertListItem(*mpNodeNumRLHidden, true, GetAttrListLevel(), 
GetDoc());
+        pList->InsertListItem(*mpNodeNumRLHidden, SwListRedlineType::HIDDEN, 
GetAttrListLevel(), GetDoc());
+    }
+}
+
+void SwTextNode::AddToListOrig()
+{
+    if (mpNodeNumOrig)
+        return;
+
+    SwList *const pList(FindList(this));
+    if (pList)
+    {
+        assert(!mpNodeNumOrig);
+        mpNodeNumOrig.reset(new SwNodeNum(this, true));
+        pList->InsertListItem(*mpNodeNumOrig, SwListRedlineType::ORIGTEXT, 
GetAttrListLevel(), GetDoc());
     }
 }
 
@@ -4356,6 +4389,7 @@ void SwTextNode::RemoveFromList()
 {
     // sw_redlinehide: ensure it's removed from the other half too!
     RemoveFromListRLHidden();
+    RemoveFromListOrig();
     if ( IsInList() )
     {
         SwList::RemoveListItem(*mpNodeNum, GetDoc());
@@ -4377,6 +4411,18 @@ void SwTextNode::RemoveFromListRLHidden()
     }
 }
 
+void SwTextNode::RemoveFromListOrig()
+{
+    if (mpNodeNumOrig) // direct access because RemoveFromList doesn't have 
layout
+    {
+        assert(mpNodeNumOrig->GetParent() || !GetNodes().IsDocNodes());
+        SwList::RemoveListItem(*mpNodeNumOrig, GetDoc());
+        mpNodeNumOrig.reset();
+
+        SetWordCountDirty( true );
+    }
+}
+
 bool SwTextNode::IsInList() const
 {
     return GetNum() != nullptr && GetNum()->GetParent() != nullptr;

Reply via email to