summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <mstahl@redhat.com>2017-08-18 23:05:53 +0200
committerMichael Stahl <mstahl@redhat.com>2017-08-21 15:52:41 +0200
commit685442bf71440e56fa8ae5a572d62f0a1e2c3200 (patch)
treecb207dcd0cb8b52dfb77ea61df8c60fda68c713b
parent38fa44435a428685b4ac59ee98972a8521942225 (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.cxx37
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 );
}