Kaydet (Commit) 905541a6 authored tarafından Michael Stahl's avatar Michael Stahl

sw_redlinehide_2: handle delete-without-redline inside of redline

The problem is that the SwInsText/SwDelText do not transfer the
"deleted-ness" of the text from one node to the other in the
SwTextFrame, so add a new hint that is sent after SwInsText & before
SwDelText to move the info that is in the extents vector.

Change-Id: I32d8dbe52a18556d8dc2c50a47246a6600fdb355
üst aa8caf09
......@@ -31,6 +31,7 @@ class SwNodes;
class SwPageFrame;
class SwFrame;
class SwHistory;
class SwTextNode;
// Base class for all Message-Hints:
// "Overhead" of SfxPoolItem is handled here
......@@ -95,6 +96,18 @@ public:
namespace sw {
/// text is moved into pDestNode
class MoveText : public SfxHint
{
public:
SwTextNode * pDestNode;
sal_Int32 nDestStart;
sal_Int32 nSourceStart;
sal_Int32 nLen;
MoveText(SwTextNode *pD, sal_Int32 nD, sal_Int32 nS, sal_Int32 nL);
};
/// new delete redline is created
class RedlineDelText : public SfxHint
{
......
......@@ -48,6 +48,11 @@ SwDelText::SwDelText( sal_Int32 nS, sal_Int32 nL )
namespace sw {
MoveText::MoveText(SwTextNode *const pD, sal_Int32 const nD, sal_Int32 const nS, sal_Int32 const nL)
: pDestNode(pD), nDestStart(nD), nSourceStart(nS), nLen(nL)
{
}
RedlineDelText::RedlineDelText(sal_Int32 const nS, sal_Int32 const nL)
: nStart(nS), nLen(nL)
{
......
......@@ -1664,6 +1664,75 @@ static void lcl_ModifyOfst(SwTextFrame* pFrame, TextFrameIndex const nPos, TextF
}
}
namespace {
void UpdateMergedParaForMove(sw::MergedPara & rMerged,
SwTextFrame & rTextFrame,
bool & o_rbRecalcFootnoteFlag,
SwTextNode const& rDestNode,
SwTextNode const& rNode,
sal_Int32 const nDestStart,
sal_Int32 const nSourceStart,
sal_Int32 const nLen)
{
std::vector<std::pair<sal_Int32, sal_Int32>> deleted;
sal_Int32 const nSourceEnd(nSourceStart + nLen);
sal_Int32 nLastEnd(0);
for (auto it = rMerged.extents.begin(); it != rMerged.extents.end(); ++it)
{
if (it->pNode == &rNode)
{
sal_Int32 const nStart(std::max(nLastEnd, nSourceStart));
sal_Int32 const nEnd(std::min(it->nStart, nSourceEnd));
if (nStart < nEnd)
{
deleted.emplace_back(nStart, nEnd);
}
nLastEnd = it->nEnd;
if (nSourceEnd <= it->nEnd)
{
break;
}
}
else if (rNode.GetIndex() < it->pNode->GetIndex())
{
break;
}
}
if (nLastEnd != rNode.Len() + nLen) // add nLen, string was removed already
{
assert(rNode.Len() == 0 || nLastEnd < nSourceEnd);
if (nLastEnd < nSourceEnd)
{
deleted.emplace_back(std::max(nLastEnd, nSourceStart), nSourceEnd);
}
}
if (!deleted.empty())
{
o_rbRecalcFootnoteFlag = true;
for (auto const& it : deleted)
{
sal_Int32 const nStart(it.first - nSourceStart + nDestStart);
TextFrameIndex const nDeleted = UpdateMergedParaForDelete(rMerged, false,
rDestNode, nStart, it.second - it.first);
//FIXME asserts valid for join - but if called from split, the new node isn't there yet and it will be added later... assert(nDeleted);
// assert(nDeleted == it.second - it.first);
if(nDeleted)
{
// InvalidateRange/lcl_SetScriptInval was called sufficiently for SwInsText
lcl_SetWrong(rTextFrame, rDestNode, nStart, -nDeleted, false);
if (rTextFrame.HasFollow())
{
TextFrameIndex const nIndex(sw::MapModelToView(rMerged, &rDestNode, nStart));
lcl_ModifyOfst(&rTextFrame, nIndex, nDeleted); // FIXME why positive?
}
}
}
}
}
} // namespace
/**
* Related: fdo#56031 filter out attribute changes that don't matter for
* humans/a11y to stop flooding the destination mortal with useless noise
......@@ -1683,6 +1752,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
{
SfxPoolItem const* pOld(nullptr);
SfxPoolItem const* pNew(nullptr);
sw::MoveText const* pMoveText(nullptr);
sw::RedlineDelText const* pRedlineDelText(nullptr);
sw::RedlineUnDelText const* pRedlineUnDelText(nullptr);
......@@ -1691,6 +1761,10 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
pOld = pHint->m_pOld;
pNew = pHint->m_pNew;
}
else if (auto const pHt = dynamic_cast<sw::MoveText const*>(&rHint))
{
pMoveText = pHt;
}
else if (auto const pHynt = dynamic_cast<sw::RedlineDelText const*>(&rHint))
{
pRedlineDelText = pHynt;
......@@ -1813,6 +1887,27 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
lcl_ModifyOfst( this, nPos, nLen );
}
}
else if (pMoveText)
{
if (m_pMergedPara
&& m_pMergedPara->pFirstNode->GetIndex() <= pMoveText->pDestNode->GetIndex()
&& pMoveText->pDestNode->GetIndex() <= m_pMergedPara->pLastNode->GetIndex())
{ // if it's not 2 nodes in merged frame, assume the target node doesn't have frames at all
assert(std::abs(static_cast<long>(rNode.GetIndex()) - static_cast<long>(pMoveText->pDestNode->GetIndex())) == 1);
UpdateMergedParaForMove(*m_pMergedPara,
*this,
bRecalcFootnoteFlag,
*pMoveText->pDestNode, rNode,
pMoveText->nDestStart,
pMoveText->nSourceStart,
pMoveText->nLen);
}
else
{
// there is a situation where this is okay: from JoinNext, which will then call CheckResetRedlineMergeFlag, which will then create merged from scratch for this frame
// assert(!m_pMergedPara || !getRootFrame()->IsHideRedlines() || !pMoveText->pDestNode->getLayoutFrame(getRootFrame()));
}
}
else switch (nWhich)
{
case RES_LINENUMBER:
......
......@@ -2496,6 +2496,8 @@ void SwTextNode::CutImpl( SwTextNode * const pDest, const SwIndex & rDestStart,
// want to find their anchor text frame in the follow chain
SwInsText aInsHint( nDestStart, nLen );
pDest->ModifyNotification( nullptr, &aInsHint );
sw::MoveText const moveHint(pDest, nDestStart, nTextStartIdx, nLen);
CallSwClientNotify(moveHint);
SwDelText aDelHint( nTextStartIdx, nLen );
ModifyNotification( nullptr, &aDelHint );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment