[Libreoffice-commits] core.git: 2 commits - sw/inc sw/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Fri Apr 26 13:57:10 UTC 2019


 sw/inc/undobj.hxx                  |    7 +-
 sw/source/core/doc/doc.cxx         |    2 
 sw/source/core/doc/doctxm.cxx      |  118 +++++++++++++++++++++----------------
 sw/source/core/inc/UndoSection.hxx |   22 ++++++
 sw/source/core/undo/undobj.cxx     |   20 +++---
 sw/source/core/undo/unsect.cxx     |   89 +++++++++++++++++++++++++++
 sw/source/uibase/index/toxmgr.cxx  |    1 
 sw/source/uibase/wrtsh/wrtsh2.cxx  |    9 --
 8 files changed, 196 insertions(+), 72 deletions(-)

New commits:
commit 4f0b568ef35353b276ae560fb43502b6f6b2bfdb
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Apr 25 18:31:08 2019 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Apr 26 15:55:29 2019 +0200

    tdf#38703 i#42807 sw: stop clearing Undo stack on ToX Update
    
    Reverts the "fix" for i#42807 from CWS swqcore08 since there's
    now SwUndoUpdateIndex.
    
    Change-Id: I6e71513c4a6da57bafcbc3d57b8fa113153d6c2d
    Reviewed-on: https://gerrit.libreoffice.org/71324
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <Michael.Stahl at cib.de>

diff --git a/sw/source/core/doc/doc.cxx b/sw/source/core/doc/doc.cxx
index de810a488f33..cee2e7745278 100644
--- a/sw/source/core/doc/doc.cxx
+++ b/sw/source/core/doc/doc.cxx
@@ -1733,8 +1733,6 @@ void SwDoc::ChangeTOX(SwTOXBase & rTOX, const SwTOXBase & rNew,
 {
     if (GetIDocumentUndoRedo().DoesUndo())
     {
-        GetIDocumentUndoRedo().DelAllUndoObj();
-
         GetIDocumentUndoRedo().AppendUndo(
             std::make_unique<SwUndoTOXChange>(this, &rTOX, rNew));
     }
diff --git a/sw/source/uibase/index/toxmgr.cxx b/sw/source/uibase/index/toxmgr.cxx
index afae269713fb..d2ed262f00b2 100644
--- a/sw/source/uibase/index/toxmgr.cxx
+++ b/sw/source/uibase/index/toxmgr.cxx
@@ -436,7 +436,6 @@ bool SwTOXMgr::UpdateOrInsertTOX(const SwTOXDescription& rDesc,
 
         if (pDoc->GetIDocumentUndoRedo().DoesUndo())
         {
-            pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
             pDoc->GetIDocumentUndoRedo().StartUndo(SwUndoId::TOXCHANGE, nullptr);
         }
 
diff --git a/sw/source/uibase/wrtsh/wrtsh2.cxx b/sw/source/uibase/wrtsh/wrtsh2.cxx
index 6fbd3d6203d9..9298ffb95494 100644
--- a/sw/source/uibase/wrtsh/wrtsh2.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh2.cxx
@@ -324,15 +324,6 @@ void SwWrtShell::UpdateTableOf(const SwTOXBase& rTOX, const SfxItemSet* pSet)
     if(CanInsert())
     {
         SwEditShell::UpdateTableOf(rTOX, pSet);
-
-        if (pSet == nullptr)
-        {
-            SwDoc *const pDoc_ = GetDoc();
-            if (pDoc_)
-            {
-                pDoc_->GetIDocumentUndoRedo().DelAllUndoObj();
-            }
-        }
     }
 }
 
commit 41df42a8dc758571dd7635c358a09bf412051649
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Apr 25 18:17:29 2019 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Apr 26 15:55:23 2019 +0200

    tdf#38703 i#42807 tdf#123313 sw: add Undo of ToX Update
    
    * SwTOXBaseSection::Update(): refactor this to *first* collect the info
      from the document (creating CrossRefHeadingBookmark as a side effect)
      and *then* do the node deletion/insertion of the ToX itself
    
    * add new SwUndoUpdateIndex class for the update itself; it does 3 of
      the 4 required steps, the last one is done by a SwUndoDelSection that
      is already created when the original title section is deleted
    
    * SwUndoInsSection::RedoImpl() for a ToX should not Update the ToX
      because that's the job of SwUndoUpdateIndex
    
    * SwUndoSaveSection::RestoreSection()/MoveFromUndoNds() need to create
      frames for the moved nodes; not sure why other users of
      RestoreSection() don't do this currently so add a flag
    
    * SwUndoSaveContent::MoveToUndoNds() should *always* delete frames;
      seriously, why would leaving frames alive ever be a good idea?
    
    * SwUndoSaveSection::SaveSection() should not delete the surrounding
      section node of the ToX, so add a flag to prevent it
    
    This fixes tdf#123313, the SwUndoInsBookmark are now appended at the
    right time.
    
    This should fix the crash in i#42807 properly.
    
    In order to fix these bugs, implementing the feature requested in
    tdf#38703 was necessary.
    
    Change-Id: Ia976a118eb81ca37b0c48678825a1f5cd4031789
    Reviewed-on: https://gerrit.libreoffice.org/71323
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <Michael.Stahl at cib.de>

diff --git a/sw/inc/undobj.hxx b/sw/inc/undobj.hxx
index 8610ab3d38a6..38cab61b0b58 100644
--- a/sw/inc/undobj.hxx
+++ b/sw/inc/undobj.hxx
@@ -163,7 +163,8 @@ protected:
                         sal_uLong* pEndNdIdx = nullptr );
     static void MoveFromUndoNds( SwDoc& rDoc, sal_uLong nNodeIdx,
                           SwPosition& rInsPos,
-                          const sal_uLong* pEndNdIdx = nullptr );
+                          const sal_uLong* pEndNdIdx = nullptr,
+                          bool bForceCreateFrames = false);
 
     // These two methods move the SPoint back/forth from PaM. With it
     // a range can be spanned for Undo/Redo. (In this case the SPoint
