Blob Blame History Raw
From f3974a01283674f016ebd564652964302b1ab1e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
Date: Fri, 30 Jan 2015 15:34:30 +0000
Subject: [PATCH] During DocumentRedlineManager::SetRedlineMode the array
 becomes unsorted
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

so GetPos cannot be used safely, so pass down the known index
of the redline and propogate it everywhere the redline goes

This reverts

commit 36e158ce7a0effb130936ba4598a193102faa6a1
Author: Caolán McNamara <caolanm@redhat.com>
Date:   Mon Jan 19 12:09:17 2015 +0000

    if we change the keys we have to resort based on the new keys

which tried to keep the table sorted, but thats no use because
DocumentRedlineManager::SetRedlineMode loops over by index
so sorting the table during the process busts that.

Taking a copy of the entries and looping over that shows another
gadzillion problems.

So try this approach instead.

I imagine it should be possible to calculate the correct
current index of pRedl in DocumentRedlineManager::AppendRedline
but for now assume that we are sorted correctly at that
point and can use GetPos

(cherry picked from commit a5a20187c3a5e5956492f932c49501f9547e4915)

Conflicts:
	sw/source/core/doc/DocumentRedlineManager.cxx
	sw/source/core/doc/docredln.cxx
	sw/source/core/undo/unredln.cxx

Change-Id: If092dce185e3b36fd256db390132358cba155847
---
 sw/inc/docary.hxx               |  1 +
 sw/inc/redline.hxx              | 12 +++---
 sw/source/core/doc/docredln.cxx | 90 ++++++++++++++++++++---------------------
 sw/source/core/undo/unredln.cxx |  2 +-
 4 files changed, 51 insertions(+), 54 deletions(-)

diff --git a/sw/inc/docary.hxx b/sw/inc/docary.hxx
index 94f8229..34f22ed 100644
--- a/sw/inc/docary.hxx
+++ b/sw/inc/docary.hxx
@@ -195,6 +195,7 @@ public:
     using _SwRedlineTbl::size;
     using _SwRedlineTbl::operator[];
     using _SwRedlineTbl::empty;
+    using _SwRedlineTbl::Resort;
 };
 
 /// Table that holds 'extra' redlines, such as 'table row insert\delete', 'paragraph moves' etc...
diff --git a/sw/inc/redline.hxx b/sw/inc/redline.hxx
index ab1945b..b639063 100644
--- a/sw/inc/redline.hxx
+++ b/sw/inc/redline.hxx
@@ -190,8 +190,8 @@ class SW_DLLPUBLIC SwRangeRedline : public SwPaM
 
     void MoveToSection();
     void CopyToSection();
-    void DelCopyOfSection();
-    void MoveFromSection();
+    void DelCopyOfSection(size_t nMyPos);
+    void MoveFromSection(size_t nMyPos);
 
 public:
     SwRangeRedline( RedlineType_t eType, const SwPaM& rPam );
@@ -263,10 +263,10 @@ public:
     // hide the Del-Redlines via Copy and Delete.
     // Otherwise at Move the attribution would be handled incorrectly.
     // All other callers must always give 0.
-    void CallDisplayFunc( sal_uInt16 nLoop = 0 );
-    void Show( sal_uInt16 nLoop = 0 );
-    void Hide( sal_uInt16 nLoop = 0 );
-    void ShowOriginal( sal_uInt16 nLoop = 0 );
+    void CallDisplayFunc(sal_uInt16 nLoop, size_t nMyPos);
+    void Show(sal_uInt16 nLoop , size_t nMyPos);
+    void Hide(sal_uInt16 nLoop , size_t nMyPos);
+    void ShowOriginal(sal_uInt16 nLoop, size_t nMyPos);
 
     /// Calculates the intersection with text node number nNdIdx.
     void CalcStartEnd(sal_uLong nNdIdx, sal_Int32& rStart, sal_Int32& rEnd) const;
diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
index 8d3d704..fd2730e 100644
--- a/sw/source/core/doc/docredln.cxx
+++ b/sw/source/core/doc/docredln.cxx
@@ -157,7 +157,7 @@ void SwDoc::SetRedlineMode( RedlineMode_t eMode )
             bool bSaveInXMLImportFlag = IsInXMLImport();
             SetInXMLImport( false );
             // and then hide/display everything
