diff options
author | Michael Stahl <Michael.Stahl@cib.de> | 2018-08-22 17:09:02 +0200 |
---|---|---|
committer | Michael Stahl <Michael.Stahl@cib.de> | 2018-09-19 10:18:29 +0200 |
commit | 723728cd358693b8f4bc9d913541aa4479f2bd48 (patch) | |
tree | 1ac75a662a46987301ea85d32957eb08f435ffd6 | |
parent | 41d8ca9686c7c184f586e99674b443c34bfd4f33 (diff) |
sw_redlinehide_2: SwUndoDelete
This is problematic because of the calls to SplitNode.
Ideally we'd want the SplitNode to create merged frames already, but
that doesn't seem to be easy to achieve; several problems with this are:
1. the redlines are only restored at the end of UndoImpl
2. even if we store another set of SwRedlineSaveDatas right before the
Join (while preventing the first SwRedlineSaveDatas from deleting
them), and restore them by passing a closure to SplitNode, there
are complaints about empty redlines, and also this case isn't
handled properly:
f<delete start>o<redline start>o
b<redline end>a<redline start>r
b<redline end>a<delete end>z
So instead, let SplitNode create whatever frames it does, and fix it up
at the end manually on the start node's frames.
This necessitates delaying the creation of the frames on the moved nodes
until the end too.
Change-Id: I8ba2967659cc2ddbe6f7c40e0447d79601498ed6
-rw-r--r-- | sw/source/core/txtnode/ndtxt.cxx | 5 | ||||
-rw-r--r-- | sw/source/core/undo/undel.cxx | 60 |
2 files changed, 59 insertions, 6 deletions
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx index 80a258f0fb38..f37ed9d8d543 100644 --- a/sw/source/core/txtnode/ndtxt.cxx +++ b/sw/source/core/txtnode/ndtxt.cxx @@ -765,7 +765,10 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos, break; case Merge::Hidden: assert((eFirst == Merge::Hidden && eSecond == Merge::Hidden) - || (eFirst == Merge::NonFirst && eSecond == Merge::First)); + || (eFirst == Merge::NonFirst && eSecond == Merge::First) + // next ones can happen temp. in UndoDelete :( + || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst) + || (eFirst == Merge::NonFirst && eSecond == Merge::None)); break; case Merge::NonFirst: assert((eFirst == Merge::NonFirst && eSecond == Merge::First) diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx index ec88086b7739..65acbbc63bbe 100644 --- a/sw/source/core/undo/undel.cxx +++ b/sw/source/core/undo/undel.cxx @@ -41,6 +41,9 @@ #include <sfx2/app.hxx> #include <fldbas.hxx> #include <fmtfld.hxx> +#include <frmtool.hxx> +#include <txtfrm.hxx> +#include <rootfrm.hxx> #include <strings.hrc> #include <vector> @@ -761,6 +764,7 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) SwNodeIndex aIdx(rDoc.GetNodes(), nCalcStt); SwNode* pInsNd = &aIdx.GetNode(); + SwNode* pMovedNode = nullptr; { // code block so that SwPosition is detached when deleting a Node SwPosition aPos( aIdx ); @@ -836,7 +840,6 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) ++aPos.nNode; } } - SwNode* pMovedNode = nullptr; if( m_nSectDiff ) { sal_uLong nMoveIndex = aPos.nNode.GetIndex(); @@ -864,7 +867,11 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) { SwNodeRange aRange( *m_pMvStt, 0, *m_pMvStt, m_nNode ); SwNodeIndex aCopyIndex( aPos.nNode, -1 ); - rDoc.GetUndoManager().GetUndoNodes().Copy_( aRange, aPos.nNode ); + rDoc.GetUndoManager().GetUndoNodes().Copy_(aRange, aPos.nNode, + // sw_redlinehide: delay creating frames: the flags on the + // nodes aren't necessarily up-to-date, and the redlines + // from m_pRedlSaveData aren't applied yet... + false); if( m_nReplaceDummy ) { @@ -887,9 +894,6 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) } } - if( pMovedNode ) - lcl_MakeAutoFrames(*rDoc.GetSpzFrameFormats(), pMovedNode->GetIndex()); - if( m_aSttStr ) { aPos.nNode = nSttNode - m_nNdDiff + ( m_bJoinNext ? 0 : m_nReplaceDummy ); @@ -956,6 +960,52 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) if( m_pRedlSaveData ) SetSaveData(rDoc, *m_pRedlSaveData); + if (m_aSttStr && (!m_bFromTableCopy || 0 != m_nNode)) + { + // only now do we have redlines in the document again; fix up the split + // 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); + } + } + 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, sw::FrameMode::Existing)); + // note: this may or may not delete frames on the end node + } + } + + // create frames after SetSaveData has recreated redlines + if (0 != m_nNode) + { + // don't include end node in the range: it may have been merged already + // by the start node, or it may be merged by one of the moved nodes, + // but if it isn't merged, its current frame(s) should be good... + SwNodeIndex const start(rDoc.GetNodes(), nSttNode + (m_bDelFullPara ? 0 : 1)); + SwNodeIndex const end(rDoc.GetNodes(), nEndNode); + ::MakeFrames(&rDoc, start, end); + } + + if (pMovedNode) + { // probably better do this after creating all frames + lcl_MakeAutoFrames(*rDoc.GetSpzFrameFormats(), pMovedNode->GetIndex()); + } + AddUndoRedoPaM(rContext, true); } |