[Libreoffice-commits] core.git: Branch 'private/mst/sw_redlinehide_2' - 6 commits - sw/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Tue Aug 14 17:10:44 UTC 2018


 sw/source/core/layout/ssfrm.cxx  |    8 ++
 sw/source/core/layout/wsfrm.cxx  |    2 
 sw/source/core/text/redlnitr.cxx |   16 ++++-
 sw/source/core/text/txtfrm.cxx   |    7 +-
 sw/source/core/txtnode/ndtxt.cxx |  118 +++++++++++++++++++++++++++++++++++----
 sw/source/filter/xml/wrtxml.cxx  |    9 ++
 6 files changed, 144 insertions(+), 16 deletions(-)

New commits:
commit 14472006e5484ecaab3438b735bb3136112dcd94
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 14 19:07:27 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 14 19:08:47 2018 +0200

    RegisterToNode fix
    
    Change-Id: I9f02bebac4318db77baf0561409da880288a0a09

diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx
index b00851d7dd52..3a37ae92bc7f 100644
--- a/sw/source/core/layout/ssfrm.cxx
+++ b/sw/source/core/layout/ssfrm.cxx
@@ -443,8 +443,14 @@ SwContentFrame::~SwContentFrame()
 void SwTextFrame::RegisterToNode(SwTextNode & rNode)
 {
     assert(&rNode != GetDep());
+    assert(!m_pMergedPara
+        || (m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex())
+        || (rNode.GetIndex() + 1 == m_pMergedPara->pFirstNode->GetIndex()));
+    SwTextNode & rFirstNode(
+        (m_pMergedPara && m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex())
+            ? *m_pMergedPara->pFirstNode
+            : rNode);
     // sw_redlinehide: use New here, because the only caller also calls lcl_ChangeFootnoteRef
-    SwTextNode & rFirstNode(m_pMergedPara ? *m_pMergedPara->pFirstNode : rNode);
     m_pMergedPara = sw::CheckParaRedlineMerge(*this, rFirstNode, sw::FrameMode::New);
     if (!m_pMergedPara)
     {
commit ceb717ceee16d99b8f26fca7bfcadc5d1f22ae13
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 14 17:37:29 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 14 19:08:47 2018 +0200

    fix store flag in settings.xml too
    
    Change-Id: I0b715b5255505ef5c3c8053e45cddd1365dbb791

diff --git a/sw/source/filter/xml/wrtxml.cxx b/sw/source/filter/xml/wrtxml.cxx
index 3a6f976f42c3..4f7a8d4dc55c 100644
--- a/sw/source/filter/xml/wrtxml.cxx
+++ b/sw/source/filter/xml/wrtxml.cxx
@@ -412,8 +412,15 @@ ErrCode SwXMLWriter::Write_( const uno::Reference < task::XStatusIndicator >& xS
     nRedlineFlags = m_pDoc->getIDocumentRedlineAccess().GetRedlineFlags();
     nRedlineFlags &= ~RedlineFlags::ShowMask;
     nRedlineFlags |= RedlineFlags::ShowInsert;
-    if ( *o3tl::doAccess<bool>(aAny) )
+    if (getenv("SW_REDLINEHIDE"))
+    {
         nRedlineFlags |= RedlineFlags::ShowDelete;
+    }
+    else
+    {
+        if (*o3tl::doAccess<bool>(aAny))
+            nRedlineFlags |= RedlineFlags::ShowDelete;
+    }
     m_pDoc->getIDocumentRedlineAccess().SetRedlineFlags( nRedlineFlags );
 
     if (xStatusIndicator.is())
commit 9ca94c7a3efa7543b29e02d0803a1797970f89ea
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 14 15:58:35 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 14 19:08:47 2018 +0200

    sw_redlinehide_2: move SwInsText/SwDelText hint in CutImpl before attributes
    
    An unfortunate incident involving a footnote accessing its old anchor
    node's layout frame during InsertHint and the MapModelToViewPos needing
    to have a mapping for this index...
    
    6  SwTextFrame::MapModelToViewPos(SwPosition const&) const (this=0x8937760, rPos=SwPosition (node 41, offset 4)) at sw/source/core/text/txtfrm.cxx:1005
    7  SwTextFrame::GetFrameAtPos(SwPosition const&) (this=0x8937760, rPos=SwPosition (node 41, offset 4)) at sw/source/core/text/frmcrsr.cxx:153
    8  GetFrameOfModify(SwRootFrame const*, SwModify const&, SwFrameType, Point const*, SwPosition const*, bool) (pLayout=0x6a0a240, rMod=..., nFrameType=(SwFrameType::Txt | SwFrameType::NoTxt), pPoint=0x0, pPos=0x7ffcfa9d70a0, bCalcFrame=false) at sw/source/core/layout/frmtool.cxx:3517
    9  SwContentNode::getLayoutFrame(SwRootFrame const*, Point const*, SwPosition const*, bool) const (this=0x6a67e20, _pRoot=0x6a0a240, pPoint=0x0, pPos=0x7ffcfa9d70a0, bCalcFrame=false) at sw/source/core/docnode/node.cxx:1137
    10 SwFootnoteFrame::GetRefFromAttr() (this=0x8970a30) at sw/source/core/layout/ftnfrm.cxx:2839
    11 SwContentNode::DelFrames(SwRootFrame const*, bool) (this=0x897ead0, pLayout=0x0, fromDtor=false) at sw/source/core/docnode/node.cxx:1419
    12 SwTextNode::InsertHint(SwTextAttr*, SetAttrMode) (this=0x89ac890, pAttr=0x6a3ff60, nMode=(SetAttrMode::DONTREPLACE | SetAttrMode::NOTXTATRCHR)) at sw/source/core/txtnode/thints.cxx:1408
    13 SwTextNode::CutImpl(SwTextNode*, SwIndex const&, SwIndex const&, int, bool) (this=0x6a67e20, pDest=0x89ac890, rDestStart=SwIndex (offset 2), rStart=SwIndex (offset 0), nLen=3, bUpdate=false) at sw/source/core/txtnode/ndtxt.cxx:2374
    14 SwTextNode::CutText(SwTextNode*, SwIndex const&, int) (this=0x6a67e20, pDest=0x89ac890, rStart=SwIndex (offset 0), nLen=3) at sw/source/core/txtnode/ndtxt.cxx:2199
    15 SwTextNode::JoinNext() (this=0x89ac890) at sw/source/core/txtnode/ndtxt.cxx:812
    
    Change-Id: If0dc0f16eb124dc8a070b84684ee9ec9ab0dc70f

diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index d57b9b266a90..a77cfe42382e 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -2306,6 +2306,13 @@ void SwTextNode::CutImpl( SwTextNode * const pDest, const SwIndex & rDestStart,
         }
     }
 
+    // notify frames - before moving hints, because footnotes
+    // want to find their anchor text frame in the follow chain
+    SwInsText aInsHint( nDestStart, nLen );
+    pDest->ModifyNotification( nullptr, &aInsHint );
+    SwDelText aDelHint( nTextStartIdx, nLen );
+    ModifyNotification( nullptr, &aDelHint );
+
     // 2. move attributes
     // Iterate over attribute array until the start of the attribute
     // is behind the moved range
@@ -2441,12 +2448,6 @@ void SwTextNode::CutImpl( SwTextNode * const pDest, const SwIndex & rDestStart,
     CHECK_SWPHINTS(this);
 
     TryDeleteSwpHints();
-
-    // notify layout frames
-    SwInsText aInsHint( nDestStart, nLen );
-    pDest->ModifyNotification( nullptr, &aInsHint );
-    SwDelText aDelHint( nTextStartIdx, nLen );
-    ModifyNotification( nullptr, &aDelHint );
 }
 
 void SwTextNode::EraseText(const SwIndex &rIdx, const sal_Int32 nCount,
commit f5aea792e265375452578fd163ef3c3f6458643c
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 14 15:48:31 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 14 19:08:47 2018 +0200

    sw_redlinehide_2: fix SplitNode handling of merged frames
    
    The first branch is a bit easier, because it always moves the existing
    frame onto the first node of the split anyway; the second branch may or
    may not need to do that, but it has to move it just to be sure if it
    needs to move it, which is a bit annoying...
    
    Change-Id: Ib2fc69c2bd99dffa958f1620211ec657a8cc1be8

diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 6c7b07e4819b..d57b9b266a90 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -367,6 +367,7 @@ static void lcl_ChangeFootnoteRef( SwTextNode &rNode )
 SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
         std::function<void (SwTextNode *, sw::mark::RestoreMode)> const*const pContentIndexRestore)
 {
+    SwNode::Merge const eOldMergeFlag(GetRedlineMergeFlag());
     bool parentIsOutline = IsOutline();
 
     // create a node "in front" of me
@@ -480,6 +481,10 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
         {   // call before making frames and before RegisterToNode
             (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::NonFlys);
         }
+        if (eOldMergeFlag != SwNode::Merge::None)
+        {   // clear before making frames and before RegisterToNode
+            SetRedlineMergeFlag(SwNode::Merge::None);
+        }   // now RegisterToNode will set merge flags in both nodes properly!
 
         SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*this);
         for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
@@ -523,6 +528,7 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
         {
             MoveTextAttr_To_AttrSet();
         }
+        // in case there are frames, the RegisterToNode has set the merge flag
         pNode->MakeFramesForAdjacentContentNode(*this);
         lcl_ChangeFootnoteRef( *this );
         if (pContentIndexRestore)
@@ -585,15 +591,61 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
         }
 
         if (pContentIndexRestore)
-        {   // call before making frames
+        {   // call before making frames and before RegisterToNode
             (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::NonFlys);
         }
 
-        if ( HasWriterListeners() )
+        std::vector<SwTextFrame*> frames;
+        SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*this);
+        for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+        {
+            frames.push_back(pFrame);
+        }
+        bool bNonMerged(false);
+        bool bRecreateThis(false);
+        for (SwTextFrame * pFrame : frames)
+        {
+            // sw_redlinehide: for this to work properly with hidden nodes,
+            // the frame needs to listen on them too.
+            // also: have to check the frame; this->GetRedlineMergeFlag()
+            // is None in case there's a delete redline inside the paragraph,
+            // but that could still result in a merged frame after split...
+            if (auto const pMergedPara = pFrame->GetMergedPara())
+            {
+                // Can't special case this == First here - that could (if
+                // both nodes are still merged by redline) lead to
+                // duplicate frames on "this".
+                // Update the extents with new node; also inits merge flag,
+                // so the MakeFramesForAdjacentContentNode below respects it
+                pFrame->RegisterToNode(*pNode);
+                if (!pFrame->GetMergedPara() ||
+                    !pFrame->GetMergedPara()->listener.IsListeningTo(this))
+                {
+                    // it's no longer listening - need to recreate frame
+                    // (note this is idempotent, can be done once per frame)
+                    SetRedlineMergeFlag(SwNode::Merge::None);
+                    bRecreateThis = true;
+                }
+            }
+            else
+            {
+                bNonMerged = true;
+            }
+        }
+        assert(!(bNonMerged && bRecreateThis)); // 2 layouts not handled yet - maybe best to simply use the other branch then?
+        if (!frames.empty() && bNonMerged)
         {
+            // the existing frame on "this" should have been updated by Cut
             MakeFramesForAdjacentContentNode(*pNode);
+            lcl_ChangeFootnoteRef(*pNode);
+        }
+        else if (bRecreateThis)
+        {
+            assert(pNode->HasWriterListeners()); // was just moved there
+            pNode->MakeFramesForAdjacentContentNode(*this);
+            lcl_ChangeFootnoteRef(*this);
         }
-        lcl_ChangeFootnoteRef( *pNode );
+
         if (pContentIndexRestore)
         {   // call after making frames; listeners will take care of adding to the right frame
             (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::Flys);
@@ -601,6 +653,49 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
     }
 
     {
+        // First
+        // -> First,NonFirst
+        // -> First,Hidden
+        // -> None,First
+        // Hidden
+        // -> Hidden,Hidden (if still inside merge rl)
+        // -> NonFirst,First (if redline was split)
+        // NonFirst
+        // -> NonFirst,First (if split after end of "incoming" redline &
+        //                    before start of "outgoing" redline)
+        // -> NonFirst,None (if split after end of "incoming" redline)
+        // -> NonFirst,Hidden (if split after start of "outgoing" redline)
+        // -> Hidden, NonFirst (if split before end of "incoming" redline)
+        // None
+        // -> None,None
+        // -> First,NonFirst (if splitting inside a delete redline)
+        SwNode::Merge const eFirst(pNode->GetRedlineMergeFlag());
+        SwNode::Merge const eSecond(GetRedlineMergeFlag());
+        switch (eOldMergeFlag)
+        {
+            case Merge::First:
+                assert((eFirst == Merge::First && eSecond == Merge::NonFirst)
+                    || (eFirst == Merge::First && eSecond == Merge::Hidden)
+                    || (eFirst == Merge::None && eSecond == Merge::First));
+            break;
+            case Merge::Hidden:
+                assert((eFirst == Merge::Hidden && eSecond == Merge::Hidden)
+                    || (eFirst == Merge::NonFirst && eSecond == Merge::First));
+            break;
+            case Merge::NonFirst:
+                assert((eFirst == Merge::NonFirst && eSecond == Merge::First)
+                    || (eFirst == Merge::NonFirst && eSecond == Merge::None)
+                    || (eFirst == Merge::NonFirst && eSecond == Merge::Hidden)
+                    || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst));
+            break;
+            case Merge::None:
+                assert((eFirst == Merge::None && eSecond == Merge::None)
+                    || (eFirst == Merge::First && eSecond == Merge::NonFirst));
+            break;
+        }
+    }
+
+    {
         // Send Hint for PageDesc. This should be done in the Layout when
         // pasting the frames, but that causes other problems that look
         // expensive to solve.
commit 5d3d4854e4e263347c2d633c5cb9b3b6a3200a59
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 14 15:38:53 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 14 15:38:53 2018 +0200

    merge into "fix ordering of SplitNode usage of ContentIdxStore 2"
    
    Change-Id: Ia6639e6bb2864cf518267f38eb805468e8de443b

diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 4d797a3a8d44..6c7b07e4819b 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -526,7 +526,7 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
         pNode->MakeFramesForAdjacentContentNode(*this);
         lcl_ChangeFootnoteRef( *this );
         if (pContentIndexRestore)
-        {   // call after making frames
+        {   // call after making frames; listeners will take care of adding to the right frame
             (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::Flys);
         }
     }
@@ -595,7 +595,7 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
         }
         lcl_ChangeFootnoteRef( *pNode );
         if (pContentIndexRestore)
