sw_redlinehide_2: update frames on redline ops
When Delete redline is created, removed, accepted, rejected & undo/redo
of all of these, update all the text frames so they're merged or not,
as required.
Change-Id: I08aa6aea270a50d19f4bda0caf016870a42a8dd3
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 7b2b9aa..45010c2 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -44,6 +44,7 @@
#include <fmtcnct.hxx>
#include <SwStyleNameMapper.hxx>
#include <redline.hxx>
#include <txtfrm.hxx>
#include <unocrsr.hxx>
#include <mvsave.hxx>
#include <ndtxt.hxx>
@@ -3632,6 +3633,11 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa
m_rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_DELETE, rPam ), true );
m_rDoc.getIDocumentState().SetModified();
// sw_redlinehide: 2 reasons why this is needed:
// 1. it's the first redline in node => RedlineDelText was sent but ignored
// 2. redline spans multiple nodes => must merge text frames
sw::UpdateFramesForAddDeleteRedline(rPam);
if (pUndo)
{
m_rDoc.GetIDocumentUndoRedo().EndUndo( SwUndoId::EMPTY, nullptr );
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx
index 327ad96..631b35e 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -19,6 +19,7 @@
#include <DocumentRedlineManager.hxx>
#include <frmfmt.hxx>
#include <rootfrm.hxx>
#include <txtfrm.hxx>
#include <doc.hxx>
#include <IDocumentUndoRedo.hxx>
#include <IDocumentState.hxx>
@@ -113,6 +114,74 @@ using namespace com::sun::star;
#endif
namespace sw {
void UpdateFramesForAddDeleteRedline(SwPaM const& rPam)
{
SwTextNode *const pStartNode(rPam.Start()->nNode.GetNode().GetTextNode());
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)
{
SwTextNode & rFirstNode(pFrame->GetMergedPara()
? *pFrame->GetMergedPara()->pFirstNode
: *pStartNode);
assert(rFirstNode.GetIndex() <= pStartNode->GetIndex());
// clear old one first to avoid DelFrames confusing updates & asserts...
pFrame->SetMergedPara(nullptr);
pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
*pFrame, rFirstNode, sw::FrameMode::Existing));
}
}
void UpdateFramesForRemoveDeleteRedline(SwDoc & rDoc, SwPaM const& rPam)
{
if (rPam.GetPoint()->nNode != rPam.GetMark()->nNode)
{
// first, call CheckParaRedlineMerge on the first paragraph,
// to init flag on new merge range (if any) + 1st node post the merge
SwTextNode *const pStartNode(rPam.Start()->nNode.GetNode().GetTextNode());
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)
{
if (auto const pMergedPara = pFrame->GetMergedPara())
{
assert(pMergedPara->pFirstNode->GetIndex() <= pStartNode->GetIndex());
// clear old one first to avoid DelFrames confusing updates & asserts...
SwTextNode & rFirstNode(*pMergedPara->pFirstNode);
pFrame->SetMergedPara(nullptr);
pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
*pFrame, rFirstNode, sw::FrameMode::Existing));
}
}
// now start node until end of merge + 1 has proper flags; MakeFrames
// should pick up from the next node in need of frames by checking flags
if (!frames.empty())
{
SwNodeIndex const start(*pStartNode, +1);
SwNodeIndex const end(rPam.End()->nNode, +1); // end is exclusive
::MakeFrames(&rDoc, start, end);
}
}
}
} // namespace sw
namespace
{
inline bool IsPrevPos( const SwPosition & rPos1, const SwPosition & rPos2 )
@@ -294,6 +363,7 @@ namespace
{
bool bRet = true;
SwRangeRedline* pRedl = rArr[ rPos ];
SwDoc& rDoc = *pRedl->GetDoc();
SwPosition *pRStt = nullptr, *pREnd = nullptr;
SwComparePosition eCmp = SwComparePosition::Outside;
if( pSttRng && pEndRng )
@@ -309,7 +379,6 @@ namespace
{
case nsRedlineType_t::REDLINE_INSERT:
{
SwDoc& rDoc = *pRedl->GetDoc();
const SwPosition *pDelStt = nullptr, *pDelEnd = nullptr;
bool bDelRedl = false;
switch( eCmp )
@@ -390,6 +459,8 @@ namespace
{
SwRangeRedline* pNew = nullptr;
bool bCheck = false, bReplace = false;
SwPaM const updatePaM(pSttRng ? *pSttRng : *pRedl->Start(),
pEndRng ? *pEndRng : *pRedl->End());
switch( eCmp )
{
@@ -473,6 +544,8 @@ namespace
rArr.Remove( pRedl );
rArr.Insert( pRedl );
}
sw::UpdateFramesForRemoveDeleteRedline(rDoc, updatePaM);
}
break;
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 10bde32..a52bf0f 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -108,6 +108,9 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged,
void MoveDeletedPrevFrames(SwTextNode & rDeletedPrev, SwTextNode & rNode);
void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool bRecreateMerged);
void UpdateFramesForAddDeleteRedline(SwPaM const& rPam);
void UpdateFramesForRemoveDeleteRedline(SwDoc & rDoc, SwPaM const& rPam);
} // namespace sw
/// Represents the visualization of a paragraph. Typical upper is an
diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx
index 3866e55..a2eaa3f 100644
--- a/sw/source/core/undo/unredln.cxx
+++ b/sw/source/core/undo/unredln.cxx
@@ -25,6 +25,7 @@
#include <swundo.hxx>
#include <pam.hxx>
#include <ndtxt.hxx>
#include <txtfrm.hxx>
#include <UndoCore.hxx>
#include <UndoDelete.hxx>
#include <strings.hrc>
@@ -106,6 +107,17 @@ void SwUndoRedline::UndoImpl(::sw::UndoRedoContext & rContext)
}
SetPaM(rPam, true);
}
// update frames after calling SetSaveData
if (dynamic_cast<SwUndoRedlineDelete*>(this))
{
sw::UpdateFramesForRemoveDeleteRedline(rDoc, rPam);
}
else if (dynamic_cast<SwUndoAcceptRedline*>(this)
|| dynamic_cast<SwUndoRejectRedline*>(this))
{ // (can't check here if there's a delete redline being accepted)
sw::UpdateFramesForAddDeleteRedline(rPam);
}
}
void SwUndoRedline::RedoImpl(::sw::UndoRedoContext & rContext)
@@ -191,6 +203,7 @@ void SwUndoRedlineDelete::RedoRedlineImpl(SwDoc & rDoc, SwPaM & rPam)
{
rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline(*mpRedlData, rPam), false );
}
sw::UpdateFramesForAddDeleteRedline(rPam);
}
bool SwUndoRedlineDelete::CanGrouping( const SwUndoRedlineDelete& rNext )