@@ -199,9 +200,9 @@ public:
     ~SwUndoSaveSection();
 
     void SaveSection( const SwNodeIndex& rSttIdx );
-    void SaveSection( const SwNodeRange& rRange );
+    void SaveSection(const SwNodeRange& rRange, bool bExpandNodes = true);
     void RestoreSection( SwDoc* pDoc, SwNodeIndex* pIdx, sal_uInt16 nSectType );
-    void RestoreSection( SwDoc* pDoc, const SwNodeIndex& rInsPos );
+    void RestoreSection(SwDoc* pDoc, const SwNodeIndex& rInsPos, bool bForceCreateFrames = false);
 
     const SwHistory* GetHistory() const { return pHistory.get(); }
           SwHistory* GetHistory()       { return pHistory.get(); }
diff --git a/sw/source/core/doc/doctxm.cxx b/sw/source/core/doc/doctxm.cxx
index d1dd7e59139d..13ca079c2804 100644
--- a/sw/source/core/doc/doctxm.cxx
+++ b/sw/source/core/doc/doctxm.cxx
@@ -51,6 +51,7 @@
 #include <txtfrm.hxx>
 #include <rootfrm.hxx>
 #include <UndoAttribute.hxx>
+#include <UndoSection.hxx>
 #include <swundo.hxx>
 #include <mdiexp.hxx>
 #include <docary.hxx>
@@ -870,8 +871,50 @@ void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
     SwNode2LayoutSaveUpperFrames aN2L(*pSectNd);
     const_cast<SwSectionNode*>(pSectNd)->DelFrames();
 
