sw/inc/hints.hxx | 11 ++ sw/inc/redline.hxx | 3 sw/source/core/attr/hints.cxx | 5 + sw/source/core/doc/DocumentRedlineManager.cxx | 23 +++- sw/source/core/doc/docredln.cxx | 27 +++-- sw/source/core/layout/ftnfrm.cxx | 2 sw/source/core/layout/wsfrm.cxx | 2 sw/source/core/text/txtfrm.cxx | 120 ++++++++++++++++++++++---- sw/source/core/undo/unredln.cxx | 4 9 files changed, 161 insertions(+), 36 deletions(-)
New commits: commit 0fabb1a41cbb100b6cae52f64bef8a8458aa4c97 Author: Michael Stahl <[email protected]> AuthorDate: Fri Aug 17 18:57:37 2018 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Fri Aug 17 18:58:25 2018 +0200 sw_redlinehide_2: quite the nuisance when it happens, better assert Change-Id: I5cef7c2cea41a5b246268a541afd47945603ffed diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx index b82f23e56198..3c475defe980 100644 --- a/sw/source/core/layout/ftnfrm.cxx +++ b/sw/source/core/layout/ftnfrm.cxx @@ -2821,6 +2821,8 @@ SwContentFrame* SwFootnoteFrame::GetRef() SAL_WARN_IF( mpReference != pRefAttr && !mpReference->IsAnFollow( pRefAttr ) && !pRefAttr->IsAnFollow( mpReference ), "sw.core", "access to deleted Frame? pRef != pAttr->GetRef()" ); + assert(mpReference == pRefAttr || mpReference->IsAnFollow(pRefAttr) + || pRefAttr->IsAnFollow(mpReference)); return mpReference; } #endif commit 58a6ab7c120169937780d54cf03dd019f54106e3 Author: Michael Stahl <[email protected]> AuthorDate: Fri Aug 17 18:56:30 2018 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Fri Aug 17 18:56:30 2018 +0200 sw_redlinehide_2: fix wrong assertion Change-Id: I8b00f406ae52c3280f9ec07c845ef7aa6e41617f diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index f52f336ad376..79b5081812f4 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -935,7 +935,7 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged, } } // assert(nFoundNode != 0 && "text node not found - why is it sending hints to us"); - assert(nIndex - nDeleted <= rNode.Len()); + assert(nIndex <= rNode.Len() + nLen); // if there's a remaining deletion, it must be in gap at the end of the node // can't do: might be last one in node was erased assert(nLen == 0 || rMerged.empty() || (it-1)->nEnd <= nIndex); // note: if first node gets deleted then that must call DelFrames as commit a26bfddf9859813da36ebc21b6d5bd987db61738 Author: Michael Stahl <[email protected]> AuthorDate: Fri Aug 17 18:54:39 2018 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Fri Aug 17 18:54:39 2018 +0200 sw_redlinehide_2: invalidate more in DocumentRedlineManager::DeleteRedline To get the extents right, first invalidate old range with Remove, then new range with Add. Change-Id: If46954b9bb86680ae689de742ec878e0287f58d9 diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index 81b858cf5ee9..ad9c292810a1 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -1968,6 +1968,7 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd case SwComparePosition::OverlapBefore: pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove); pRedl->SetStart( *pEnd, pRStt ); + pRedl->InvalidateRange(SwRangeRedline::Invalidation::Add); // re-insert mpRedlineTable->Remove( n ); mpRedlineTable->Insert( pRedl ); @@ -1977,6 +1978,7 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd case SwComparePosition::OverlapBehind: pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove); pRedl->SetEnd( *pStt, pREnd ); + pRedl->InvalidateRange(SwRangeRedline::Invalidation::Add); if( !pRedl->HasValidRange() ) { // re-insert @@ -1993,6 +1995,7 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd if( *pRStt == *pStt ) { pRedl->SetStart( *pEnd, pRStt ); + pRedl->InvalidateRange(SwRangeRedline::Invalidation::Add); // re-insert mpRedlineTable->Remove( n ); mpRedlineTable->Insert( pRedl ); @@ -2005,10 +2008,12 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd { pCpy = new SwRangeRedline( *pRedl ); pCpy->SetStart( *pEnd ); + pCpy->InvalidateRange(SwRangeRedline::Invalidation::Add); } else pCpy = nullptr; pRedl->SetEnd( *pStt, pREnd ); + pRedl->InvalidateRange(SwRangeRedline::Invalidation::Add); if( !pRedl->HasValidRange() ) { // re-insert commit 2c53ff781cc20797aba981c095d69cba9db59d6f Author: Michael Stahl <[email protected]> AuthorDate: Fri Aug 17 17:52:52 2018 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Fri Aug 17 18:51:05 2018 +0200 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 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 cde78e743b0b..40d8377fcb54 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 c056c1c7a113..81b858cf5ee9 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() ) { @@ -784,7 +784,7 @@ DocumentRedlineManager::AppendRedline(SwRangeRedline* pNewRedl, bool const bCall if (IsRedlineOn() && !IsShowOriginal(meRedlineFlags)) { - pNewRedl->InvalidateRange(); + pNewRedl->InvalidateRange(SwRangeRedline::Invalidation::Add); if( m_rDoc.IsAutoFormatRedline() ) { @@ -1900,7 +1900,7 @@ bool DocumentRedlineManager::SplitRedline( const SwPaM& rRange ) break; case 3: - pRedline->InvalidateRange(); + pRedline->InvalidateRange(SwRangeRedline::Invalidation::Remove); mpRedlineTable->DeleteAndDestroy( n-- ); pRedline = nullptr; break; @@ -1960,13 +1960,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 ); @@ -1975,7 +1975,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() ) { @@ -1989,7 +1989,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 ); @@ -2687,7 +2687,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 0947b6a0cbfd..950526187efc 100644 --- a/sw/source/core/doc/docredln.cxx +++ b/sw/source/core/doc/docredln.cxx @@ -1162,7 +1162,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; @@ -1199,7 +1199,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; @@ -1241,7 +1241,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; @@ -1249,7 +1249,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(); @@ -1282,9 +1283,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); + } } } } @@ -1396,7 +1405,7 @@ void SwRangeRedline::MoveToSection() DeleteMark(); } else - InvalidateRange(); + InvalidateRange(Invalidation::Remove); } void SwRangeRedline::CopyToSection() @@ -1676,7 +1685,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 8bb1b0407f72..bcea7f789905 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -4480,7 +4480,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 c38af1cfa2ba..f52f336ad376 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -721,7 +721,10 @@ SwTextFrame::~SwTextFrame() namespace sw { -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 +TextFrameIndex UpdateMergedParaForInsert(MergedPara & rMerged, + bool const isRealInsert, SwTextNode const& rNode, sal_Int32 const nIndex, sal_Int32 const nLen) { assert(nLen); // can 0 happen? @@ -730,6 +733,7 @@ void UpdateMergedParaForInsert(MergedPara & rMerged, assert(rMerged.pFirstNode->GetIndex() <= rNode.GetIndex() && rNode.GetIndex() <= rMerged.pLastNode->GetIndex()); OUStringBuffer text(rMerged.mergedText); sal_Int32 nTFIndex(0); + sal_Int32 nInserted(0); bool bInserted(false); bool bFoundNode(false); auto itInsert(rMerged.extents.end()); @@ -737,22 +741,75 @@ 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) @@ -767,12 +824,14 @@ 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 @@ -1613,6 +1672,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)) { @@ -1623,6 +1683,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"); @@ -1709,6 +1773,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, true ); + lcl_SetScriptInval( *this, nPos ); + bSetFieldsDirty = true; + if (HasFollow()) + lcl_ModifyOfst( this, nPos, nLen ); + } + } else switch (nWhich) { case RES_LINENUMBER: @@ -1725,7 +1817,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 5a7334beb7ac..58d2de808363 100644 --- a/sw/source/core/undo/unredln.cxx +++ b/sw/source/core/undo/unredln.cxx @@ -486,7 +486,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() ) @@ -510,7 +510,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); } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
