sw/source/core/doc/DocumentRedlineManager.cxx | 1620 +++++++++++++------------- 1 file changed, 820 insertions(+), 800 deletions(-)
New commits: commit e965617c003fba3c4f2b804baa9eb0dce6c3eb0b Author: Noel Grandin <noelgran...@gmail.com> AuthorDate: Sun Aug 29 18:41:44 2021 +0200 Commit: Tünde Tóth <toth.tu...@nisz.hu> CommitDate: Thu Oct 21 14:23:13 2021 +0200 flatten DocumentRedlineManager::AppendRedline a little Change-Id: I2801aad45f11bd9b8a97fc63c2f005f946a02bf6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/121233 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123992 Tested-by: Tünde Tóth <toth.tu...@nisz.hu> Reviewed-by: Tünde Tóth <toth.tu...@nisz.hu> diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index 9982415b4a3e..3010317613bd 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -1222,340 +1222,464 @@ Behaviour of Delete-Redline: IDocumentRedlineAccess::AppendResult DocumentRedlineManager::AppendRedline(SwRangeRedline* pNewRedl, bool const bCallDelete) { - bool bMerged = false; CHECK_REDLINE( *this ) - if (IsRedlineOn() && !IsShowOriginal(meRedlineFlags)) + if (!IsRedlineOn() || IsShowOriginal(meRedlineFlags)) { - pNewRedl->InvalidateRange(SwRangeRedline::Invalidation::Add); + if( bCallDelete && RedlineType::Delete == pNewRedl->GetType() ) + { + RedlineFlags eOld = meRedlineFlags; + // Set to NONE, so that the Delete::Redo merges the Redline data correctly! + // The ShowMode needs to be retained! + meRedlineFlags = eOld & ~RedlineFlags(RedlineFlags::On | RedlineFlags::Ignore); + m_rDoc.getIDocumentContentOperations().DeleteAndJoin( *pNewRedl ); + meRedlineFlags = eOld; + } + delete pNewRedl; + pNewRedl = nullptr; + CHECK_REDLINE( *this ) + return AppendResult::IGNORED; + } + + + bool bMerged = false; - if( m_rDoc.IsAutoFormatRedline() ) + pNewRedl->InvalidateRange(SwRangeRedline::Invalidation::Add); + + if( m_rDoc.IsAutoFormatRedline() ) + { + pNewRedl->SetAutoFormat(); + if( mpAutoFormatRedlnComment && !mpAutoFormatRedlnComment->isEmpty() ) { - pNewRedl->SetAutoFormat(); - if( mpAutoFormatRedlnComment && !mpAutoFormatRedlnComment->isEmpty() ) - { - pNewRedl->SetComment( *mpAutoFormatRedlnComment ); - pNewRedl->SetSeqNo( mnAutoFormatRedlnCommentNo ); - } + pNewRedl->SetComment( *mpAutoFormatRedlnComment ); + pNewRedl->SetSeqNo( mnAutoFormatRedlnCommentNo ); } + } - SwPosition* pStt = pNewRedl->Start(), - * pEnd = pStt == pNewRedl->GetPoint() ? pNewRedl->GetMark() - : pNewRedl->GetPoint(); + SwPosition* pStt = pNewRedl->Start(), + * pEnd = pStt == pNewRedl->GetPoint() ? pNewRedl->GetMark() + : pNewRedl->GetPoint(); + { + SwTextNode* pTextNode = pStt->nNode.GetNode().GetTextNode(); + if( pTextNode == nullptr ) { - SwTextNode* pTextNode = pStt->nNode.GetNode().GetTextNode(); - if( pTextNode == nullptr ) + if( pStt->nContent > 0 ) { - if( pStt->nContent > 0 ) - { - OSL_ENSURE( false, "Redline start: non-text-node with content" ); - pStt->nContent = 0; - } + OSL_ENSURE( false, "Redline start: non-text-node with content" ); + pStt->nContent = 0; } - else + } + else + { + if( pStt->nContent > pTextNode->Len() ) { - if( pStt->nContent > pTextNode->Len() ) - { - OSL_ENSURE( false, "Redline start: index after text" ); - pStt->nContent = pTextNode->Len(); - } + OSL_ENSURE( false, "Redline start: index after text" ); + pStt->nContent = pTextNode->Len(); } - pTextNode = pEnd->nNode.GetNode().GetTextNode(); - if( pTextNode == nullptr ) + } + pTextNode = pEnd->nNode.GetNode().GetTextNode(); + if( pTextNode == nullptr ) + { + if( pEnd->nContent > 0 ) { - if( pEnd->nContent > 0 ) - { - OSL_ENSURE( false, "Redline end: non-text-node with content" ); - pEnd->nContent = 0; - } + OSL_ENSURE( false, "Redline end: non-text-node with content" ); + pEnd->nContent = 0; } - else + } + else + { + if( pEnd->nContent > pTextNode->Len() ) { - if( pEnd->nContent > pTextNode->Len() ) - { - OSL_ENSURE( false, "Redline end: index after text" ); - pEnd->nContent = pTextNode->Len(); - } + OSL_ENSURE( false, "Redline end: index after text" ); + pEnd->nContent = pTextNode->Len(); } } - if( ( *pStt == *pEnd ) && - ( pNewRedl->GetContentIdx() == nullptr ) ) - { // Do not insert empty redlines - delete pNewRedl; - return AppendResult::IGNORED; - } - bool bCompress = false; - SwRedlineTable::size_type n = 0; - // look up the first Redline for the starting position - if( !GetRedline( *pStt, &n ) && n ) - --n; - bool bDec = false; + } + if( ( *pStt == *pEnd ) && + ( pNewRedl->GetContentIdx() == nullptr ) ) + { // Do not insert empty redlines + delete pNewRedl; + return AppendResult::IGNORED; + } + bool bCompress = false; + SwRedlineTable::size_type n = 0; + // look up the first Redline for the starting position + if( !GetRedline( *pStt, &n ) && n ) + --n; + bool bDec = false; - for( ; pNewRedl && n < mpRedlineTable->size(); bDec ? n : ++n ) - { - bDec = false; + for( ; pNewRedl && n < mpRedlineTable->size(); bDec ? n : ++n ) + { + bDec = false; - SwRangeRedline* pRedl = (*mpRedlineTable)[ n ]; - SwPosition* pRStt = pRedl->Start(), - * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark() - : pRedl->GetPoint(); + SwRangeRedline* pRedl = (*mpRedlineTable)[ n ]; + SwPosition* pRStt = pRedl->Start(), + * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark() + : pRedl->GetPoint(); - // #i8518# remove empty redlines while we're at it - if( ( *pRStt == *pREnd ) && - ( pRedl->GetContentIdx() == nullptr ) ) - { - mpRedlineTable->DeleteAndDestroy(n); - continue; - } + // #i8518# remove empty redlines while we're at it + if( ( *pRStt == *pREnd ) && + ( pRedl->GetContentIdx() == nullptr ) ) + { + mpRedlineTable->DeleteAndDestroy(n); + continue; + } - SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ); + SwComparePosition eCmpPos = ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ); - switch( pNewRedl->GetType() ) + switch( pNewRedl->GetType() ) + { + case RedlineType::Insert: + switch( pRedl->GetType() ) { case RedlineType::Insert: - switch( pRedl->GetType() ) + if( pRedl->IsOwnRedline( *pNewRedl ) ) { - case RedlineType::Insert: - if( pRedl->IsOwnRedline( *pNewRedl ) ) - { - bool bDelete = false; - - // Merge if applicable? - if( (( SwComparePosition::Behind == eCmpPos && - IsPrevPos( *pREnd, *pStt ) ) || - ( SwComparePosition::CollideStart == eCmpPos ) || - ( SwComparePosition::OverlapBehind == eCmpPos ) ) && - pRedl->CanCombine( *pNewRedl ) && - ( n+1 >= mpRedlineTable->size() || - ( *(*mpRedlineTable)[ n+1 ]->Start() >= *pEnd && - *(*mpRedlineTable)[ n+1 ]->Start() != *pREnd ) ) ) - { - pRedl->SetEnd( *pEnd, pREnd ); - if( !pRedl->HasValidRange() ) - { - // re-insert - mpRedlineTable->Remove( n ); - mpRedlineTable->Insert( pRedl ); - } - - bMerged = true; - bDelete = true; - } - else if( (( SwComparePosition::Before == eCmpPos && - IsPrevPos( *pEnd, *pRStt ) ) || - ( SwComparePosition::CollideEnd == eCmpPos ) || - ( SwComparePosition::OverlapBefore == eCmpPos ) ) && - pRedl->CanCombine( *pNewRedl ) && - ( !n || - *(*mpRedlineTable)[ n-1 ]->End() != *pRStt )) + bool bDelete = false; + + // Merge if applicable? + if( (( SwComparePosition::Behind == eCmpPos && + IsPrevPos( *pREnd, *pStt ) ) || + ( SwComparePosition::CollideStart == eCmpPos ) || + ( SwComparePosition::OverlapBehind == eCmpPos ) ) && + pRedl->CanCombine( *pNewRedl ) && + ( n+1 >= mpRedlineTable->size() || + ( *(*mpRedlineTable)[ n+1 ]->Start() >= *pEnd && + *(*mpRedlineTable)[ n+1 ]->Start() != *pREnd ) ) ) + { + pRedl->SetEnd( *pEnd, pREnd ); + if( !pRedl->HasValidRange() ) { - pRedl->SetStart( *pStt, pRStt ); // re-insert mpRedlineTable->Remove( n ); mpRedlineTable->Insert( pRedl ); - - bMerged = true; - bDelete = true; - } - else if ( SwComparePosition::Outside == eCmpPos ) - { - // own insert-over-insert redlines: - // just scrap the inside ones - mpRedlineTable->DeleteAndDestroy( n ); - bDec = true; - } - else if( SwComparePosition::OverlapBehind == eCmpPos ) - { - *pStt = *pREnd; - if( ( *pStt == *pEnd ) && - ( pNewRedl->GetContentIdx() == nullptr ) ) - bDelete = true; - } - else if( SwComparePosition::OverlapBefore == eCmpPos ) - { - *pEnd = *pRStt; - if( ( *pStt == *pEnd ) && - ( pNewRedl->GetContentIdx() == nullptr ) ) - bDelete = true; - } - else if( SwComparePosition::Inside == eCmpPos ) - { - bDelete = true; - bMerged = true; } - else if( SwComparePosition::Equal == eCmpPos ) - bDelete = true; - if( bDelete ) - { - delete pNewRedl; - pNewRedl = nullptr; - bCompress = true; - } + bMerged = true; + bDelete = true; } - else if( SwComparePosition::Inside == eCmpPos ) + else if( (( SwComparePosition::Before == eCmpPos && + IsPrevPos( *pEnd, *pRStt ) ) || + ( SwComparePosition::CollideEnd == eCmpPos ) || + ( SwComparePosition::OverlapBefore == eCmpPos ) ) && + pRedl->CanCombine( *pNewRedl ) && + ( !n || + *(*mpRedlineTable)[ n-1 ]->End() != *pRStt )) { - // split up - if( *pEnd != *pREnd ) - { - SwRangeRedline* pCpy = new SwRangeRedline( *pRedl ); - pCpy->SetStart( *pEnd ); - mpRedlineTable->Insert( pCpy ); - } - pRedl->SetEnd( *pStt, pREnd ); - if( ( *pStt == *pRStt ) && - ( pRedl->GetContentIdx() == nullptr ) ) - { - mpRedlineTable->DeleteAndDestroy( n ); - bDec = true; - } - else if( !pRedl->HasValidRange() ) - { - // re-insert - mpRedlineTable->Remove( n ); - mpRedlineTable->Insert( pRedl ); - } + pRedl->SetStart( *pStt, pRStt ); + // re-insert + mpRedlineTable->Remove( n ); + mpRedlineTable->Insert( pRedl ); + + bMerged = true; + bDelete = true; } else if ( SwComparePosition::Outside == eCmpPos ) { - // handle overlapping redlines in broken documents - - // split up the new redline, since it covers the - // existing redline. Insert the first part, and - // progress with the remainder as usual - SwRangeRedline* pSplit = new SwRangeRedline( *pNewRedl ); - pSplit->SetEnd( *pRStt ); - pNewRedl->SetStart( *pREnd ); - mpRedlineTable->Insert( pSplit ); - if( *pStt == *pEnd && pNewRedl->GetContentIdx() == nullptr ) - { - delete pNewRedl; - pNewRedl = nullptr; - bCompress = true; - } + // own insert-over-insert redlines: + // just scrap the inside ones + mpRedlineTable->DeleteAndDestroy( n ); + bDec = true; } - else if ( SwComparePosition::OverlapBehind == eCmpPos ) + else if( SwComparePosition::OverlapBehind == eCmpPos ) { - // handle overlapping redlines in broken documents - pNewRedl->SetStart( *pREnd ); + *pStt = *pREnd; + if( ( *pStt == *pEnd ) && + ( pNewRedl->GetContentIdx() == nullptr ) ) + bDelete = true; } - else if ( SwComparePosition::OverlapBefore == eCmpPos ) + else if( SwComparePosition::OverlapBefore == eCmpPos ) { - // handle overlapping redlines in broken documents *pEnd = *pRStt; if( ( *pStt == *pEnd ) && ( pNewRedl->GetContentIdx() == nullptr ) ) - { - delete pNewRedl; - pNewRedl = nullptr; - bCompress = true; - } + bDelete = true; + } + else if( SwComparePosition::Inside == eCmpPos ) + { + bDelete = true; + bMerged = true; + } + else if( SwComparePosition::Equal == eCmpPos ) + bDelete = true; + + if( bDelete ) + { + delete pNewRedl; + pNewRedl = nullptr; + bCompress = true; + } + } + else if( SwComparePosition::Inside == eCmpPos ) + { + // split up + if( *pEnd != *pREnd ) + { + SwRangeRedline* pCpy = new SwRangeRedline( *pRedl ); + pCpy->SetStart( *pEnd ); + mpRedlineTable->Insert( pCpy ); } + pRedl->SetEnd( *pStt, pREnd ); + if( ( *pStt == *pRStt ) && + ( pRedl->GetContentIdx() == nullptr ) ) + { + mpRedlineTable->DeleteAndDestroy( n ); + bDec = true; + } + else if( !pRedl->HasValidRange() ) + { + // re-insert + mpRedlineTable->Remove( n ); + mpRedlineTable->Insert( pRedl ); + } + } + else if ( SwComparePosition::Outside == eCmpPos ) + { + // handle overlapping redlines in broken documents + + // split up the new redline, since it covers the + // existing redline. Insert the first part, and + // progress with the remainder as usual + SwRangeRedline* pSplit = new SwRangeRedline( *pNewRedl ); + pSplit->SetEnd( *pRStt ); + pNewRedl->SetStart( *pREnd ); + mpRedlineTable->Insert( pSplit ); + if( *pStt == *pEnd && pNewRedl->GetContentIdx() == nullptr ) + { + delete pNewRedl; + pNewRedl = nullptr; + bCompress = true; + } + } + else if ( SwComparePosition::OverlapBehind == eCmpPos ) + { + // handle overlapping redlines in broken documents + pNewRedl->SetStart( *pREnd ); + } + else if ( SwComparePosition::OverlapBefore == eCmpPos ) + { + // handle overlapping redlines in broken documents + *pEnd = *pRStt; + if( ( *pStt == *pEnd ) && + ( pNewRedl->GetContentIdx() == nullptr ) ) + { + delete pNewRedl; + pNewRedl = nullptr; + bCompress = true; + } + } + break; + case RedlineType::Delete: + if( SwComparePosition::Inside == eCmpPos ) + { + // split up + if( *pEnd != *pREnd ) + { + SwRangeRedline* pCpy = new SwRangeRedline( *pRedl ); + pCpy->SetStart( *pEnd ); + mpRedlineTable->Insert( pCpy ); + } + pRedl->SetEnd( *pStt, pREnd ); + if( ( *pStt == *pRStt ) && + ( pRedl->GetContentIdx() == nullptr ) ) + { + mpRedlineTable->DeleteAndDestroy( n ); + bDec = true; + } + else if( !pRedl->HasValidRange() ) + { + // re-insert + mpRedlineTable->Remove( n ); + mpRedlineTable->Insert( pRedl, n ); + } + } + else if ( SwComparePosition::Outside == eCmpPos ) + { + // handle overlapping redlines in broken documents + + // split up the new redline, since it covers the + // existing redline. Insert the first part, and + // progress with the remainder as usual + SwRangeRedline* pSplit = new SwRangeRedline( *pNewRedl ); + pSplit->SetEnd( *pRStt ); + pNewRedl->SetStart( *pREnd ); + mpRedlineTable->Insert( pSplit ); + if( *pStt == *pEnd && pNewRedl->GetContentIdx() == nullptr ) + { + delete pNewRedl; + pNewRedl = nullptr; + bCompress = true; + } + } + else if ( SwComparePosition::Equal == eCmpPos ) + { + // handle identical redlines in broken documents + // delete old (delete) redline + mpRedlineTable->DeleteAndDestroy( n ); + bDec = true; + } + else if ( SwComparePosition::OverlapBehind == eCmpPos ) + { // Another workaround for broken redlines + pNewRedl->SetStart( *pREnd ); + } + break; + case RedlineType::Format: + switch( eCmpPos ) + { + case SwComparePosition::OverlapBefore: + pRedl->SetStart( *pEnd, pRStt ); + // re-insert + mpRedlineTable->Remove( n ); + mpRedlineTable->Insert( pRedl, n ); + bDec = true; + break; + + case SwComparePosition::OverlapBehind: + pRedl->SetEnd( *pStt, pREnd ); + if( *pStt == *pRStt && pRedl->GetContentIdx() == nullptr ) + { + mpRedlineTable->DeleteAndDestroy( n ); + bDec = true; + } + break; + + case SwComparePosition::Equal: + case SwComparePosition::Outside: + // Overlaps the current one completely or has the + // same dimension, delete the old one + mpRedlineTable->DeleteAndDestroy( n ); + bDec = true; break; - case RedlineType::Delete: - if( SwComparePosition::Inside == eCmpPos ) + + case SwComparePosition::Inside: + // Overlaps the current one completely, + // split or shorten the new one + if( *pEnd != *pREnd ) { - // split up - if( *pEnd != *pREnd ) + if( *pEnd != *pRStt ) { - SwRangeRedline* pCpy = new SwRangeRedline( *pRedl ); - pCpy->SetStart( *pEnd ); - mpRedlineTable->Insert( pCpy ); + SwRangeRedline* pNew = new SwRangeRedline( *pRedl ); + pNew->SetStart( *pEnd ); + pRedl->SetEnd( *pStt, pREnd ); + if( *pStt == *pRStt && pRedl->GetContentIdx() == nullptr ) + mpRedlineTable->DeleteAndDestroy( n ); + AppendRedline( pNew, bCallDelete ); + n = 0; // re-initialize + bDec = true; } + } + else pRedl->SetEnd( *pStt, pREnd ); - if( ( *pStt == *pRStt ) && - ( pRedl->GetContentIdx() == nullptr ) ) + break; + default: + break; + } + break; + default: + break; + } + break; + + case RedlineType::Delete: + switch( pRedl->GetType() ) + { + case RedlineType::Delete: + switch( eCmpPos ) + { + case SwComparePosition::Outside: + { + // Overlaps the current one completely, + // split the new one + if (*pEnd == *pREnd) { - mpRedlineTable->DeleteAndDestroy( n ); - bDec = true; + pNewRedl->SetEnd(*pRStt, pEnd); } - else if( !pRedl->HasValidRange() ) + else if (*pStt == *pRStt) { - // re-insert - mpRedlineTable->Remove( n ); - mpRedlineTable->Insert( pRedl, n ); + pNewRedl->SetStart(*pREnd, pStt); } - } - else if ( SwComparePosition::Outside == eCmpPos ) - { - // handle overlapping redlines in broken documents - - // split up the new redline, since it covers the - // existing redline. Insert the first part, and - // progress with the remainder as usual - SwRangeRedline* pSplit = new SwRangeRedline( *pNewRedl ); - pSplit->SetEnd( *pRStt ); - pNewRedl->SetStart( *pREnd ); - mpRedlineTable->Insert( pSplit ); - if( *pStt == *pEnd && pNewRedl->GetContentIdx() == nullptr ) + else { - delete pNewRedl; - pNewRedl = nullptr; - bCompress = true; + SwRangeRedline* pNew = new SwRangeRedline( *pNewRedl ); + pNew->SetStart( *pREnd ); + pNewRedl->SetEnd( *pRStt, pEnd ); + AppendRedline( pNew, bCallDelete ); + n = 0; // re-initialize + bDec = true; } } - else if ( SwComparePosition::Equal == eCmpPos ) - { - // handle identical redlines in broken documents - // delete old (delete) redline - mpRedlineTable->DeleteAndDestroy( n ); - bDec = true; - } - else if ( SwComparePosition::OverlapBehind == eCmpPos ) - { // Another workaround for broken redlines - pNewRedl->SetStart( *pREnd ); - } break; - case RedlineType::Format: - switch( eCmpPos ) + + case SwComparePosition::Inside: + case SwComparePosition::Equal: + delete pNewRedl; + pNewRedl = nullptr; + bCompress = true; + break; + + case SwComparePosition::OverlapBefore: + case SwComparePosition::OverlapBehind: + if( pRedl->IsOwnRedline( *pNewRedl ) && + pRedl->CanCombine( *pNewRedl )) { - case SwComparePosition::OverlapBefore: - pRedl->SetStart( *pEnd, pRStt ); - // re-insert - mpRedlineTable->Remove( n ); - mpRedlineTable->Insert( pRedl, n ); + // If that's the case we can merge it, meaning + // the new one covers this well + if( SwComparePosition::OverlapBehind == eCmpPos ) + pNewRedl->SetStart( *pRStt, pStt ); + else + pNewRedl->SetEnd( *pREnd, pEnd ); + mpRedlineTable->DeleteAndDestroy( n ); bDec = true; - break; + } + else if( SwComparePosition::OverlapBehind == eCmpPos ) + pNewRedl->SetStart( *pREnd, pStt ); + else + pNewRedl->SetEnd( *pRStt, pEnd ); + break; - case SwComparePosition::OverlapBehind: - pRedl->SetEnd( *pStt, pREnd ); - if( *pStt == *pRStt && pRedl->GetContentIdx() == nullptr ) + case SwComparePosition::CollideStart: + case SwComparePosition::CollideEnd: + if( pRedl->IsOwnRedline( *pNewRedl ) && + pRedl->CanCombine( *pNewRedl ) ) + { + if( IsHideChanges( meRedlineFlags )) { - mpRedlineTable->DeleteAndDestroy( n ); - bDec = true; + // Before we can merge, we make it visible! + // We insert temporarily so that pNew is + // also dealt with when moving the indices. + mpRedlineTable->Insert(pNewRedl); + pRedl->Show(0, mpRedlineTable->GetPos(pRedl)); + mpRedlineTable->Remove( pNewRedl ); + pRStt = pRedl->Start(); + pREnd = pRedl->End(); } - break; - case SwComparePosition::Equal: - case SwComparePosition::Outside: - // Overlaps the current one completely or has the - // same dimension, delete the old one - mpRedlineTable->DeleteAndDestroy( n ); + // If that's the case we can merge it, meaning + // the new one covers this well + if( SwComparePosition::CollideStart == eCmpPos ) + pNewRedl->SetStart( *pRStt, pStt ); + else + pNewRedl->SetEnd( *pREnd, pEnd ); + + // delete current (below), and restart process with + // previous + SwRedlineTable::size_type nToBeDeleted = n; bDec = true; - break; - case SwComparePosition::Inside: - // Overlaps the current one completely, - // split or shorten the new one - if( *pEnd != *pREnd ) + if( *(pNewRedl->Start()) <= *pREnd ) { - if( *pEnd != *pRStt ) - { - SwRangeRedline* pNew = new SwRangeRedline( *pRedl ); - pNew->SetStart( *pEnd ); - pRedl->SetEnd( *pStt, pREnd ); - if( *pStt == *pRStt && pRedl->GetContentIdx() == nullptr ) - mpRedlineTable->DeleteAndDestroy( n ); - AppendRedline( pNew, bCallDelete ); - n = 0; // re-initialize - bDec = true; - } + // Whoooah, we just extended the new 'redline' + // beyond previous redlines, so better start + // again. Of course this is not supposed to + // happen, and in an ideal world it doesn't, + // but unfortunately this code is buggy and + // totally rotten so it does happen and we + // better fix it. + n = 0; + bDec = true; } - else - pRedl->SetEnd( *pStt, pREnd ); - break; - default: - break; + + mpRedlineTable->DeleteAndDestroy( nToBeDeleted ); } break; default: @@ -1563,636 +1687,540 @@ DocumentRedlineManager::AppendRedline(SwRangeRedline* pNewRedl, bool const bCall } break; - case RedlineType::Delete: - switch( pRedl->GetType() ) + case RedlineType::Insert: + { + // b62341295: Do not throw away redlines + // even if they are not allowed to be combined + RedlineFlags eOld = meRedlineFlags; + if( !( eOld & RedlineFlags::DontCombineRedlines ) && + pRedl->IsOwnRedline( *pNewRedl ) ) { - case RedlineType::Delete: + + // Set to NONE, so that the Delete::Redo merges the Redline data correctly! + // The ShowMode needs to be retained! + meRedlineFlags = eOld & ~RedlineFlags(RedlineFlags::On | RedlineFlags::Ignore); switch( eCmpPos ) { - case SwComparePosition::Outside: + case SwComparePosition::Equal: + bCompress = true; + mpRedlineTable->DeleteAndDestroy( n ); + bDec = true; + [[fallthrough]]; + + case SwComparePosition::Inside: + if( bCallDelete ) { - // Overlaps the current one completely, - // split the new one - if (*pEnd == *pREnd) + // DeleteAndJoin does not yield the + // desired result if there is no paragraph to + // join with, i.e. at the end of the document. + // For this case, we completely delete the + // paragraphs (if, of course, we also start on + // a paragraph boundary). + if( (pStt->nContent == 0) && + pEnd->nNode.GetNode().IsEndNode() ) { - pNewRedl->SetEnd(*pRStt, pEnd); - } - else if (*pStt == *pRStt) - { - pNewRedl->SetStart(*pREnd, pStt); + pEnd->nNode--; + pEnd->nContent.Assign( + pEnd->nNode.GetNode().GetTextNode(), 0); + m_rDoc.getIDocumentContentOperations().DelFullPara( *pNewRedl ); } else + m_rDoc.getIDocumentContentOperations().DeleteAndJoin( *pNewRedl ); + + bCompress = true; + } + if( !bCallDelete && !bDec && *pEnd == *pREnd ) + { + m_rDoc.getIDocumentContentOperations().DeleteAndJoin( *pNewRedl ); + bCompress = true; + } + else if ( bCallDelete || !bDec ) + { + // delete new redline, except in some cases of fallthrough from previous + // case ::Equal (eg. same portion w:del in w:ins in OOXML import) + delete pNewRedl; + pNewRedl = nullptr; + } + break; + + case SwComparePosition::Outside: + { + mpRedlineTable->Remove( n ); + bDec = true; + if( bCallDelete ) { - SwRangeRedline* pNew = new SwRangeRedline( *pNewRedl ); - pNew->SetStart( *pREnd ); - pNewRedl->SetEnd( *pRStt, pEnd ); - AppendRedline( pNew, bCallDelete ); + TemporaryRedlineUpdater const u(m_rDoc, *pNewRedl); + m_rDoc.getIDocumentContentOperations().DeleteAndJoin( *pRedl ); n = 0; // re-initialize - bDec = true; } + delete pRedl; } break; - case SwComparePosition::Inside: - case SwComparePosition::Equal: - delete pNewRedl; - pNewRedl = nullptr; - bCompress = true; - break; - case SwComparePosition::OverlapBefore: - case SwComparePosition::OverlapBehind: - if( pRedl->IsOwnRedline( *pNewRedl ) && - pRedl->CanCombine( *pNewRedl )) { - // If that's the case we can merge it, meaning - // the new one covers this well - if( SwComparePosition::OverlapBehind == eCmpPos ) - pNewRedl->SetStart( *pRStt, pStt ); + SwPaM aPam( *pRStt, *pEnd ); + + if( *pEnd == *pREnd ) + mpRedlineTable->DeleteAndDestroy( n ); else - pNewRedl->SetEnd( *pREnd, pEnd ); - mpRedlineTable->DeleteAndDestroy( n ); + { + pRedl->SetStart( *pEnd, pRStt ); + // re-insert + mpRedlineTable->Remove( n ); + mpRedlineTable->Insert( pRedl, n ); + } + + if( bCallDelete ) + { + TemporaryRedlineUpdater const u(m_rDoc, *pNewRedl); + m_rDoc.getIDocumentContentOperations().DeleteAndJoin( aPam ); + n = 0; // re-initialize + } bDec = true; } - else if( SwComparePosition::OverlapBehind == eCmpPos ) - pNewRedl->SetStart( *pREnd, pStt ); - else - pNewRedl->SetEnd( *pRStt, pEnd ); break; - case SwComparePosition::CollideStart: - case SwComparePosition::CollideEnd: - if( pRedl->IsOwnRedline( *pNewRedl ) && - pRedl->CanCombine( *pNewRedl ) ) + case SwComparePosition::OverlapBehind: { - if( IsHideChanges( meRedlineFlags )) + SwPaM aPam( *pStt, *pREnd ); + + if( *pStt == *pRStt ) { - // Before we can merge, we make it visible! - // We insert temporarily so that pNew is - // also dealt with when moving the indices. - mpRedlineTable->Insert(pNewRedl); - pRedl->Show(0, mpRedlineTable->GetPos(pRedl)); - mpRedlineTable->Remove( pNewRedl ); - pRStt = pRedl->Start(); - pREnd = pRedl->End(); + mpRedlineTable->DeleteAndDestroy( n ); + bDec = true; } - - // If that's the case we can merge it, meaning - // the new one covers this well - if( SwComparePosition::CollideStart == eCmpPos ) - pNewRedl->SetStart( *pRStt, pStt ); else - pNewRedl->SetEnd( *pREnd, pEnd ); - - // delete current (below), and restart process with - // previous - SwRedlineTable::size_type nToBeDeleted = n; - bDec = true; + pRedl->SetEnd( *pStt, pREnd ); - if( *(pNewRedl->Start()) <= *pREnd ) + if( bCallDelete ) { - // Whoooah, we just extended the new 'redline' - // beyond previous redlines, so better start - // again. Of course this is not supposed to - // happen, and in an ideal world it doesn't, - // but unfortunately this code is buggy and - // totally rotten so it does happen and we - // better fix it. - n = 0; + TemporaryRedlineUpdater const u(m_rDoc, *pNewRedl); + m_rDoc.getIDocumentContentOperations().DeleteAndJoin( aPam ); + n = 0; // re-initialize bDec = true; } - - mpRedlineTable->DeleteAndDestroy( nToBeDeleted ); } break; default: break; } - break; - case RedlineType::Insert: + meRedlineFlags = eOld; + } + else { - // b62341295: Do not throw away redlines - // even if they are not allowed to be combined - RedlineFlags eOld = meRedlineFlags; - if( !( eOld & RedlineFlags::DontCombineRedlines ) && - pRedl->IsOwnRedline( *pNewRedl ) ) - { + // it may be necessary to split the existing redline in + // two. In this case, pRedl will be changed to cover + // only part of its former range, and pNew will cover + // the remainder. + SwRangeRedline* pNew = nullptr; - // Set to NONE, so that the Delete::Redo merges the Redline data correctly! - // The ShowMode needs to be retained! - meRedlineFlags = eOld & ~RedlineFlags(RedlineFlags::On | RedlineFlags::Ignore); - switch( eCmpPos ) + switch( eCmpPos ) + { + case SwComparePosition::Equal: { - case SwComparePosition::Equal: - bCompress = true; - mpRedlineTable->DeleteAndDestroy( n ); - bDec = true; - [[fallthrough]]; - - case SwComparePosition::Inside: - if( bCallDelete ) - { - // DeleteAndJoin does not yield the - // desired result if there is no paragraph to - // join with, i.e. at the end of the document. - // For this case, we completely delete the - // paragraphs (if, of course, we also start on - // a paragraph boundary). - if( (pStt->nContent == 0) && - pEnd->nNode.GetNode().IsEndNode() ) - { - pEnd->nNode--; - pEnd->nContent.Assign( - pEnd->nNode.GetNode().GetTextNode(), 0); - m_rDoc.getIDocumentContentOperations().DelFullPara( *pNewRedl ); - } - else - m_rDoc.getIDocumentContentOperations().DeleteAndJoin( *pNewRedl ); - - bCompress = true; - } - if( !bCallDelete && !bDec && *pEnd == *pREnd ) - { - m_rDoc.getIDocumentContentOperations().DeleteAndJoin( *pNewRedl ); - bCompress = true; - } - else if ( bCallDelete || !bDec ) - { - // delete new redline, except in some cases of fallthrough from previous - // case ::Equal (eg. same portion w:del in w:ins in OOXML import) - delete pNewRedl; - pNewRedl = nullptr; - } - break; - - case SwComparePosition::Outside: + pRedl->PushData( *pNewRedl ); + delete pNewRedl; + pNewRedl = nullptr; + if( IsHideChanges( meRedlineFlags )) { - mpRedlineTable->Remove( n ); - bDec = true; - if( bCallDelete ) - { - TemporaryRedlineUpdater const u(m_rDoc, *pNewRedl); - m_rDoc.getIDocumentContentOperations().DeleteAndJoin( *pRedl ); - n = 0; // re-initialize - } - delete pRedl; + pRedl->Hide(0, mpRedlineTable->GetPos(pRedl)); } - break; + bCompress = true; + } + break; - case SwComparePosition::OverlapBefore: + case SwComparePosition::Inside: + { + if( *pRStt == *pStt ) { - SwPaM aPam( *pRStt, *pEnd ); - - if( *pEnd == *pREnd ) - mpRedlineTable->DeleteAndDestroy( n ); - else + // #i97421# + // redline w/out extent loops + if (*pStt != *pEnd) { + pNewRedl->PushData( *pRedl, false ); pRedl->SetStart( *pEnd, pRStt ); // re-insert mpRedlineTable->Remove( n ); mpRedlineTable->Insert( pRedl, n ); + bDec = true; } - - if( bCallDelete ) - { - TemporaryRedlineUpdater const u(m_rDoc, *pNewRedl); - m_rDoc.getIDocumentContentOperations().DeleteAndJoin( aPam ); - n = 0; // re-initialize - } - bDec = true; } - break; - - case SwComparePosition::OverlapBehind: + else { - SwPaM aPam( *pStt, *pREnd ); - - if( *pStt == *pRStt ) + pNewRedl->PushData( *pRedl, false ); + if( *pREnd != *pEnd ) { - mpRedlineTable->DeleteAndDestroy( n ); - bDec = true; + pNew = new SwRangeRedline( *pRedl ); + pNew->SetStart( *pEnd ); } - else - pRedl->SetEnd( *pStt, pREnd ); - - if( bCallDelete ) + pRedl->SetEnd( *pStt, pREnd ); + if( !pRedl->HasValidRange() ) { - TemporaryRedlineUpdater const u(m_rDoc, *pNewRedl); - m_rDoc.getIDocumentContentOperations().DeleteAndJoin( aPam ); - n = 0; // re-initialize - bDec = true; + // re-insert + mpRedlineTable->Remove( n ); + mpRedlineTable->Insert( pRedl, n ); } } - break; - default: - break; } + break; - meRedlineFlags = eOld; - } - else - { - // it may be necessary to split the existing redline in - // two. In this case, pRedl will be changed to cover - // only part of its former range, and pNew will cover - // the remainder. - SwRangeRedline* pNew = nullptr; + case SwComparePosition::Outside: + { + pRedl->PushData( *pNewRedl ); + if( *pEnd == *pREnd ) + { + pNewRedl->SetEnd( *pRStt, pEnd ); + } + else if (*pStt == *pRStt) + { + pNewRedl->SetStart(*pREnd, pStt); + } + else + { + pNew = new SwRangeRedline( *pNewRedl ); + pNew->SetEnd( *pRStt ); + pNewRedl->SetStart( *pREnd, pStt ); + } + bCompress = true; + } + break; - switch( eCmpPos ) + case SwComparePosition::OverlapBefore: { - case SwComparePosition::Equal: + if( *pEnd == *pREnd ) { pRedl->PushData( *pNewRedl ); - delete pNewRedl; - pNewRedl = nullptr; + pNewRedl->SetEnd( *pRStt, pEnd ); if( IsHideChanges( meRedlineFlags )) { + mpRedlineTable->Insert(pNewRedl); pRedl->Hide(0, mpRedlineTable->GetPos(pRedl)); + mpRedlineTable->Remove( pNewRedl ); } - bCompress = true; } - break; - - case SwComparePosition::Inside: + else { - if( *pRStt == *pStt ) - { - // #i97421# - // redline w/out extent loops - if (*pStt != *pEnd) - { - pNewRedl->PushData( *pRedl, false ); - pRedl->SetStart( *pEnd, pRStt ); - // re-insert - mpRedlineTable->Remove( n ); - mpRedlineTable->Insert( pRedl, n ); - bDec = true; - } - } - else - { - pNewRedl->PushData( *pRedl, false ); - if( *pREnd != *pEnd ) - { - pNew = new SwRangeRedline( *pRedl ); - pNew->SetStart( *pEnd ); - } - pRedl->SetEnd( *pStt, pREnd ); - if( !pRedl->HasValidRange() ) - { - // re-insert - mpRedlineTable->Remove( n ); - mpRedlineTable->Insert( pRedl, n ); - } - } + pNew = new SwRangeRedline( *pRedl ); + pNew->PushData( *pNewRedl ); + pNew->SetEnd( *pEnd ); + pNewRedl->SetEnd( *pRStt, pEnd ); + pRedl->SetStart( *pNew->End(), pRStt ) ; + // re-insert + mpRedlineTable->Remove( n ); + mpRedlineTable->Insert( pRedl ); + bDec = true; } - break; + } + break; - case SwComparePosition::Outside: + case SwComparePosition::OverlapBehind: + { + if( *pStt == *pRStt ) { pRedl->PushData( *pNewRedl ); - if( *pEnd == *pREnd ) - { - pNewRedl->SetEnd( *pRStt, pEnd ); - } - else if (*pStt == *pRStt) - { - pNewRedl->SetStart(*pREnd, pStt); - } - else + pNewRedl->SetStart( *pREnd, pStt ); + if( IsHideChanges( meRedlineFlags )) { - pNew = new SwRangeRedline( *pNewRedl ); - pNew->SetEnd( *pRStt ); - pNewRedl->SetStart( *pREnd, pStt ); + mpRedlineTable->Insert( pNewRedl ); + pRedl->Hide(0, mpRedlineTable->GetPos(pRedl)); + mpRedlineTable->Remove( pNewRedl ); } - bCompress = true; } - break; - - case SwComparePosition::OverlapBefore: + else { - if( *pEnd == *pREnd ) - { - pRedl->PushData( *pNewRedl ); - pNewRedl->SetEnd( *pRStt, pEnd ); - if( IsHideChanges( meRedlineFlags )) - { - mpRedlineTable->Insert(pNewRedl); - pRedl->Hide(0, mpRedlineTable->GetPos(pRedl)); - mpRedlineTable->Remove( pNewRedl ); - } - } - else + pNew = new SwRangeRedline( *pRedl ); + pNew->PushData( *pNewRedl ); + pNew->SetStart( *pStt ); + pNewRedl->SetStart( *pREnd, pStt ); + pRedl->SetEnd( *pNew->Start(), pREnd ); + if( !pRedl->HasValidRange() ) { - pNew = new SwRangeRedline( *pRedl ); - pNew->PushData( *pNewRedl ); - pNew->SetEnd( *pEnd ); - pNewRedl->SetEnd( *pRStt, pEnd ); - pRedl->SetStart( *pNew->End(), pRStt ) ; // re-insert mpRedlineTable->Remove( n ); mpRedlineTable->Insert( pRedl ); - bDec = true; - } - } - break; - - case SwComparePosition::OverlapBehind: - { - if( *pStt == *pRStt ) - { - pRedl->PushData( *pNewRedl ); - pNewRedl->SetStart( *pREnd, pStt ); - if( IsHideChanges( meRedlineFlags )) - { - mpRedlineTable->Insert( pNewRedl ); - pRedl->Hide(0, mpRedlineTable->GetPos(pRedl)); - mpRedlineTable->Remove( pNewRedl ); - } - } - else - { - pNew = new SwRangeRedline( *pRedl ); - pNew->PushData( *pNewRedl ); - pNew->SetStart( *pStt ); - pNewRedl->SetStart( *pREnd, pStt ); - pRedl->SetEnd( *pNew->Start(), pREnd ); - if( !pRedl->HasValidRange() ) - { - // re-insert - mpRedlineTable->Remove( n ); - mpRedlineTable->Insert( pRedl ); - } } } - break; - default: - break; } + break; + default: + break; + } + + // insert the pNew part (if it exists) + if( pNew ) + { + mpRedlineTable->Insert( pNew ); + + // pNew must be deleted if Insert() wasn't + // successful. But that can't happen, since pNew is + // part of the original pRedl redline. + // OSL_ENSURE( bRet, "Can't insert existing redline?" ); + + // restart (now with pRedl being split up) + n = 0; + bDec = true; + } + } + } + break; + + case RedlineType::Format: + switch( eCmpPos ) + { + case SwComparePosition::OverlapBefore: + pRedl->SetStart( *pEnd, pRStt ); + // re-insert + mpRedlineTable->Remove( n ); + mpRedlineTable->Insert( pRedl, n ); + bDec = true; + break; - // insert the pNew part (if it exists) - if( pNew ) - { - mpRedlineTable->Insert( pNew ); + case SwComparePosition::OverlapBehind: + pRedl->SetEnd( *pStt, pREnd ); + break; - // pNew must be deleted if Insert() wasn't - // successful. But that can't happen, since pNew is - // part of the original pRedl redline. - // OSL_ENSURE( bRet, "Can't insert existing redline?" ); + case SwComparePosition::Equal: + case SwComparePosition::Outside: + // Overlaps the current one completely or has the + // same dimension, delete the old one + mpRedlineTable->DeleteAndDestroy( n ); + bDec = true; + break; - // restart (now with pRedl being split up) - n = 0; + case SwComparePosition::Inside: + // Overlaps the current one completely, + // split or shorten the new one + if( *pEnd != *pREnd ) + { + if( *pEnd != *pRStt ) + { + SwRangeRedline* pNew = new SwRangeRedline( *pRedl ); + pNew->SetStart( *pEnd ); + pRedl->SetEnd( *pStt, pREnd ); + if( ( *pStt == *pRStt ) && + ( pRedl->GetContentIdx() == nullptr ) ) + mpRedlineTable->DeleteAndDestroy( n ); + AppendRedline( pNew, bCallDelete ); + n = 0; // re-initialize bDec = true; } } + else + pRedl->SetEnd( *pStt, pREnd ); + break; + default: + break; } break; + default: + break; + } + break; - case RedlineType::Format: - switch( eCmpPos ) - { - case SwComparePosition::OverlapBefore: - pRedl->SetStart( *pEnd, pRStt ); - // re-insert - mpRedlineTable->Remove( n ); - mpRedlineTable->Insert( pRedl, n ); - bDec = true; - break; + case RedlineType::Format: + switch( pRedl->GetType() ) + { + case RedlineType::Insert: + case RedlineType::Delete: + switch( eCmpPos ) + { + case SwComparePosition::OverlapBefore: + pNewRedl->SetEnd( *pRStt, pEnd ); + break; - case SwComparePosition::OverlapBehind: - pRedl->SetEnd( *pStt, pREnd ); - break; + case SwComparePosition::OverlapBehind: + pNewRedl->SetStart( *pREnd, pStt ); + break; - case SwComparePosition::Equal: - case SwComparePosition::Outside: - // Overlaps the current one completely or has the - // same dimension, delete the old one - mpRedlineTable->DeleteAndDestroy( n ); - bDec = true; - break; + case SwComparePosition::Equal: + case SwComparePosition::Inside: + delete pNewRedl; + pNewRedl = nullptr; + break; - case SwComparePosition::Inside: - // Overlaps the current one completely, - // split or shorten the new one - if( *pEnd != *pREnd ) - { - if( *pEnd != *pRStt ) - { - SwRangeRedline* pNew = new SwRangeRedline( *pRedl ); - pNew->SetStart( *pEnd ); - pRedl->SetEnd( *pStt, pREnd ); - if( ( *pStt == *pRStt ) && - ( pRedl->GetContentIdx() == nullptr ) ) - mpRedlineTable->DeleteAndDestroy( n ); - AppendRedline( pNew, bCallDelete ); - n = 0; // re-initialize - bDec = true; - } - } - else - pRedl->SetEnd( *pStt, pREnd ); - break; - default: - break; + case SwComparePosition::Outside: + // Overlaps the current one completely, + // split or shorten the new one + if (*pEnd == *pREnd) + { + pNewRedl->SetEnd(*pRStt, pEnd); + } + else if (*pStt == *pRStt) + { + pNewRedl->SetStart(*pREnd, pStt); + } + else + { + SwRangeRedline* pNew = new SwRangeRedline( *pNewRedl ); + pNew->SetStart( *pREnd ); + pNewRedl->SetEnd( *pRStt, pEnd ); + AppendRedline( pNew, bCallDelete ); + n = 0; // re-initialize + bDec = true; } break; default: break; } break; - case RedlineType::Format: - switch( pRedl->GetType() ) + switch( eCmpPos ) { - case RedlineType::Insert: - case RedlineType::Delete: - switch( eCmpPos ) + case SwComparePosition::Outside: + case SwComparePosition::Equal: { - case SwComparePosition::OverlapBefore: - pNewRedl->SetEnd( *pRStt, pEnd ); - break; - - case SwComparePosition::OverlapBehind: - pNewRedl->SetStart( *pREnd, pStt ); - break; + // Overlaps the current one completely or has the + // same dimension, delete the old one + mpRedlineTable->DeleteAndDestroy( n ); + bDec = true; + } + break; - case SwComparePosition::Equal: - case SwComparePosition::Inside: + case SwComparePosition::Inside: + if( pRedl->IsOwnRedline( *pNewRedl ) && + pRedl->CanCombine( *pNewRedl )) + { + // own one can be ignored completely delete pNewRedl; pNewRedl = nullptr; - break; - - case SwComparePosition::Outside: - // Overlaps the current one completely, - // split or shorten the new one - if (*pEnd == *pREnd) - { - pNewRedl->SetEnd(*pRStt, pEnd); - } - else if (*pStt == *pRStt) - { - pNewRedl->SetStart(*pREnd, pStt); - } - else - { - SwRangeRedline* pNew = new SwRangeRedline( *pNewRedl ); - pNew->SetStart( *pREnd ); - pNewRedl->SetEnd( *pRStt, pEnd ); - AppendRedline( pNew, bCallDelete ); - n = 0; // re-initialize - bDec = true; - } - break; - default: - break; } - break; - case RedlineType::Format: - switch( eCmpPos ) + else if( *pREnd == *pEnd ) + // or else only shorten the current one + pRedl->SetEnd( *pStt, pREnd ); + else if( *pRStt == *pStt ) { - case SwComparePosition::Outside: - case SwComparePosition::Equal: - { - // Overlaps the current one completely or has the - // same dimension, delete the old one - mpRedlineTable->DeleteAndDestroy( n ); - bDec = true; - } - break; - - case SwComparePosition::Inside: - if( pRedl->IsOwnRedline( *pNewRedl ) && - pRedl->CanCombine( *pNewRedl )) - { - // own one can be ignored completely - delete pNewRedl; - pNewRedl = nullptr; - } - else if( *pREnd == *pEnd ) - // or else only shorten the current one - pRedl->SetEnd( *pStt, pREnd ); - else if( *pRStt == *pStt ) - { - // or else only shorten the current one - pRedl->SetStart( *pEnd, pRStt ); - // re-insert - mpRedlineTable->Remove( n ); - mpRedlineTable->Insert( pRedl, n ); - bDec = true; - } - else - { - // If it lies completely within the current one - // we need to split it - SwRangeRedline* pNew = new SwRangeRedline( *pRedl ); - pNew->SetStart( *pEnd ); - pRedl->SetEnd( *pStt, pREnd ); - AppendRedline( pNew, bCallDelete ); - n = 0; // re-initialize - bDec = true; - } - break; + // or else only shorten the current one + pRedl->SetStart( *pEnd, pRStt ); + // re-insert + mpRedlineTable->Remove( n ); + mpRedlineTable->Insert( pRedl, n ); + bDec = true; + } + else + { + // If it lies completely within the current one + // we need to split it + SwRangeRedline* pNew = new SwRangeRedline( *pRedl ); + pNew->SetStart( *pEnd ); + pRedl->SetEnd( *pStt, pREnd ); + AppendRedline( pNew, bCallDelete ); + n = 0; // re-initialize + bDec = true; + } + break; - case SwComparePosition::OverlapBefore: - case SwComparePosition::OverlapBehind: - if( pRedl->IsOwnRedline( *pNewRedl ) && - pRedl->CanCombine( *pNewRedl )) - { - // If that's the case we can merge it, meaning - // the new one covers this well - if( SwComparePosition::OverlapBehind == eCmpPos ) - pNewRedl->SetStart( *pRStt, pStt ); - else - pNewRedl->SetEnd( *pREnd, pEnd ); - mpRedlineTable->DeleteAndDestroy( n ); - bDec = false; - } - else if( SwComparePosition::OverlapBehind == eCmpPos ) - pNewRedl->SetStart( *pREnd, pStt ); + case SwComparePosition::OverlapBefore: + case SwComparePosition::OverlapBehind: + if( pRedl->IsOwnRedline( *pNewRedl ) && + pRedl->CanCombine( *pNewRedl )) + { + // If that's the case we can merge it, meaning + // the new one covers this well + if( SwComparePosition::OverlapBehind == eCmpPos ) + pNewRedl->SetStart( *pRStt, pStt ); else - pNewRedl->SetEnd( *pRStt, pEnd ); - break; - - case SwComparePosition::CollideEnd: - if( pRedl->IsOwnRedline( *pNewRedl ) && - pRedl->CanCombine( *pNewRedl ) && n && - *(*mpRedlineTable)[ n-1 ]->End() < *pStt ) - { - // If that's the case we can merge it, meaning - // the new one covers this well pNewRedl->SetEnd( *pREnd, pEnd ); - mpRedlineTable->DeleteAndDestroy( n ); - bDec = true; - } - break; - case SwComparePosition::CollideStart: - if( pRedl->IsOwnRedline( *pNewRedl ) && - pRedl->CanCombine( *pNewRedl ) && - n+1 < mpRedlineTable->size() && - *(*mpRedlineTable)[ n+1 ]->Start() < *pEnd ) - { - // If that's the case we can merge it, meaning - // the new one covers this well - pNewRedl->SetStart( *pRStt, pStt ); - mpRedlineTable->DeleteAndDestroy( n ); - bDec = true; - } - break; - default: - break; + mpRedlineTable->DeleteAndDestroy( n ); + bDec = false; + } + else if( SwComparePosition::OverlapBehind == eCmpPos ) + pNewRedl->SetStart( *pREnd, pStt ); + else + pNewRedl->SetEnd( *pRStt, pEnd ); + break; + + case SwComparePosition::CollideEnd: + if( pRedl->IsOwnRedline( *pNewRedl ) && + pRedl->CanCombine( *pNewRedl ) && n && + *(*mpRedlineTable)[ n-1 ]->End() < *pStt ) + { + // If that's the case we can merge it, meaning + // the new one covers this well + pNewRedl->SetEnd( *pREnd, pEnd ); + mpRedlineTable->DeleteAndDestroy( n ); + bDec = true; + } + break; + case SwComparePosition::CollideStart: + if( pRedl->IsOwnRedline( *pNewRedl ) && + pRedl->CanCombine( *pNewRedl ) && + n+1 < mpRedlineTable->size() && + *(*mpRedlineTable)[ n+1 ]->Start() < *pEnd ) + { + // If that's the case we can merge it, meaning + // the new one covers this well + pNewRedl->SetStart( *pRStt, pStt ); + mpRedlineTable->DeleteAndDestroy( n ); + bDec = true; } break; default: break; } break; - - case RedlineType::FmtColl: - // How should we behave here? - // insert as is - break; default: break; } + break; + + case RedlineType::FmtColl: + // How should we behave here? + // insert as is + break; + default: + break; } + } - if( pNewRedl ) + if( pNewRedl ) + { + if( ( *pStt == *pEnd ) && + ( pNewRedl->GetContentIdx() == nullptr ) ) + { // Do not insert empty redlines + delete pNewRedl; + pNewRedl = nullptr; + } + else { - if( ( *pStt == *pEnd ) && - ( pNewRedl->GetContentIdx() == nullptr ) ) - { // Do not insert empty redlines - delete pNewRedl; - pNewRedl = nullptr; - } - else + if ( bCallDelete && RedlineType::Delete == pNewRedl->GetType() ) { - if ( bCallDelete && RedlineType::Delete == pNewRedl->GetType() ) + if ( pStt->nContent != 0 ) { - if ( pStt->nContent != 0 ) - { - // tdf#119571 update the style of the joined paragraph - // after a partially deleted paragraph to show its correct style - // in "Show changes" mode, too. All removed paragraphs - // get the style of the first (partially deleted) paragraph - // to avoid text insertion with bad style in the deleted - // area later. - - SwContentNode* pDelNd = pStt->nNode.GetNode().GetContentNode(); - SwContentNode* pTextNd = pEnd->nNode.GetNode().GetContentNode(); - SwTextNode* pDelNode = pStt->nNode.GetNode().GetTextNode(); - SwTextNode* pTextNode; - SwNodeIndex aIdx( pEnd->nNode.GetNode() ); - bool bFirst = true; - - while (pDelNode != nullptr && pTextNd != nullptr && pDelNd->GetIndex() < pTextNd->GetIndex()) + // tdf#119571 update the style of the joined paragraph + // after a partially deleted paragraph to show its correct style + // in "Show changes" mode, too. All removed paragraphs + // get the style of the first (partially deleted) paragraph + // to avoid text insertion with bad style in the deleted + // area later. + + SwContentNode* pDelNd = pStt->nNode.GetNode().GetContentNode(); + SwContentNode* pTextNd = pEnd->nNode.GetNode().GetContentNode(); + SwTextNode* pDelNode = pStt->nNode.GetNode().GetTextNode(); + SwTextNode* pTextNode; + SwNodeIndex aIdx( pEnd->nNode.GetNode() ); + bool bFirst = true; + + while (pDelNode != nullptr && pTextNd != nullptr && pDelNd->GetIndex() < pTextNd->GetIndex()) + { + pTextNode = pTextNd->GetTextNode(); + if (pTextNode && pDelNode != pTextNode ) { - pTextNode = pTextNd->GetTextNode(); - if (pTextNode && pDelNode != pTextNode ) + SwPosition aPos(aIdx); + + if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) { - SwPosition aPos(aIdx); + bCompress = true; + + // split redline to store ExtraData per paragraphs + SwRangeRedline* pPar = new SwRangeRedline( *pNewRedl ); + pPar->SetStart( aPos ); + pNewRedl->SetEnd( aPos ); - if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) + // get extradata for reset formatting of the modified paragraph + SwRedlineExtraData_FormatColl* pExtraData = lcl_CopyStyle(aPos, *pStt, false); + if (pExtraData) { bCompress = true; @@ -2211,45 +2239,37 @@ DocumentRedlineManager::AppendRedline(SwRangeRedline* pNewRedl, bool const bCall xRedlineExtraData.reset(pExtraData); pPar->SetExtraData( xRedlineExtraData.get() ); } - mpRedlineTable->Insert( pPar ); - } - // modify paragraph formatting - lcl_CopyStyle(*pStt, aPos); + // skip empty redlines without ExtraData + // FIXME: maybe checking pExtraData is redundant here + if ( pExtraData || *pPar->Start() != *pPar->End() ) + mpRedlineTable->Insert( pPar ); + else + delete pPar; } - pTextNd = SwNodes::GoPrevious( &aIdx ); - if (bFirst) - bFirst = false; + // modify paragraph formatting + lcl_CopyStyle(*pStt, aPos); } + pTextNd = SwNodes::GoPrevious( &aIdx ); + + if (bFirst) + bFirst = false; } } - bool const ret = mpRedlineTable->Insert( pNewRedl ); - assert(ret || !pNewRedl); - if (ret && !pNewRedl) - { - bMerged = true; // treat InsertWithValidRanges as "merge" - } + } + bool const ret = mpRedlineTable->Insert( pNewRedl ); + assert(ret || !pNewRedl); + if (ret && !pNewRedl) + { + bMerged = true; // treat InsertWithValidRanges as "merge" } } - - if( bCompress ) - CompressRedlines(); - } - else - { - if( bCallDelete && RedlineType::Delete == pNewRedl->GetType() ) - { - RedlineFlags eOld = meRedlineFlags; - // Set to NONE, so that the Delete::Redo merges the Redline data correctly! - // The ShowMode needs to be retained! - meRedlineFlags = eOld & ~RedlineFlags(RedlineFlags::On | RedlineFlags::Ignore); - m_rDoc.getIDocumentContentOperations().DeleteAndJoin( *pNewRedl ); - meRedlineFlags = eOld; - } - delete pNewRedl; - pNewRedl = nullptr; } + + if( bCompress ) + CompressRedlines(); + CHECK_REDLINE( *this ) return (nullptr != pNewRedl)