-            void (SwRangeRedline::*pFnc)( sal_uInt16 ) = 0;
+            void (SwRangeRedline::*pFnc)(sal_uInt16, size_t) = 0;
 
             switch( nsRedlineMode_t::REDLINE_SHOW_MASK & eMode )
             {
@@ -179,10 +179,17 @@ void SwDoc::SetRedlineMode( RedlineMode_t eMode )
 
             _CHECK_REDLINE( this )
 
-            if( pFnc )
-                for( sal_uInt16 nLoop = 1; nLoop <= 2; ++nLoop )
-                    for( sal_uInt16 i = 0; i < mpRedlineTbl->size(); ++i )
-                        ((*mpRedlineTbl)[ i ]->*pFnc)( nLoop );
+            if (pFnc)
+            {
+                for (sal_uInt16 nLoop = 1; nLoop <= 2; ++nLoop)
+                    for (size_t i = 0; i < mpRedlineTbl->size(); ++i)
+                        ((*mpRedlineTbl)[i]->*pFnc)(nLoop, i);
+
+                //SwRangeRedline::MoveFromSection routinely changes
+                //the keys that mpRedlineTbl is sorted by
+                mpRedlineTbl->Resort();
+            }
+
             _CHECK_REDLINE( this )
             SetInXMLImport( bSaveInXMLImportFlag );
         }
@@ -705,7 +712,7 @@ bool SwDoc::AppendRedline( SwRangeRedline* pNewRedl, bool bCallDelete )
                                 // We insert temporarily so that pNew is
                                 // also dealt with when moving the indices.
                                 mpRedlineTbl->Insert( pNewRedl );
-                                pRedl->Show();
+                                pRedl->Show(0, mpRedlineTbl->GetPos(pRedl));
                                 mpRedlineTbl->Remove( pNewRedl );
                                 pRStt = pRedl->Start();
                                 pREnd = pRedl->End();
@@ -882,7 +889,7 @@ bool SwDoc::AppendRedline( SwRangeRedline* pNewRedl, bool bCallDelete )
                                 pRedl->PushData( *pNewRedl );
                                 delete pNewRedl, pNewRedl = 0;
                                 if( IsHideChanges( meRedlineMode ))
-                                    pRedl->Hide();
+                                    pRedl->Hide(0, mpRedlineTbl->GetPos(pRedl));
                                 bCompress = true;
                             }
                             break;
@@ -946,7 +953,7 @@ bool SwDoc::AppendRedline( SwRangeRedline* pNewRedl, bool bCallDelete )
                                     if( IsHideChanges( meRedlineMode ))
                                     {
                                         mpRedlineTbl->Insert( pNewRedl );
-                                        pRedl->Hide();
+                                        pRedl->Hide(0, mpRedlineTbl->GetPos(pRedl));
                                         mpRedlineTbl->Remove( pNewRedl );
                                     }
                                 }
@@ -974,7 +981,7 @@ bool SwDoc::AppendRedline( SwRangeRedline* pNewRedl, bool bCallDelete )
                                     if( IsHideChanges( meRedlineMode ))
                                     {
                                         mpRedlineTbl->Insert( pNewRedl );
-                                        pRedl->Hide();
+                                        pRedl->Hide(0, mpRedlineTbl->GetPos(pRedl));
                                         mpRedlineTbl->Remove( pNewRedl );
                                     }
                                 }
@@ -1255,7 +1262,7 @@ void SwDoc::CompressRedlines()
 {
     _CHECK_REDLINE( this )
 
-    void (SwRangeRedline::*pFnc)(sal_uInt16) = 0;
+    void (SwRangeRedline::*pFnc)(sal_uInt16, size_t) = 0;
     switch( nsRedlineMode_t::REDLINE_SHOW_MASK & meRedlineMode )
     {
     case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE:
@@ -1283,14 +1290,15 @@ void SwDoc::CompressRedlines()
             !pCurEnd->nNode.GetNode().StartOfSectionNode()->IsTableNode() )
         {
             // we then can merge them
-            pPrev->Show();
-            pCur->Show();
+            size_t nPrevIndex = n-1;
+            pPrev->Show(0, nPrevIndex);
+            pCur->Show(0, n);
 
             pPrev->SetEnd( *pCur->End() );
             mpRedlineTbl->DeleteAndDestroy( n );
             --n;
             if( pFnc )
-                (pPrev->*pFnc)(0);
+                (pPrev->*pFnc)(0, nPrevIndex);
         }
     }
     _CHECK_REDLINE( this )
@@ -2751,8 +2759,10 @@ bool SwRedlineTbl::Insert( SwRangeRedline* p, bool bIns )
     bool bRet = false;
     if( p->HasValidRange() )
     {
-        bRet = insert( p ).second;
-        p->CallDisplayFunc();
+        std::pair<_SwRedlineTbl::const_iterator, bool> rv = insert( p );
+        size_t nP = rv.first - begin();
+        bRet = rv.second;
+        p->CallDisplayFunc(0, nP);
     }
     else if( bIns )
         bRet = InsertWithValidRanges( p );