+    // This would be a good time to update the Numbering
+    pDoc->UpdateNumRule();
+
+    if( GetCreateType() & SwTOXElement::Mark )
+        UpdateMarks( aIntl, pOwnChapterNode, pLayout );
+
+    if( GetCreateType() & SwTOXElement::OutlineLevel )
+        UpdateOutline( pOwnChapterNode, pLayout );
+
+    if( GetCreateType() & SwTOXElement::Template )
+        UpdateTemplate( pOwnChapterNode, pLayout );
+
+    if( GetCreateType() & SwTOXElement::Ole ||
+            TOX_OBJECTS == SwTOXBase::GetType())
+        UpdateContent( SwTOXElement::Ole, pOwnChapterNode, pLayout );
+
+    if( GetCreateType() & SwTOXElement::Table ||
+            (TOX_TABLES == SwTOXBase::GetType() && IsFromObjectNames()) )
+        UpdateTable( pOwnChapterNode, pLayout );
+
+    if( GetCreateType() & SwTOXElement::Graphic ||
+        (TOX_ILLUSTRATIONS == SwTOXBase::GetType() && IsFromObjectNames()))
+        UpdateContent( SwTOXElement::Graphic, pOwnChapterNode, pLayout );
+
+    if( !GetSequenceName().isEmpty() && !IsFromObjectNames() &&
+        (TOX_TABLES == SwTOXBase::GetType() ||
+         TOX_ILLUSTRATIONS == SwTOXBase::GetType() ) )
+        UpdateSequence( pOwnChapterNode, pLayout );
+
+    if( GetCreateType() & SwTOXElement::Frame )
+        UpdateContent( SwTOXElement::Frame, pOwnChapterNode, pLayout );
+
+    if(TOX_AUTHORITIES == SwTOXBase::GetType())
+        UpdateAuthorities( aIntl, pLayout );
+
+    // Insert AlphaDelimitters if needed (just for keywords)
+    if( TOX_INDEX == SwTOXBase::GetType() &&
+        ( GetOptions() & SwTOIOptions::AlphaDelimiter ) )
+        InsertAlphaDelimitter( aIntl );
+
     // remove old content an insert one empty textnode (to hold the layout!)
     SwTextNode* pFirstEmptyNd;
+
+    SwUndoUpdateIndex * pUndo(nullptr);
     {
         pDoc->getIDocumentRedlineAccess().DeleteRedline( *pSectNd, true, USHRT_MAX );
 
@@ -886,6 +929,8 @@ void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
             const SwContentNode* pCNd = aNxtIdx.GetNode().GetContentNode();
             if( !pCNd )
                 pCNd = pDoc->GetNodes().GoNext( &aNxtIdx );
+            assert(pCNd != pFirstEmptyNd);
+            assert(pCNd->GetIndex() < pFirstEmptyNd->GetIndex());
             if( pCNd->HasSwAttrSet() )
             {
                 SfxItemSet aBrkSet( pDoc->GetAttrPool(), aBreakSetRange );
@@ -894,16 +939,28 @@ void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
                     pFirstEmptyNd->SetAttr( aBrkSet );
             }
         }
-        --aEndIdx;
-        SwPosition aPos( aEndIdx, SwIndex( pFirstEmptyNd, 0 ));
-        SwDoc::CorrAbs( aSttIdx, aEndIdx, aPos, true );
 
-        // delete flys in whole range including start node which requires
-        // giving the node before start node as Mark parameter, hence -1.
-        // (flys must be deleted because the anchor nodes are removed)
-        DelFlyInRange( SwNodeIndex(aSttIdx, -1), aEndIdx );
+        if (pDoc->GetIDocumentUndoRedo().DoesUndo())
+        {
+            // note: this will first append a SwUndoDelSection from the ctor...
+            pUndo = new SwUndoUpdateIndex(*this);
+            // tdf#123313 insert Undo *after* all CrossRefBookmark Undos have
+            // been inserted by the Update*() functions
+            pDoc->GetIDocumentUndoRedo().AppendUndo(std::unique_ptr<SwUndoUpdateIndex>(pUndo));
+        }
+        else
+        {
+            --aEndIdx;
+            SwPosition aPos( aEndIdx, SwIndex( pFirstEmptyNd, 0 ));
+            SwDoc::CorrAbs( aSttIdx, aEndIdx, aPos, true );
+
+            // delete flys in whole range including start node which requires
+            // giving the node before start node as Mark parameter, hence -1.
+            // (flys must be deleted because the anchor nodes are removed)
+            DelFlyInRange( SwNodeIndex(aSttIdx, -1), aEndIdx );
 
-        pDoc->GetNodes().Delete( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() );
+            pDoc->GetNodes().Delete( aSttIdx, aEndIdx.GetIndex() - aSttIdx.GetIndex() );
+        }
     }
 
     // insert title of TOX
