summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2018-08-17 17:52:52 +0200
committerMichael Stahl <Michael.Stahl@cib.de>2018-09-19 10:08:55 +0200
commit7fdba6a506533571455cb3ef0532c971dbee210c (patch)
tree8e60d4d8bd508d62520a21da158eb5c86b32baa7
parent7273b79c542e37384b9b71e28163e496cd762a85 (diff)
sw_redlinehide_2: invalidate when delete redline goes away
Add another new hint sw::RedlineUnDelText; the main use case is to send it from DocumentRedlineManager::DeleteRedline() so the view is updated accordingly. Change-Id: Ia490116588dc8d3c695ec83c0c2ce8497736f76e
-rw-r--r--sw/inc/hints.hxx11
-rw-r--r--sw/inc/redline.hxx3
-rw-r--r--sw/source/core/attr/hints.cxx5
-rw-r--r--sw/source/core/doc/DocumentRedlineManager.cxx18
-rw-r--r--sw/source/core/doc/docredln.cxx27
-rw-r--r--sw/source/core/layout/wsfrm.cxx2
-rw-r--r--sw/source/core/text/txtfrm.cxx124
-rw-r--r--sw/source/core/undo/unredln.cxx4
8 files changed, 158 insertions, 36 deletions
diff --git a/sw/inc/hints.hxx b/sw/inc/hints.hxx
index dc31d7424756..bee0ebb1c21a 100644
--- a/sw/inc/hints.hxx
+++ b/sw/inc/hints.hxx
@@ -95,6 +95,7 @@ public:
namespace sw {
+/// new delete redline is created
class RedlineDelText : public SfxHint
{
public:
@@ -104,6 +105,16 @@ public:
RedlineDelText(sal_Int32 nS, sal_Int32 nL);
};
+/// delete redline is removed
+class RedlineUnDelText : public SfxHint
+{
+public:
+ sal_Int32 nStart;
+ sal_Int32 nLen;
+
+ RedlineUnDelText(sal_Int32 nS, sal_Int32 nL);
+};
+
}
class SwUpdateAttr : public SwMsgPoolItem
diff --git a/sw/inc/redline.hxx b/sw/inc/redline.hxx
index c307792d80b0..8b6e2a27a0c3 100644
--- a/sw/inc/redline.hxx
+++ b/sw/inc/redline.hxx
@@ -253,8 +253,9 @@ public:
/// Calculates the intersection with text node number nNdIdx.
void CalcStartEnd(sal_uLong nNdIdx, sal_Int32& rStart, sal_Int32& rEnd) const;
+ enum class Invalidation { Add, Remove };
/// Initiate the layout.
- void InvalidateRange();
+ void InvalidateRange(Invalidation);
bool IsOwnRedline( const SwRangeRedline& rRedl ) const
{ return GetAuthor() == rRedl.GetAuthor(); }
diff --git a/sw/source/core/attr/hints.cxx b/sw/source/core/attr/hints.cxx
index 44c60ff0fd17..7c1ff2a40aec 100644
--- a/sw/source/core/attr/hints.cxx
+++ b/sw/source/core/attr/hints.cxx
@@ -53,6 +53,11 @@ RedlineDelText::RedlineDelText(sal_Int32 const nS, sal_Int32 const nL)
{
}
+RedlineUnDelText::RedlineUnDelText(sal_Int32 const nS, sal_Int32 const nL)
+ : nStart(nS), nLen(nL)
+{
+}
+
} // namespace sw
SwUpdateAttr::SwUpdateAttr( sal_Int32 nS, sal_Int32 nE, sal_uInt16 nW )
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx
index 95ed87d7c818..425a42b1a94a 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -140,7 +140,7 @@ namespace
eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
}
- pRedl->InvalidateRange();
+ pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
switch( pRedl->GetType() )
{
@@ -303,7 +303,7 @@ namespace
eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
}
- pRedl->InvalidateRange();
+ pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
switch( pRedl->GetType() )
{
@@ -783,7 +783,7 @@ DocumentRedlineManager::AppendRedline(SwRangeRedline* pNewRedl, bool const bCall
if (IsRedlineOn() && !IsShowOriginal(meRedlineFlags))
{
- pNewRedl->InvalidateRange();
+ pNewRedl->InvalidateRange(SwRangeRedline::Invalidation::Add);
if( m_rDoc.IsAutoFormatRedline() )
{
@@ -1932,7 +1932,7 @@ bool DocumentRedlineManager::SplitRedline( const SwPaM& rRange )
break;
case 3:
- pRedline->InvalidateRange();
+ pRedline->InvalidateRange(SwRangeRedline::Invalidation::Remove);
mpRedlineTable->DeleteAndDestroy( n-- );
pRedline = nullptr;
break;
@@ -1992,13 +1992,13 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd
{
case SwComparePosition::Equal:
case SwComparePosition::Outside:
- pRedl->InvalidateRange();
+ pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
mpRedlineTable->DeleteAndDestroy( n-- );
bChg = true;
break;
case SwComparePosition::OverlapBefore:
- pRedl->InvalidateRange();
+ pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
pRedl->SetStart( *pEnd, pRStt );
// re-insert
mpRedlineTable->Remove( n );
@@ -2007,7 +2007,7 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd
break;
case SwComparePosition::OverlapBehind:
- pRedl->InvalidateRange();
+ pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
pRedl->SetEnd( *pStt, pREnd );
if( !pRedl->HasValidRange() )
{
@@ -2021,7 +2021,7 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd
case SwComparePosition::Inside:
{
// this one needs to be splitted
- pRedl->InvalidateRange();
+ pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
if( *pRStt == *pStt )
{
pRedl->SetStart( *pEnd, pRStt );
@@ -2744,7 +2744,7 @@ void DocumentRedlineManager::UpdateRedlineAttr()
for(SwRangeRedline* pRedl : rTable)
{
if( pRedl->IsVisible() )
- pRedl->InvalidateRange();
+ pRedl->InvalidateRange(SwRangeRedline::Invalidation::Add);
}
// #TODO - add 'SwExtraRedlineTable' also ?
diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
index fa7b749d4c06..da79c099b14e 100644
--- a/sw/source/core/doc/docredln.cxx
+++ b/sw/source/core/doc/docredln.cxx
@@ -1166,7 +1166,7 @@ void SwRangeRedline::Show(sal_uInt16 nLoop, size_t nMyPos)
case nsRedlineType_t::REDLINE_FORMAT: // Attributes have been applied
case nsRedlineType_t::REDLINE_TABLE: // Table structure has been modified
- InvalidateRange();
+ InvalidateRange(Invalidation::Add);
break;
default:
break;
@@ -1203,7 +1203,7 @@ void SwRangeRedline::Hide(sal_uInt16 nLoop, size_t nMyPos)
case nsRedlineType_t::REDLINE_FORMAT: // Attributes have been applied
case nsRedlineType_t::REDLINE_TABLE: // Table structure has been modified
if( 1 <= nLoop )
- InvalidateRange();
+ InvalidateRange(Invalidation::Remove);
break;
default:
break;
@@ -1245,7 +1245,7 @@ void SwRangeRedline::ShowOriginal(sal_uInt16 nLoop, size_t nMyPos)
case nsRedlineType_t::REDLINE_FORMAT: // Attributes have been applied
case nsRedlineType_t::REDLINE_TABLE: // Table structure has been modified
if( 1 <= nLoop )
- InvalidateRange();
+ InvalidateRange(Invalidation::Remove);
break;
default:
break;
@@ -1253,7 +1253,8 @@ void SwRangeRedline::ShowOriginal(sal_uInt16 nLoop, size_t nMyPos)
pDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
}
-void SwRangeRedline::InvalidateRange() // trigger the Layout
+// trigger the Layout
+void SwRangeRedline::InvalidateRange(Invalidation const eWhy)
{
sal_uLong nSttNd = GetMark()->nNode.GetIndex(),
nEndNd = GetPoint()->nNode.GetIndex();
@@ -1286,9 +1287,17 @@ void SwRangeRedline::InvalidateRange() // trigger the Layout
if (GetType() == nsRedlineType_t::REDLINE_DELETE)
{
sal_Int32 const nStart(n == nSttNd ? nSttCnt : 0);
- sw::RedlineDelText const hint(nStart,
- (n == nEndNd ? nEndCnt : pNd->GetText().getLength()) - nStart);
- pNd->CallSwClientNotify(hint);
+ sal_Int32 const nLen((n == nEndNd ? nEndCnt : pNd->GetText().getLength()) - nStart);
+ if (eWhy == Invalidation::Add)
+ {
+ sw::RedlineDelText const hint(nStart, nLen);
+ pNd->CallSwClientNotify(hint);
+ }
+ else
+ {
+ sw::RedlineUnDelText const hint(nStart, nLen);
+ pNd->CallSwClientNotify(hint);
+ }
}
}
}
@@ -1400,7 +1409,7 @@ void SwRangeRedline::MoveToSection()
DeleteMark();
}
else
- InvalidateRange();
+ InvalidateRange(Invalidation::Remove);
}
void SwRangeRedline::CopyToSection()
@@ -1680,7 +1689,7 @@ void SwRangeRedline::MoveFromSection(size_t nMyPos)
*pItem = *End();
}
else
- InvalidateRange();
+ InvalidateRange(Invalidation::Add);
}
// for Undo
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index 28e1c7739e7c..57b6f698e0da 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4466,7 +4466,7 @@ void SwRootFrame::SetHideRedlines(bool const bHideRedlines)
// trigger repaint of text frames to add/remove the redline color font
if (pRedline->GetType() != nsRedlineType_t::REDLINE_DELETE)
{
- pRedline->InvalidateRange();
+ pRedline->InvalidateRange(SwRangeRedline::Invalidation::Add);
}
}
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 4a0ce81e2cb4..212fc0b40e28 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -722,15 +722,23 @@ SwTextFrame::~SwTextFrame()
namespace sw {
-static void UpdateMergedParaForInsert(MergedPara & rMerged,
+// 1. if real insert => correct nStart/nEnd for full nLen
+// 2. if rl un-delete => do not correct nStart/nEnd but just include un-deleted
+static TextFrameIndex UpdateMergedParaForInsert(MergedPara & rMerged,
+ bool const isRealInsert,
SwTextNode const& rNode, sal_Int32 const nIndex, sal_Int32 const nLen)
{
- assert(nLen); // can 0 happen?
+ assert(!isRealInsert || nLen); // can 0 happen? yes, for redline in empty node
assert(nIndex <= rNode.Len());
assert(nIndex + nLen <= rNode.Len());
assert(rMerged.pFirstNode->GetIndex() <= rNode.GetIndex() && rNode.GetIndex() <= rMerged.pLastNode->GetIndex());
+ if (!nLen)
+ {
+ return TextFrameIndex(0);
+ }
OUStringBuffer text(rMerged.mergedText);
sal_Int32 nTFIndex(0);
+ sal_Int32 nInserted(0);
bool bInserted(false);
bool bFoundNode(false);
auto itInsert(rMerged.extents.end());
@@ -738,22 +746,75 @@ static void UpdateMergedParaForInsert(MergedPara & rMerged,
{
if (it->pNode == &rNode)
{
- bFoundNode = true;
- if (it->nStart <= nIndex && nIndex <= it->nEnd)
- { // note: this can happen only once
- text.insert(nTFIndex + (nIndex - it->nStart),
- rNode.GetText().copy(nIndex, nLen));
- it->nEnd += nLen;
- bInserted = true;
+ if (isRealInsert)
+ {
+ bFoundNode = true;
+ if (it->nStart <= nIndex && nIndex <= it->nEnd)
+ { // note: this can happen only once
+ text.insert(nTFIndex + (nIndex - it->nStart),
+ rNode.GetText().copy(nIndex, nLen));
+ it->nEnd += nLen;
+ nInserted = nLen;
+ assert(!bInserted);
+ bInserted = true;
+ }
+ else if (nIndex < it->nStart)
+ {
+ if (itInsert == rMerged.extents.end())
+ {
+ itInsert = it;
+ }
+ it->nStart += nLen;
+ it->nEnd += nLen;
+ }
}
- else if (nIndex < it->nStart)
+ else
{
- if (itInsert == rMerged.extents.end())
+ assert(it == rMerged.extents.begin() || (it-1)->pNode != &rNode || (it-1)->nEnd < nIndex);
+ if (nIndex + nLen < it->nStart)
{
itInsert = it;
+ break;
+ }
+ if (nIndex < it->nStart)
+ {
+ text.insert(nTFIndex,
+ rNode.GetText().copy(nIndex, it->nStart - nIndex));
+ nInserted += it->nStart - nIndex;
+ it->nStart = nIndex;
+ bInserted = true;
+ }
+ assert(it->nStart <= nIndex);
+ if (nIndex <= it->nEnd)
+ {
+ nTFIndex += it->nEnd - it->nStart;
+ while (it->nEnd < nIndex + nLen)
+ {
+ auto *const pNext(
+ (it+1) != rMerged.extents.end() && (it+1)->pNode == it->pNode
+ ? &*(it+1)
+ : nullptr);
+ if (pNext && pNext->nStart <= nIndex + nLen)
+ {
+ text.insert(nTFIndex,
+ rNode.GetText().copy(it->nEnd, pNext->nStart - it->nEnd));
+ nTFIndex += pNext->nStart - it->nEnd;
+ nInserted += pNext->nStart - it->nEnd;
+ pNext->nStart = it->nStart;
+ it = rMerged.extents.erase(it);
+ }
+ else
+ {
+ text.insert(nTFIndex,
+ rNode.GetText().copy(it->nEnd, nIndex + nLen - it->nEnd));
+ nTFIndex += nIndex + nLen - it->nEnd;
+ nInserted += nIndex + nLen - it->nEnd;
+ it->nEnd = nIndex + nLen;
+ }
+ }
+ bInserted = true;
+ break;
}
- it->nStart += nLen;
- it->nEnd += nLen;
}
}
else if (rNode.GetIndex() < it->pNode->GetIndex() || bFoundNode)
@@ -768,12 +829,14 @@ static 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));
+ nInserted = nLen;
if (rNode.GetIndex() < rMerged.pParaPropsNode->GetIndex())
{ // text inserted before current para-props node
rMerged.pParaPropsNode = &rNode;
}
}
rMerged.mergedText = text.makeStringAndClear();
+ return TextFrameIndex(nInserted);
}
// 1. if real delete => correct nStart/nEnd for full nLen
@@ -1621,6 +1684,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
SfxPoolItem const* pOld(nullptr);
SfxPoolItem const* pNew(nullptr);
sw::RedlineDelText const* pRedlineDelText(nullptr);
+ sw::RedlineUnDelText const* pRedlineUnDelText(nullptr);
if (auto const pHint = dynamic_cast<sw::LegacyModifyHint const*>(&rHint))
{
@@ -1631,6 +1695,10 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
{
pRedlineDelText = pHynt;
}
+ else if (auto const pHnt = dynamic_cast<sw::RedlineUnDelText const*>(&rHint))
+ {
+ pRedlineUnDelText = pHnt;
+ }
else
{
assert(!"unexpected hint");
@@ -1717,6 +1785,34 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
}
}
}
+ else if (pRedlineUnDelText)
+ {
+ if (m_pMergedPara)
+ {
+ sal_Int32 const nNPos = pRedlineUnDelText->nStart;
+ sal_Int32 const nNLen = pRedlineUnDelText->nLen;
+ nPos = MapModelToView(&rNode, nNPos);
+ nLen = UpdateMergedParaForInsert(*m_pMergedPara, false, rNode, nNPos, nNLen);
+ if (IsIdxInside(nPos, nLen))
+ {
+ if (!nLen)
+ {
+ // Refresh NumPortions even when line is empty!
+ if (nPos)
+ InvalidateSize();
+ else
+ Prepare();
+ }
+ else
+ InvalidateRange_( SwCharRange( nPos, nLen ), nNLen );
+ }
+ lcl_SetWrong( *this, rNode, nNPos, nNLen, false );
+ lcl_SetScriptInval( *this, nPos );
+ bSetFieldsDirty = true;
+ if (HasFollow())
+ lcl_ModifyOfst( this, nPos, nLen );
+ }
+ }
else switch (nWhich)
{
case RES_LINENUMBER:
@@ -1733,7 +1829,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
nLen = TextFrameIndex(nNLen);
if (m_pMergedPara)
{
- UpdateMergedParaForInsert(*m_pMergedPara, rNode, nNPos, nNLen);
+ UpdateMergedParaForInsert(*m_pMergedPara, true, rNode, nNPos, nNLen);
}
if( IsIdxInside( nPos, nLen ) )
{
diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx
index 147f9d5c731f..3866e55cfe11 100644
--- a/sw/source/core/undo/unredln.cxx
+++ b/sw/source/core/undo/unredln.cxx
@@ -485,7 +485,7 @@ void SwUndoCompDoc::RedoImpl(::sw::UndoRedoContext & rContext)
{
SwRangeRedline* pTmp = new SwRangeRedline(*pRedlData, rPam);
rDoc.getIDocumentRedlineAccess().GetRedlineTable().Insert( pTmp );
- pTmp->InvalidateRange();
+ pTmp->InvalidateRange(SwRangeRedline::Invalidation::Add);
}
else if( !( RedlineFlags::Ignore & GetRedlineFlags() ) &&
!rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty() )
@@ -509,7 +509,7 @@ void SwUndoCompDoc::RedoImpl(::sw::UndoRedoContext & rContext)
SwRangeRedline* pTmp = new SwRangeRedline(*pRedlData, rPam);
rDoc.getIDocumentRedlineAccess().GetRedlineTable().Insert( pTmp );
- pTmp->InvalidateRange();
+ pTmp->InvalidateRange(SwRangeRedline::Invalidation::Add);
SetPaM(rPam, true);
}