-        {   // call after making frames
+        {   // call after making frames; listeners will take care of adding to the right frame
             (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::Flys);
         }
     }
commit 89b5b33af5120ec32277e7324185f87eb4f91fd9
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 14 11:20:46 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Tue Aug 14 11:20:46 2018 +0200

    sw_redlinehide_2: let's have MergedPara listen on hidden nodes
    
    ... in particular all SwTextNodes on the same nodes-array nesting level
    as the first one; then UpdateMergedParaForInsert can handle insertions
    there.
    
    Change-Id: I59d12b87c1296c322ab1f21779240ec611919cb0

diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index b7cde56120e1..1d308a50e937 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4202,7 +4202,7 @@ static void UnHideRedlines(SwRootFrame & rLayout,
                 if (rLayout.IsHideRedlines())
                 {
                     assert(!pFrame->GetMergedPara() ||
-                        rNode.GetRedlineMergeFlag() == SwNode::Merge::NonFirst);
+                        !rNode.IsCreateFrameWhenHidingRedlines());
                     if (rNode.IsCreateFrameWhenHidingRedlines())
                     {
                         {
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index 09480c84852e..58e42190f278 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -89,9 +89,23 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode,
             {
                 pNode->SetRedlineMergeFlag(SwNode::Merge::First);
             } // else: was already set before
+            int nLevel(0);
             for (sal_uLong j = pNode->GetIndex() + 1; j < pEnd->nNode.GetIndex(); ++j)
             {
-                pNode->GetNodes()[j]->SetRedlineMergeFlag(SwNode::Merge::Hidden);
+                SwNode *const pTmp(pNode->GetNodes()[j]);
+                if (pTmp->IsStartNode())
+                {
+                    ++nLevel;
+                }
+                else if (pTmp->IsEndNode())
+                {
+                    --nLevel;
+                }
+                else if (nLevel == 0 && pTmp->IsTextNode())
+                {
+                    nodes.push_back(pTmp->GetTextNode());
+                }
+                pTmp->SetRedlineMergeFlag(SwNode::Merge::Hidden);
             }
             pNode = pEnd->nNode.GetNode().GetTextNode();
             assert(pNode);
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index f5aca5cc2c45..eba5ec65b400 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -724,6 +724,7 @@ namespace sw {
 void UpdateMergedParaForInsert(MergedPara & rMerged,
         SwTextNode const& rNode, sal_Int32 const nIndex, sal_Int32 const nLen)
 {
+    assert(nLen); // can 0 happen?
     assert(nIndex <= rNode.Len());
     assert(nIndex + nLen <= rNode.Len());
     assert(rMerged.pFirstNode->GetIndex() <= rNode.GetIndex() && rNode.GetIndex() <= rMerged.pLastNode->GetIndex());
@@ -754,7 +755,7 @@ void UpdateMergedParaForInsert(MergedPara & rMerged,
                 it->nEnd += nLen;
             }
         }
-        else if (bFoundNode)
+        else if (rNode.GetIndex() < it->pNode->GetIndex() || bFoundNode)
         {
             itInsert = it;
             break;
@@ -766,6 +767,10 @@ void UpdateMergedParaForInsert(MergedPara & rMerged,
     {   // must be in a gap
         rMerged.extents.emplace(itInsert, const_cast<SwTextNode*>(&rNode), nIndex, nIndex + nLen);
         text.insert(nTFIndex, rNode.GetText().copy(nIndex, nLen));
+        if (rNode.GetIndex() < rMerged.pParaPropsNode->GetIndex())
+        {   // text inserted before current para-props node
+            rMerged.pParaPropsNode = &rNode;
+        }
     }
     rMerged.mergedText = text.makeStringAndClear();
 }


More information about the Libreoffice-commits mailing list