diff options
-rw-r--r-- | sw/inc/redline.hxx | 7 | ||||
-rw-r--r-- | sw/source/core/doc/DocumentContentOperationsManager.cxx | 105 | ||||
-rw-r--r-- | sw/source/core/doc/docredln.cxx | 41 |
3 files changed, 109 insertions, 44 deletions
diff --git a/sw/inc/redline.hxx b/sw/inc/redline.hxx index 8b6e2a27a0c3..4afc978cd743 100644 --- a/sw/inc/redline.hxx +++ b/sw/inc/redline.hxx @@ -340,6 +340,13 @@ class SW_DLLPUBLIC SwRedlineHint : public SfxHint { }; + +namespace sw { + +std::vector<SwRangeRedline*> GetAllValidRanges(std::unique_ptr<SwRangeRedline> p); + +} // namespace sw + #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index e0f071dddcb6..1e15c9a22fc2 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -3580,10 +3580,32 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa { assert(m_rDoc.getIDocumentRedlineAccess().IsRedlineOn()); - SwUndoRedlineDelete* pUndo = nullptr; RedlineFlags eOld = m_rDoc.getIDocumentRedlineAccess().GetRedlineFlags(); m_rDoc.GetDocumentRedlineManager().checkRedlining( eOld ); + if (*rPam.GetPoint() == *rPam.GetMark()) + { + return false; // do not add empty redlines + } + + std::vector<SwRangeRedline*> redlines; + { + auto pRedline(o3tl::make_unique<SwRangeRedline>(nsRedlineType_t::REDLINE_DELETE, rPam)); + if (pRedline->HasValidRange()) + { + redlines.push_back(pRedline.release()); + } + else // sigh ... why is such a selection even possible... + { // split it up so we get one SwUndoRedlineDelete per inserted RL + redlines = GetAllValidRanges(std::move(pRedline)); + } + } + + if (redlines.empty()) + { + return false; + } + auto & rDMA(*m_rDoc.getIDocumentMarkAccess()); std::vector<std::unique_ptr<SwUndo>> MarkUndos; for (auto iter = rDMA.getAnnotationMarksBegin(); @@ -3617,6 +3639,7 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa if (*rPam.GetPoint() != *rPam.GetMark()) m_rDoc.getIDocumentRedlineAccess().AcceptRedlineParagraphFormatting(rPam); + std::vector<std::unique_ptr<SwUndoRedlineDelete>> undos; if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) { /* please don't translate -- for cultural reasons this comment is protected @@ -3624,47 +3647,61 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa //JP 06.01.98: MUSS noch optimiert werden!!! m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags( RedlineFlags::On | RedlineFlags::ShowInsert | RedlineFlags::ShowDelete); - pUndo = new SwUndoRedlineDelete( rPam, SwUndoId::DELETE ); - const SwRewriter aRewriter = pUndo->GetRewriter(); - m_rDoc.GetIDocumentUndoRedo().StartUndo( SwUndoId::DELETE, &aRewriter ); - for (auto& it : MarkUndos) + for (SwRangeRedline * pRedline : redlines) + { + assert(pRedline->HasValidRange()); + undos.emplace_back(o3tl::make_unique<SwUndoRedlineDelete>( + *pRedline, SwUndoId::DELETE)); + } + const SwRewriter aRewriter = undos.front()->GetRewriter(); + // can only group a single undo action + if (MarkUndos.empty() && undos.size() == 1 + && m_rDoc.GetIDocumentUndoRedo().DoesGroupUndo()) { - m_rDoc.GetIDocumentUndoRedo().AppendUndo(it.release()); + SwUndo * const pLastUndo( m_rDoc.GetUndoManager().GetLastUndo() ); + SwUndoRedlineDelete *const pUndoRedlineDel(dynamic_cast<SwUndoRedlineDelete*>(pLastUndo)); + bool const bMerged = pUndoRedlineDel + && pUndoRedlineDel->CanGrouping(*undos.front()); + if (!bMerged) + { + m_rDoc.GetIDocumentUndoRedo().AppendUndo(undos.front().release()); + } + undos.clear(); // prevent unmatched EndUndo + } + else + { + m_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE, &aRewriter); + for (auto& it : MarkUndos) + { + m_rDoc.GetIDocumentUndoRedo().AppendUndo(it.release()); + } + for (auto & it : undos) + { + m_rDoc.GetIDocumentUndoRedo().AppendUndo(it.release()); + } } - m_rDoc.GetIDocumentUndoRedo().AppendUndo( pUndo ); } - if (*rPam.GetPoint() != *rPam.GetMark()) - m_rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_DELETE, rPam ), true ); + for (SwRangeRedline *const pRedline : redlines) + { + // note: 1. the pRedline can still be merged & deleted + // 2. the impl. can even DeleteAndJoin the range => no plain PaM + std::shared_ptr<SwUnoCursor> const pCursor(m_rDoc.CreateUnoCursor(*pRedline->GetMark())); + pCursor->SetMark(); + *pCursor->GetPoint() = *pRedline->GetPoint(); + m_rDoc.getIDocumentRedlineAccess().AppendRedline(pRedline, true); + // 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(*pCursor); + } 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) + if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) { - m_rDoc.GetIDocumentUndoRedo().EndUndo( SwUndoId::EMPTY, nullptr ); - // ??? why the hell is the AppendUndo not below the - // CanGrouping, so this hideous cleanup wouldn't be necessary? - // bah, this is redlining, probably changing this would break it... - if (m_rDoc.GetIDocumentUndoRedo().DoesGroupUndo()) + if (!undos.empty()) { - SwUndo * const pLastUndo( m_rDoc.GetUndoManager().GetLastUndo() ); - SwUndoRedlineDelete *const pUndoRedlineDel( dynamic_cast<SwUndoRedlineDelete*>(pLastUndo) ); - if (pUndoRedlineDel) - { - bool const bMerged = pUndoRedlineDel->CanGrouping( *pUndo ); - if (bMerged) - { - ::sw::UndoGuard const undoGuard( m_rDoc.GetIDocumentUndoRedo() ); - SwUndo const*const pDeleted = m_rDoc.GetUndoManager().RemoveLastUndo(); - OSL_ENSURE( pDeleted == pUndo, "DeleteAndJoinWithRedlineImpl: " - "undo removed is not undo inserted?" ); - delete pDeleted; - } - } + m_rDoc.GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr); } //JP 06.01.98: MUSS noch optimiert werden!!! m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags( eOld ); diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx index b943ca7f23aa..a1987f55dd6e 100644 --- a/sw/source/core/doc/docredln.cxx +++ b/sw/source/core/doc/docredln.cxx @@ -454,10 +454,12 @@ bool SwRedlineTable::Insert(SwRangeRedlinePtr& p, size_type& rP) return InsertWithValidRanges( p, &rP ); } -bool SwRedlineTable::InsertWithValidRanges(SwRangeRedlinePtr& p, size_type* pInsPos) +namespace sw { + +std::vector<SwRangeRedline*> GetAllValidRanges(std::unique_ptr<SwRangeRedline> p) { + std::vector<SwRangeRedline*> ret; // Create valid "sub-ranges" from the Selection - bool bAnyIns = false; SwPosition* pStt = p->Start(), * pEnd = pStt == p->GetPoint() ? p->GetMark() : p->GetPoint(); SwPosition aNewStt( *pStt ); @@ -474,7 +476,6 @@ bool SwRedlineTable::InsertWithValidRanges(SwRangeRedlinePtr& p, size_type* pIns } SwRangeRedline* pNew = nullptr; - size_type nInsPos; if( aNewStt < *pEnd ) do { @@ -542,14 +543,10 @@ bool SwRedlineTable::InsertWithValidRanges(SwRangeRedlinePtr& p, size_type* pIns #endif if( *pNew->GetPoint() != *pNew->GetMark() && - pNew->HasValidRange() && - Insert( pNew, nInsPos ) ) + pNew->HasValidRange()) { - pNew->CallDisplayFunc(nInsPos); - bAnyIns = true; + ret.push_back(pNew); pNew = nullptr; - if( pInsPos && *pInsPos < nInsPos ) - *pInsPos = nInsPos; } if( aNewStt >= *pEnd || @@ -561,7 +558,31 @@ bool SwRedlineTable::InsertWithValidRanges(SwRangeRedlinePtr& p, size_type* pIns } while( aNewStt < *pEnd ); delete pNew; - delete p; + p.reset(); + return ret; +} + +} // namespace sw + +bool SwRedlineTable::InsertWithValidRanges(SwRangeRedlinePtr& p, size_type* pInsPos) +{ + bool bAnyIns = false; + std::vector<SwRangeRedline*> const redlines( + GetAllValidRanges(std::unique_ptr<SwRangeRedline>(p))); + for (SwRangeRedline * pRedline : redlines) + { + assert(pRedline->HasValidRange()); + size_type nInsPos; + if (Insert(pRedline, nInsPos)) + { + pRedline->CallDisplayFunc(nInsPos); + bAnyIns = true; + if (pInsPos && *pInsPos < nInsPos) + { + *pInsPos = nInsPos; + } + } + } p = nullptr; return bAnyIns; } |