@@ -2771,7 +2781,7 @@ bool SwRedlineTbl::Insert( SwRangeRedline* p, sal_uInt16& rP, bool bIns )
         std::pair<_SwRedlineTbl::const_iterator, bool> rv = insert( p );
         rP = rv.first - begin();
         bRet = rv.second;
-        p->CallDisplayFunc();
+        p->CallDisplayFunc(0, rP);
     }
     else if( bIns )
         bRet = InsertWithValidRanges( p, &rP );
@@ -2873,7 +2883,7 @@ bool SwRedlineTbl::InsertWithValidRanges( SwRangeRedline* p, sal_uInt16* pInsPos
                 pNew->HasValidRange() &&
                 Insert( pNew, nInsPos ) )
             {
-                pNew->CallDisplayFunc();
+                pNew->CallDisplayFunc(0, nInsPos);
                 bAnyIns = true;
                 pNew = 0;
                 if( pInsPos && *pInsPos < nInsPos )
@@ -3382,23 +3392,23 @@ bool SwRangeRedline::HasValidRange() const
     return false;
 }
 
-void SwRangeRedline::CallDisplayFunc( sal_uInt16 nLoop )
+void SwRangeRedline::CallDisplayFunc(sal_uInt16 nLoop, size_t nMyPos)
 {
     switch( nsRedlineMode_t::REDLINE_SHOW_MASK & GetDoc()->GetRedlineMode() )
     {
     case nsRedlineMode_t::REDLINE_SHOW_INSERT | nsRedlineMode_t::REDLINE_SHOW_DELETE:
-        Show( nLoop );
+        Show(nLoop, nMyPos);
         break;
     case nsRedlineMode_t::REDLINE_SHOW_INSERT:
-        Hide( nLoop );
+        Hide(nLoop, nMyPos);
         break;
     case nsRedlineMode_t::REDLINE_SHOW_DELETE:
-        ShowOriginal( nLoop );
+        ShowOriginal(nLoop, nMyPos);
         break;
     }
 }
 
-void SwRangeRedline::Show( sal_uInt16 nLoop )
+void SwRangeRedline::Show(sal_uInt16 nLoop, size_t nMyPos)
 {
     if( 1 <= nLoop )
     {
@@ -3411,12 +3421,12 @@ void SwRangeRedline::Show( sal_uInt16 nLoop )
         {
         case nsRedlineType_t::REDLINE_INSERT:           // Content has been inserted
             bIsVisible = true;
-            MoveFromSection();
+            MoveFromSection(nMyPos);
             break;
 
         case nsRedlineType_t::REDLINE_DELETE:           // Content has been deleted
             bIsVisible = true;
-            MoveFromSection();
+            MoveFromSection(nMyPos);
             break;
 
         case nsRedlineType_t::REDLINE_FORMAT:           // Attributes have been applied
@@ -3430,7 +3440,7 @@ void SwRangeRedline::Show( sal_uInt16 nLoop )
     }
 }
 
-void SwRangeRedline::Hide( sal_uInt16 nLoop )
+void SwRangeRedline::Hide(sal_uInt16 nLoop, size_t nMyPos)
 {
     SwDoc* pDoc = GetDoc();
     RedlineMode_t eOld = pDoc->GetRedlineMode();
@@ -3442,7 +3452,7 @@ void SwRangeRedline::Hide( sal_uInt16 nLoop )
     case nsRedlineType_t::REDLINE_INSERT:           // Content has been inserted
         bIsVisible = true;
         if( 1 <= nLoop )
-            MoveFromSection();
+            MoveFromSection(nMyPos);
         break;
 
     case nsRedlineType_t::REDLINE_DELETE:           // Content has been deleted
@@ -3451,7 +3461,7 @@ void SwRangeRedline::Hide( sal_uInt16 nLoop )
         {
         case 0: MoveToSection();    break;
         case 1: CopyToSection();    break;
-        case 2: DelCopyOfSection(); break;
+        case 2: DelCopyOfSection(nMyPos); break;
         }
         break;
 
@@ -3466,7 +3476,7 @@ void SwRangeRedline::Hide( sal_uInt16 nLoop )
     pDoc->SetRedlineMode_intern( eOld );
 }
 
-void SwRangeRedline::ShowOriginal( sal_uInt16 nLoop )
+void SwRangeRedline::ShowOriginal(sal_uInt16 nLoop, size_t nMyPos)
 {
     SwDoc* pDoc = GetDoc();
     RedlineMode_t eOld = pDoc->GetRedlineMode();
@@ -3487,14 +3497,14 @@ void SwRangeRedline::ShowOriginal( sal_uInt16 nLoop )
         {
         case 0: MoveToSection();    break;
         case 1: CopyToSection();    break;
-        case 2: DelCopyOfSection(); break;
+        case 2: DelCopyOfSection(nMyPos); break;
         }
         break;
 
     case nsRedlineType_t::REDLINE_DELETE:           // Inhalt wurde eingefuegt
         bIsVisible = true;
         if( 1 <= nLoop )
-            MoveFromSection();
+            MoveFromSection(nMyPos);
         break;
 
     case nsRedlineType_t::REDLINE_FORMAT:           // Attributes have been applied
@@ -3725,7 +3735,7 @@ void SwRangeRedline::CopyToSection()
     }
 }
 