@@ -922,47 +979,12 @@ void SwTOXBaseSection::Update(const SfxItemSet* pAttr,
         SwSectionFormat* pSectFormat = pDoc->MakeSectionFormat();
         pDoc->GetNodes().InsertTextSection(
                 aStt, *pSectFormat, headerData, nullptr, &aIdx, true, false);
-    }
-
-    // This would be a good time to update the Numbering
-    pDoc->UpdateNumRule();
-
-    if( GetCreateType() & SwTOXElement::Mark )
-        UpdateMarks( aIntl, pOwnChapterNode, pLayout );
-
-    if( GetCreateType() & SwTOXElement::OutlineLevel )
-        UpdateOutline( pOwnChapterNode, pLayout );
-
-    if( GetCreateType() & SwTOXElement::Template )
-        UpdateTemplate( pOwnChapterNode, pLayout );
-
-    if( GetCreateType() & SwTOXElement::Ole ||
-            TOX_OBJECTS == SwTOXBase::GetType())
-        UpdateContent( SwTOXElement::Ole, pOwnChapterNode, pLayout );
-
-    if( GetCreateType() & SwTOXElement::Table ||
-            (TOX_TABLES == SwTOXBase::GetType() && IsFromObjectNames()) )
-        UpdateTable( pOwnChapterNode, pLayout );
 
-    if( GetCreateType() & SwTOXElement::Graphic ||
-        (TOX_ILLUSTRATIONS == SwTOXBase::GetType() && IsFromObjectNames()))
-        UpdateContent( SwTOXElement::Graphic, pOwnChapterNode, pLayout );
-
-    if( !GetSequenceName().isEmpty() && !IsFromObjectNames() &&
-        (TOX_TABLES == SwTOXBase::GetType() ||
-         TOX_ILLUSTRATIONS == SwTOXBase::GetType() ) )
-        UpdateSequence( pOwnChapterNode, pLayout );
-
-    if( GetCreateType() & SwTOXElement::Frame )
-        UpdateContent( SwTOXElement::Frame, pOwnChapterNode, pLayout );
-
-    if(TOX_AUTHORITIES == SwTOXBase::GetType())
-        UpdateAuthorities( aIntl, pLayout );
-
-    // Insert AlphaDelimitters if needed (just for keywords)
-    if( TOX_INDEX == SwTOXBase::GetType() &&
-        ( GetOptions() & SwTOIOptions::AlphaDelimiter ) )
-        InsertAlphaDelimitter( aIntl );
+        if (pUndo)
+        {
+            pUndo->TitleSectionInserted(*pSectFormat);
+        }
+    }
 
     // Sort the List of all TOC Marks and TOC Sections
     std::vector<SwTextFormatColl*> aCollArr( GetTOXForm().GetFormMax(), nullptr );
diff --git a/sw/source/core/inc/UndoSection.hxx b/sw/source/core/inc/UndoSection.hxx
index ef8847dae1e0..985259728b64 100644
--- a/sw/source/core/inc/UndoSection.hxx
+++ b/sw/source/core/inc/UndoSection.hxx
@@ -70,6 +70,28 @@ std::unique_ptr<SwUndo> MakeUndoDelSection(SwSectionFormat const&);
 
 std::unique_ptr<SwUndo> MakeUndoUpdateSection(SwSectionFormat const&, bool const);
 
