diff options
author | Michael Stahl <mstahl@redhat.com> | 2017-08-18 23:05:53 +0200 |
---|---|---|
committer | Michael Stahl <mstahl@redhat.com> | 2017-08-21 15:52:41 +0200 |
commit | 685442bf71440e56fa8ae5a572d62f0a1e2c3200 (patch) | |
tree | cb207dcd0cb8b52dfb77ea61df8c60fda68c713b | |
parent | 38fa44435a428685b4ac59ee98972a8521942225 (diff) |
tdf#111524 sw: delete annotation marks when creating delete redline
Range annotations are represented by a SwPostItField at the end of the
annotated range, and a AnnotationMark that covers the range (including
the field).
During a normal delete, SwUndoDelete calls
SwUndoSaveContent::DelContentIndex(), which has a special case to remove
the AnnotationMark if the field is deleted.
The problem is that when change tracking is enabled, the AnnotationMark
survives, but the field is moved out of the paragraph when the redlines
are hidden (as happens during ODF export), hence
lcl_FillAnnotationStartArray() doesn't find its field.
There doesn't appear to be a good solution to this, because in ODF it's
also not possible to represent this, because the deleted content is
outside the text:p element.
It doesn't work to delete the annotation mark in DelBookmarks(), when
hiding the redline, because then no Undo is created to restore
the mark, and DelBookmarks() is also called from Undo code from
SwUndoDelete, which breaks with this change.
So delete the annotation mark when creating the redline in
DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl().
Fixes the assert and the subsequent crash, which is a regression
from 31c54fa7bb03768b425ae019096e0a0e26e9c736.
Change-Id: I361ffee8e6ab86de499c25f34a96ceeaf83d9e0b
-rw-r--r-- | sw/source/core/doc/DocumentContentOperationsManager.cxx | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index 42572905e79c..45d192443d66 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -52,6 +52,7 @@ #include <txatbase.hxx> #include <UndoRedline.hxx> #include <undobj.hxx> +#include <UndoBookmark.hxx> #include <UndoDelete.hxx> #include <UndoSplitMove.hxx> #include <UndoOverwrite.hxx> @@ -73,6 +74,7 @@ #include <svx/svdouno.hxx> #include <tools/globname.hxx> #include <editeng/formatbreakitem.hxx> +#include <o3tl/make_unique.hxx> #include <com/sun/star/i18n/Boundary.hpp> #include <memory> @@ -3556,6 +3558,36 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa SwUndoRedlineDelete* pUndo = nullptr; RedlineFlags eOld = m_rDoc.getIDocumentRedlineAccess().GetRedlineFlags(); m_rDoc.GetDocumentRedlineManager().checkRedlining( eOld ); + + auto & rDMA(*m_rDoc.getIDocumentMarkAccess()); + std::vector<std::unique_ptr<SwUndo>> MarkUndos; + for (auto iter = rDMA.getAnnotationMarksBegin(); + iter != rDMA.getAnnotationMarksEnd(); ) + { + // tdf#111524 remove annotation marks that have their field + // characters deleted + SwPosition const& rEndPos((**iter).GetMarkEnd()); + if (*rPam.Start() < rEndPos && rEndPos <= *rPam.End()) + { + if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) + { + MarkUndos.emplace_back(o3tl::make_unique<SwUndoDeleteBookmark>(**iter)); + } + // iter is into annotation mark vector so must be dereferenced! + rDMA.deleteMark(&**iter); + // this invalidates iter, have to start over... + iter = rDMA.getAnnotationMarksBegin(); + } + else + { // marks are sorted by start + if (*rPam.End() < (**iter).GetMarkStart()) + { + break; + } + ++iter; + } + } + if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) { @@ -3564,10 +3596,13 @@ 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) + { + m_rDoc.GetIDocumentUndoRedo().AppendUndo(it.release()); + } m_rDoc.GetIDocumentUndoRedo().AppendUndo( pUndo ); } |