summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2018-08-22 15:09:59 +0200
committerMichael Stahl <Michael.Stahl@cib.de>2018-09-19 10:18:28 +0200
commit41d8ca9686c7c184f586e99674b443c34bfd4f33 (patch)
tree348453a751ecb16557221a6825148726c861d010 /sw
parent0de06872ab8fcd2c0e8cd852f80adc9f0183ddca (diff)
sw_redlinehide_2: JoinPrev() may need to move frames on deleted ...
... prev. Node to the second node, if the two were merged before the Join. Change-Id: I047b6008c5f0bb6e79c63421a4dba09ba8cf3320
Diffstat (limited to 'sw')
-rw-r--r--sw/source/core/doc/docedt.cxx6
-rw-r--r--sw/source/core/inc/txtfrm.hxx5
-rw-r--r--sw/source/core/layout/ssfrm.cxx11
-rw-r--r--sw/source/core/txtnode/ndtxt.cxx46
4 files changed, 64 insertions, 4 deletions
diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx
index c8c66ee4fc11..0a01b1f4beeb 100644
--- a/sw/source/core/doc/docedt.cxx
+++ b/sw/source/core/doc/docedt.cxx
@@ -412,7 +412,13 @@ bool sw_JoinText( SwPaM& rPam, bool bJoinPrev )
rPam.GetBound( false ) = aAlphaPos;
}
// delete the Node, at last!
+ SwNode::Merge const eOldMergeFlag(pOldTextNd->GetRedlineMergeFlag());
+ if (eOldMergeFlag == SwNode::Merge::First)
+ {
+ sw::MoveDeletedPrevFrames(*pOldTextNd, *pTextNd);
+ }
pDoc->GetNodes().Delete( aOldIdx );
+ sw::CheckResetRedlineMergeFlag(*pTextNd, eOldMergeFlag == SwNode::Merge::NonFirst);
}
else
{
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 028c3605aa50..10bde328c903 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -105,6 +105,9 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged,
bool isRealDelete,
SwTextNode const& rNode, sal_Int32 nIndex, sal_Int32 nLen);
+void MoveDeletedPrevFrames(SwTextNode & rDeletedPrev, SwTextNode & rNode);
+void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool bRecreateMerged);
+
} // namespace sw
/// Represents the visualization of a paragraph. Typical upper is an
@@ -726,7 +729,7 @@ public:
static void repaintTextFrames( const SwTextNode& rNode );
- void RegisterToNode( SwTextNode& );
+ void RegisterToNode(SwTextNode &, bool isForceNodeAsFirst = false);
virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const override;
};
diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx
index 3a37ae92bc7f..99d187faa571 100644
--- a/sw/source/core/layout/ssfrm.cxx
+++ b/sw/source/core/layout/ssfrm.cxx
@@ -27,6 +27,7 @@
#include <fmtfsize.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/shaditem.hxx>
+#include <IDocumentRedlineAccess.hxx>
#include <fmtclds.hxx>
#include <viewimp.hxx>
#include <sortedobjs.hxx>
@@ -440,14 +441,20 @@ SwContentFrame::~SwContentFrame()
{
}
-void SwTextFrame::RegisterToNode(SwTextNode & rNode)
+void SwTextFrame::RegisterToNode(SwTextNode & rNode, bool const isForceNodeAsFirst)
{
+ if (isForceNodeAsFirst && m_pMergedPara)
+ { // nothing registered here, in particular no redlines
+ assert(m_pMergedPara->pFirstNode->GetIndex() + 1 == rNode.GetIndex());
+ assert(rNode.GetDoc()->getIDocumentRedlineAccess().GetRedlinePos(
+ *m_pMergedPara->pFirstNode, USHRT_MAX) == SwRedlineTable::npos);
+ }
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())
+ (!isForceNodeAsFirst && 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
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 38f5eff54ba1..80a258f0fb38 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -826,8 +826,45 @@ void SwTextNode::MoveTextAttr_To_AttrSet()
}
-namespace {
+namespace sw {
+/// if first node is deleted & second survives, then the first node's frame
+/// will be deleted too; prevent this by moving the frame to the second node
+/// if necessary.
+void MoveDeletedPrevFrames(SwTextNode & rDeletedPrev, SwTextNode & rNode)
+{
+ std::vector<SwTextFrame*> frames;
+ SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rDeletedPrev);
+ for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+ {
+ frames.push_back(pFrame);
+ }
+ {
+ auto frames2(frames);
+ SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIt(rNode);
+ for (SwTextFrame* pFrame = aIt.First(); pFrame; pFrame = aIt.Next())
+ {
+ auto const it(std::find(frames2.begin(), frames2.end(), pFrame));
+ assert(it != frames2.end());
+ frames2.erase(it);
+ }
+ assert(frames2.empty());
+ }
+ for (SwTextFrame *const pFrame : frames)
+ {
+ pFrame->RegisterToNode(rNode, true);
+ }
+}
+
+// typical Join:
+// None,Node->None
+// None,First->First
+// First,NonFirst->First
+// NonFirst,First->NonFirst
+// NonFirst,None->NonFirst
+
+/// if first node is First, its frames may need to be moved, never deleted.
+/// if first node is NonFirst, second node's own frames (First/None) must be deleted
void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool const bRecreateMerged)
{
if (bRecreateMerged)
@@ -846,6 +883,9 @@ void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool const bRecreateMerged)
assert(rFirstNode.GetIndex() <= rNode.GetIndex());
pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
*pFrame, rFirstNode, sw::FrameMode::Existing));
+ assert(pFrame->GetMergedPara());
+ assert(pFrame->GetMergedPara()->listener.IsListeningTo(&rNode));
+ assert(rNode.GetIndex() <= pFrame->GetMergedPara()->pLastNode->GetIndex());
}
}
else if (rNode.GetRedlineMergeFlag() != SwNode::Merge::None)
@@ -1051,6 +1091,10 @@ void SwTextNode::JoinPrev()
pDoc->CorrAbs( aIdx, SwPosition( *this ), nLen, true );
}
SwNode::Merge const eOldMergeFlag(pTextNode->GetRedlineMergeFlag());
+ if (eOldMergeFlag == SwNode::Merge::First)
+ {
+ sw::MoveDeletedPrevFrames(*pTextNode, *this);
+ }
rNds.Delete(aIdx);
SetWrong( pList, false );
SetGrammarCheck( pList3, false );