-void SwRangeRedline::DelCopyOfSection()
+void SwRangeRedline::DelCopyOfSection(size_t nMyPos)
 {
     if( pCntntSect )
     {
@@ -3772,7 +3782,7 @@ void SwRangeRedline::DelCopyOfSection()
                 // bDelLastPara condition above), only redlines before the
                 // current ones can be affected.
                 const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
-                sal_uInt16 n = rTbl.GetPos( this );
+                sal_uInt16 n = nMyPos;
                 OSL_ENSURE( n != USHRT_MAX, "How strange. We don't exist!" );
                 for( bool bBreak = false; !bBreak && n > 0; )
                 {
@@ -3813,16 +3823,13 @@ void SwRangeRedline::DelCopyOfSection()
     }
 }
 
-void SwRangeRedline::MoveFromSection()
+void SwRangeRedline::MoveFromSection(size_t nMyPos)
 {
     if( pCntntSect )
     {
         SwDoc* pDoc = GetDoc();
         const SwRedlineTbl& rTbl = pDoc->GetRedlineTbl();
         std::vector<SwPosition*> aBeforeArr, aBehindArr;
-        typedef std::map<sal_uInt16, SwRangeRedline*> IndexAndRange;
-        IndexAndRange aIndexAndRangeMap;
-        sal_uInt16 nMyPos = rTbl.GetPos( this );
         OSL_ENSURE( this, "this is not in the array?" );
         bool bBreak = false;
         sal_uInt16 n;
@@ -3834,14 +3841,12 @@ void SwRangeRedline::MoveFromSection()
             {
                 SwRangeRedline* pRedl = rTbl[n];
                 aBehindArr.push_back(&pRedl->GetBound(true));
-                aIndexAndRangeMap.insert(std::make_pair(n, pRedl));
                 bBreak = false;
             }
             if( rTbl[ n ]->GetBound(false) == *GetPoint() )
             {
                 SwRangeRedline* pRedl = rTbl[n];
                 aBehindArr.push_back(&pRedl->GetBound(false));
-                aIndexAndRangeMap.insert(std::make_pair(n, pRedl));
                 bBreak = false;
             }
         }
@@ -3853,14 +3858,12 @@ void SwRangeRedline::MoveFromSection()
             {
                 SwRangeRedline* pRedl = rTbl[n];
                 aBeforeArr.push_back(&pRedl->GetBound(true));
-                aIndexAndRangeMap.insert(std::make_pair(n, pRedl));
                 bBreak = false;
             }
             if( rTbl[ n ]->GetBound(false) == *GetPoint() )
             {
                 SwRangeRedline* pRedl = rTbl[n];
                 aBeforeArr.push_back(&pRedl->GetBound(false));
-                aIndexAndRangeMap.insert(std::make_pair(n, pRedl));
                 bBreak = false;
             }
         }
@@ -3935,13 +3938,6 @@ void SwRangeRedline::MoveFromSection()
             *aBeforeArr[ n ] = *Start();
         for( n = 0; n < aBehindArr.size(); ++n )
             *aBehindArr[ n ] = *End();
-        SwRedlineTbl& rResortTbl = const_cast<SwRedlineTbl&>(rTbl);
-        for (auto& a : aIndexAndRangeMap)
-        {
-            // re-insert
-            rResortTbl.Remove(a.first);
-            rResortTbl.Insert(a.second);
-        }
     }
     else
         InvalidateRange();
diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx
index 283bf30..48b80c7 100644
--- a/sw/source/core/undo/unredln.cxx
+++ b/sw/source/core/undo/unredln.cxx
@@ -243,7 +243,7 @@ void SwUndoRedlineSort::UndoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
         OSL_ENSURE( USHRT_MAX != nFnd && nFnd+1 < (sal_uInt16)rDoc.GetRedlineTbl().size(),
                     "could not find an Insert object" );
         ++nFnd;
-        rDoc.GetRedlineTbl()[nFnd]->Show( 1 );
+        rDoc.GetRedlineTbl()[nFnd]->Show(1, nFnd);
     }
 
     {
-- 
1.9.3