[Libreoffice-commits] core.git: Branch 'distro/lhm/libreoffice-6-1+backports' - sw/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Tue Apr 7 08:50:26 UTC 2020


 sw/source/core/doc/DocumentContentOperationsManager.cxx |   43 ++++++++++++----
 sw/source/core/inc/txtfrm.hxx                           |    2 
 sw/source/core/layout/frmtool.cxx                       |   32 +++++++++++
 sw/source/core/undo/undel.cxx                           |   25 ---------
 4 files changed, 69 insertions(+), 33 deletions(-)

New commits:
commit 79b30c6354ec3b22050f3cc71a27a6a83105602e
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Apr 2 17:18:37 2020 +0200
Commit:     Michael Stahl <michael.stahl at cib.de>
CommitDate: Tue Apr 7 10:49:54 2020 +0200

    tdf#130685 sw_redlinehide: fix copying to position following redline
    
    In DocumentContentOperationsManager::CopyWithFlyInFly(), first
    CopyNodes() also creates all layout frames, then SaveRedlEndPosForRestore
    fixes the end position of all redlines that were moved by CopyNodes()
    (they were moved not by changing their position but by inserting
    new nodes before their end position).
    
    Of course this means that the layout frames are created with redlines
    that have only a temporary end position, and then things go wrong when
    the end positions are adjusted, so add something similar to
    SwUndoDelete::UndoImpl() to recreate the frames in CopyWithFlyInFly().
    
    This hit the assert:
    sw/source/core/text/redlnitr.cxx:94: std::unique_ptr<sw::MergedPara> sw::CheckParaRedlineMerge(SwTextFrame&, SwTextNode&, sw::FrameMode): Assertion `pNode != &rTextNode || &pStart->nNode.GetNode() == &rTextNode' failed.
    
    (regression from ... sw_redlinehide)
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91596
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 166b5010b402a41b192b1659093a25acf9065fd9)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91523
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    (cherry picked from commit f7aa951014c283bc629eaea14da2ca0d68f99431)
    
    Change-Id: I82e0f5b320cab201e762f58800f83e08f4f01048
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91760
    Tested-by: Michael Stahl <michael.stahl at cib.de>
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>

diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index e09e04597409..693b965b3b9b 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -46,6 +46,7 @@
 #include <redline.hxx>
 #include <txtfrm.hxx>
 #include <rootfrm.hxx>
+#include <frmtool.hxx>
 #include <unocrsr.hxx>
 #include <mvsave.hxx>
 #include <ndtxt.hxx>
@@ -3319,17 +3320,41 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
     assert(!pCopiedPaM || pCopiedPaM->first.End()->nNode == rRg.aEnd);
 
     SwDoc* pDest = rInsPos.GetNode().GetDoc();
+    SwNodeIndex aSavePos( rInsPos );
 
-    SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
-
-    SwNodeIndex aSavePos( rInsPos, -1 );
-    bool bEndIsEqualEndPos = rInsPos == rRg.aEnd;
-    m_rDoc.GetNodes().CopyNodes( rRg, rInsPos, bMakeNewFrames, true );
-    ++aSavePos;
-    if( bEndIsEqualEndPos )
-        const_cast<SwNodeIndex&>(rRg.aEnd) = aSavePos;
+    {
+        bool bEndIsEqualEndPos = rInsPos == rRg.aEnd;
+        --aSavePos;
+        SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
 
-    aRedlRest.Restore();
+        // insert behind the already copied start node
+        m_rDoc.GetNodes().CopyNodes( rRg, rInsPos, false, true );
+        aRedlRest.Restore();
+        if (bMakeNewFrames) // tdf#130685 only after aRedlRest
+        {   // recreate from previous node (could be merged now)
+            if (SwTextNode *const pNode = aSavePos.GetNode().GetTextNode())
+            {
+                sw::RecreateStartTextFrames(*pNode);
+            }
+        }
+        bool const isAtStartOfSection(aSavePos.GetNode().IsStartNode());
+        ++aSavePos;
+        if (bMakeNewFrames)
+        {
+            // it's possible that CheckParaRedlineMerge() deleted frames
+            // on rInsPos so have to include it, but it must not be included
+            // if it was the first node in the document so that MakeFrames()
+            // will find the existing (wasn't deleted) frame on it
+            SwNodeIndex const end(rInsPos,
+                    (rInsPos.GetNode().IsEndNode() || isAtStartOfSection)
+                    ? 0 : +1);
+            ::MakeFrames(pDest, aSavePos, end);
+        }
+        if (bEndIsEqualEndPos)
+        {
+            const_cast<SwNodeIndex&>(rRg.aEnd) = aSavePos;
+        }
+    }
 
 #if OSL_DEBUG_LEVEL > 0
     {
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index b1eb8d954f69..21037bb6d754 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -144,6 +144,8 @@ bool IsMarkHidden(SwRootFrame const& rLayout, ::sw::mark::IMark const& rMark);
 bool IsMarkHintHidden(SwRootFrame const& rLayout,
         SwTextNode const& rNode, SwTextAttrEnd const& rHint);
 
+void RecreateStartTextFrames(SwTextNode & rNode);
+
 } // namespace sw
 
 /// Represents the visualization of a paragraph. Typical upper is an
diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx
index 30e1ff3da845..594de9ec8b80 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -1292,6 +1292,38 @@ void AppendAllObjs(const SwFrameFormats* pTable, const SwFrame* pSib)
     }
 }
 
+namespace sw {
+
+void RecreateStartTextFrames(SwTextNode & rNode)
+{
+    std::vector<SwTextFrame*> frames;
+    SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rNode);
+    for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+    {
+        if (pFrame->getRootFrame()->IsHideRedlines())
+        {
+            frames.push_back(pFrame);
+        }
+    }
+    auto eMode(sw::FrameMode::Existing);
+    for (SwTextFrame * pFrame : frames)
+    {
+        // SplitNode could have moved the original frame to the start node
+        // & created a new one on end, or could have created new frame on
+        // start node... grab start node's frame and recreate MergedPara.
+        SwTextNode & rFirstNode(pFrame->GetMergedPara()
+            ? *pFrame->GetMergedPara()->pFirstNode
+            : rNode);
+        assert(rFirstNode.GetIndex() <= rNode.GetIndex());
+        pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
+                    *pFrame, rFirstNode, eMode));
+        eMode = sw::FrameMode::New; // Existing is not idempotent!
+        // note: this may or may not delete frames on the end node
+    }
+}
+
+} // namespace sw
+
 /** local method to set 'working' position for newly inserted frames
 
     OD 12.08.2003 #i17969#
diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx
index 29aed73a05bb..e6d9a4e2ba03 100644
--- a/sw/source/core/undo/undel.cxx
+++ b/sw/source/core/undo/undel.cxx
@@ -1089,30 +1089,7 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
         // frames
         SwTextNode *const pStartNode(aIdx.GetNodes()[nSttNode]->GetTextNode());
         assert(pStartNode);
-        std::vector<SwTextFrame*> frames;
-        SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pStartNode);
-        for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
-        {
-            if (pFrame->getRootFrame()->IsHideRedlines())
-            {
-                frames.push_back(pFrame);
-            }
-        }
-        auto eMode(sw::FrameMode::Existing);
-        for (SwTextFrame * pFrame : frames)
-        {
-            // SplitNode could have moved the original frame to the start node
-            // & created a new one on end, or could have created new frame on
-            // start node... grab start node's frame and recreate MergedPara.
-            SwTextNode & rFirstNode(pFrame->GetMergedPara()
-                ? *pFrame->GetMergedPara()->pFirstNode
-                : *pStartNode);
-            assert(rFirstNode.GetIndex() <= pStartNode->GetIndex());
-            pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
-                        *pFrame, rFirstNode, eMode));
-            eMode = sw::FrameMode::New; // Existing is not idempotent!
-            // note: this may or may not delete frames on the end node
-        }
+        sw::RecreateStartTextFrames(*pStartNode);
     }
 
     // create frames after SetSaveData has recreated redlines


More information about the Libreoffice-commits mailing list