+
+class SwTOXBaseSection;
+class SwUndoDelSection;
+
+class SwUndoUpdateIndex : public SwUndo
+{
+private:
+    std::unique_ptr<SwUndoDelSection> m_pTitleSectionUpdated;
+    std::unique_ptr<SwUndoSaveSection> const m_pSaveSectionOriginal;
+    std::unique_ptr<SwUndoSaveSection> const m_pSaveSectionUpdated;
+    sal_uLong const m_nStartIndex;
+
+public:
+    SwUndoUpdateIndex(SwTOXBaseSection &);
+    virtual ~SwUndoUpdateIndex() override;
+
+    void TitleSectionInserted(SwSectionFormat & rSectionFormat);
+
+    virtual void UndoImpl(::sw::UndoRedoContext &) override;
+    virtual void RedoImpl(::sw::UndoRedoContext &) override;
+};
+
 #endif // INCLUDED_SW_SOURCE_CORE_INC_UNDOSECTION_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx
index 0d17568e3b09..a294c7e7e1c5 100644
--- a/sw/source/core/undo/undobj.cxx
+++ b/sw/source/core/undo/undobj.cxx
@@ -726,7 +726,7 @@ void SwUndoSaveContent::MoveToUndoNds( SwPaM& rPaM, SwNodeIndex* pNodeIdx,
     if( pCpyNd || pEndNdIdx )
     {
         SwNodeRange aRg( pStt->nNode, 0, pEnd->nNode, 1 );
-        rDoc.GetNodes().MoveNodes( aRg, rNds, aPos.nNode, false );
+        rDoc.GetNodes().MoveNodes( aRg, rNds, aPos.nNode, true );
         aPos.nContent = 0;
         --aPos.nNode;
     }
@@ -745,7 +745,7 @@ void SwUndoSaveContent::MoveToUndoNds( SwPaM& rPaM, SwNodeIndex* pNodeIdx,
 
 void SwUndoSaveContent::MoveFromUndoNds( SwDoc& rDoc, sal_uLong nNodeIdx,
                             SwPosition& rInsPos,
-                            const sal_uLong* pEndNdIdx )
+            const sal_uLong* pEndNdIdx, bool const bForceCreateFrames)
 {
     // here comes the recovery
     SwNodes & rNds = rDoc.GetUndoManager().GetUndoNodes();
@@ -793,7 +793,7 @@ void SwUndoSaveContent::MoveFromUndoNds( SwDoc& rDoc, sal_uLong nNodeIdx,
         SwNodeRange aRg( rNds, nNodeIdx, rNds, (pEndNdIdx
                         ? ((*pEndNdIdx) + 1)
                         : rNds.GetEndOfExtras().GetIndex() ) );
-        rNds.MoveNodes( aRg, rDoc.GetNodes(), rInsPos.nNode, nullptr == pEndNdIdx );
+        rNds.MoveNodes(aRg, rDoc.GetNodes(), rInsPos.nNode, nullptr == pEndNdIdx || bForceCreateFrames);
 
     }
     else {
@@ -1205,7 +1205,7 @@ void SwUndoSaveSection::SaveSection( const SwNodeIndex& rSttIdx )
 }
 
 void SwUndoSaveSection::SaveSection(
-    const SwNodeRange& rRange )
+    const SwNodeRange& rRange, bool const bExpandNodes)
 {
     SwPaM aPam( rRange.aStart, rRange.aEnd );
 
@@ -1231,8 +1231,11 @@ void SwUndoSaveSection::SaveSection(
 
     nStartPos = rRange.aStart.GetIndex();
 
-    --aPam.GetPoint()->nNode;
-    ++aPam.GetMark()->nNode;
+    if (bExpandNodes)
+    {
+        --aPam.GetPoint()->nNode;
+        ++aPam.GetMark()->nNode;
+    }
 
     SwContentNode* pCNd = aPam.GetContentNode( false );
     if( pCNd )
@@ -1266,13 +1269,14 @@ void SwUndoSaveSection::RestoreSection( SwDoc* pDoc, SwNodeIndex* pIdx,
     }
 }
 
-void SwUndoSaveSection::RestoreSection( SwDoc* pDoc, const SwNodeIndex& rInsPos )
+void SwUndoSaveSection::RestoreSection(
+        SwDoc *const pDoc, const SwNodeIndex& rInsPos, bool bForceCreateFrames)
 {
     if( ULONG_MAX != nStartPos )        // was there any content?
     {
         SwPosition aInsPos( rInsPos );
         sal_uLong nEnd = m_pMovedStart->GetIndex() + nMvLen - 1;
-        MoveFromUndoNds(*pDoc, m_pMovedStart->GetIndex(), aInsPos, &nEnd);
+        MoveFromUndoNds(*pDoc, m_pMovedStart->GetIndex(), aInsPos, &nEnd, bForceCreateFrames);
 
         // destroy indices again, content was deleted from UndoNodes array
         m_pMovedStart.reset();
diff --git a/sw/source/core/undo/unsect.cxx b/sw/source/core/undo/unsect.cxx
index f449639a7937..ef84c67a138f 100644
--- a/sw/source/core/undo/unsect.cxx
+++ b/sw/source/core/undo/unsect.cxx
@@ -29,6 +29,8 @@
 #include <IDocumentRedlineAccess.hxx>
 #include <IDocumentFieldsAccess.hxx>
 #include <IDocumentLayoutAccess.hxx>
+#include <IDocumentStylePoolAccess.hxx>
+#include <poolfmt.hxx>
 #include <docary.hxx>
 #include <swundo.hxx>
 #include <pam.hxx>
@@ -204,7 +206,8 @@ void SwUndoInsSection::RedoImpl(::sw::UndoRedoContext & rContext)
             pLayout = pLayoutToReset;
         }
         pUpdateTOX = rDoc.InsertTableOf( *rPam.GetPoint(),
-            *m_pTOXBase->first, m_pAttrSet.get(), true, pLayout);
+            // don't expand: will be done by SwUndoUpdateIndex::RedoImpl()
+            *m_pTOXBase->first, m_pAttrSet.get(), false, pLayout);
     }
     else
     {
@@ -507,4 +510,88 @@ void SwUndoUpdateSection::RedoImpl(::sw::UndoRedoContext & rContext)
     UndoImpl(rContext);
 }
 
+
+SwUndoUpdateIndex::SwUndoUpdateIndex(SwTOXBaseSection & rTOX)
+    : SwUndo(SwUndoId::INSSECTION, rTOX.GetFormat()->GetDoc())
+    , m_pSaveSectionOriginal(new SwUndoSaveSection)
+    , m_pSaveSectionUpdated(new SwUndoSaveSection)
+    , m_nStartIndex(rTOX.GetFormat()->GetSectionNode()->GetIndex() + 1)
+{
+    SwDoc & rDoc(*rTOX.GetFormat()->GetDoc());
+    assert(rDoc.GetNodes()[m_nStartIndex-1]->IsSectionNode());
+    assert(rDoc.GetNodes()[rDoc.GetNodes()[m_nStartIndex]->EndOfSectionIndex()-1]->IsTextNode()); // -1 for extra empty node
+    // note: title is optional
+    assert(rDoc.GetNodes()[m_nStartIndex]->IsTextNode()
+        || rDoc.GetNodes()[m_nStartIndex]->IsSectionNode());
+    SwNodeIndex const first(rDoc.GetNodes(), m_nStartIndex);
+    if (first.GetNode().IsSectionNode())
+    {
+        SwSectionFormat & rSectionFormat(*first.GetNode().GetSectionNode()->GetSection().GetFormat());
+        // note: DelSectionFormat will create & append SwUndoDelSection!
+        rDoc.DelSectionFormat(& rSectionFormat); // remove inner section nodes
+    }
+    assert(first.GetNode().IsTextNode()); // invariant: ToX section is *never* empty
+    SwNodeIndex const last(rDoc.GetNodes(), rDoc.GetNodes()[m_nStartIndex]->EndOfSectionIndex() - 2); // skip empty node
+    assert(last.GetNode().IsTextNode());
+    m_pSaveSectionOriginal->SaveSection(SwNodeRange(first, last), false);
+}
+
+SwUndoUpdateIndex::~SwUndoUpdateIndex() = default;
+
+void SwUndoUpdateIndex::TitleSectionInserted(SwSectionFormat & rFormat)
+{
+    SwNodeIndex const tmp(rFormat.GetDoc()->GetNodes(), m_nStartIndex); // title inserted before empty node
+    assert(tmp.GetNode().IsSectionNode());
+    assert(tmp.GetNode().GetSectionNode()->GetSection().GetFormat() == &rFormat);
+    m_pTitleSectionUpdated.reset(static_cast<SwUndoDelSection*>(MakeUndoDelSection(rFormat).release()));
+}
+
+void SwUndoUpdateIndex::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+    SwDoc & rDoc(rContext.GetDoc());
+    if (m_pTitleSectionUpdated)
+    {
+        m_pTitleSectionUpdated->RedoImpl(rContext);
+    }
+    SwNodeIndex const first(rDoc.GetNodes(), m_nStartIndex);
+    assert(first.GetNode().IsTextNode()); // invariant: ToX section is *never* empty
+    SwNodeIndex const last(rDoc.GetNodes(), rDoc.GetNodes()[m_nStartIndex]->EndOfSectionIndex() - 1);
+    assert(last.GetNode().IsTextNode());
+    // dummy node so that SaveSection doesn't remove ToX section...
+    SwTextNode *const pDeletionPrevention = rDoc.GetNodes().MakeTextNode(
+        SwNodeIndex(*rDoc.GetNodes()[m_nStartIndex]->EndOfSectionNode()),
+        rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_TEXT));
+    m_pSaveSectionUpdated->SaveSection(SwNodeRange(first, last), false);
+    m_pSaveSectionOriginal->RestoreSection(&rDoc, first, true);
+    // delete before restoring nested undo, so its node indexes match
+    SwNodeIndex const del(*pDeletionPrevention);
+    SwDoc::CorrAbs(del, del, SwPosition(SwNodeIndex(*rDoc.GetNodes()[m_nStartIndex]->EndOfSectionNode())), true);
+    rDoc.GetNodes().Delete(del);
+    // original title section will be restored by next Undo, see ctor!
+}
+
+void SwUndoUpdateIndex::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+    SwDoc & rDoc(rContext.GetDoc());
+    // original title section was deleted by previous Undo, see ctor!
+    SwNodeIndex const first(rDoc.GetNodes(), m_nStartIndex);
+    assert(first.GetNode().IsTextNode()); // invariant: ToX section is *never* empty
+    SwNodeIndex const last(rDoc.GetNodes(), rDoc.GetNodes()[m_nStartIndex]->EndOfSectionIndex() - 1);
+    assert(last.GetNode().IsTextNode());
+    // dummy node so that SaveSection doesn't remove ToX section...
+    SwTextNode *const pDeletionPrevention = rDoc.GetNodes().MakeTextNode(
+        SwNodeIndex(*rDoc.GetNodes()[m_nStartIndex]->EndOfSectionNode()),
+        rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_TEXT));
+    m_pSaveSectionOriginal->SaveSection(SwNodeRange(first, last), false);
+    m_pSaveSectionUpdated->RestoreSection(&rDoc, first, true);
+    // delete before restoring nested undo, so its node indexes match
+    SwNodeIndex const del(*pDeletionPrevention);
+    SwDoc::CorrAbs(del, del, SwPosition(SwNodeIndex(*rDoc.GetNodes()[m_nStartIndex]->EndOfSectionNode())), true);
+    rDoc.GetNodes().Delete(del);
+    if (m_pTitleSectionUpdated)
+    {
+        m_pTitleSectionUpdated->UndoImpl(rContext);
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list