summaryrefslogtreecommitdiff
path: root/sw/source
diff options
context:
space:
mode:
authorLászló Németh <nemeth@numbertext.org>2021-02-24 15:05:38 +0100
committerLászló Németh <nemeth@numbertext.org>2021-02-25 08:42:13 +0100
commitd325cd0c69b7c0cc4f47105749a98995de81cc9d (patch)
tree3932106b70b3c700d38f2ba0c447e98419f5eda1 /sw/source
parentb5422296c55b3fe7b1f96920263feb9c2f97f51d (diff)
tdf#115815 sw: fix lost annotation ranges of redlines
Annotations of tracked deletions lost their ranges during ODF export, according to the limitation of ODF or its recent implementation. As a workaround, save and restore the start of the annotation ranges using temporary bookmarks (which can be part of text:deletion). Note: maybe it's possible to split redline ranges regarding to the start of the annotation ranges, mixing tracked deletions with normal text or tracked insertions, but this would be a not backward compatible solution, because the ODF import of this file inserts extra (not tracked) spaces around the annotation, losing the original text content. Change-Id: I786993a05ee1683076e213374a92969d1856cf8c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/111489 Tested-by: László Németh <nemeth@numbertext.org> Reviewed-by: László Németh <nemeth@numbertext.org>
Diffstat (limited to 'sw/source')
-rw-r--r--sw/source/core/doc/docbm.cxx28
-rw-r--r--sw/source/core/doc/docredln.cxx29
-rw-r--r--sw/source/core/inc/MarkManager.hxx2
-rw-r--r--sw/source/filter/xml/swxml.cxx4
-rw-r--r--sw/source/filter/xml/wrtxml.cxx4
5 files changed, 67 insertions, 0 deletions
diff --git a/sw/source/core/doc/docbm.cxx b/sw/source/core/doc/docbm.cxx
index 7adb634b281b..9061e7b853d1 100644
--- a/sw/source/core/doc/docbm.cxx
+++ b/sw/source/core/doc/docbm.cxx
@@ -1641,6 +1641,34 @@ namespace sw::mark
CompareIMarkStartsAfter());
}
+ // restore text ranges of annotations of tracked deletions
+ // based on the helper bookmarks (which can survive I/O and hiding redlines)
+ void MarkManager::restoreAnnotationMarks()
+ {
+ for (auto iter = getBookmarksBegin();
+ iter != getBookmarksEnd(); )
+ {
+ const OUString & rBookmarkName = (**iter).GetName();
+ sal_Int32 nPos;
+ if ( rBookmarkName.startsWith("__Annotation__") &&
+ (nPos = rBookmarkName.indexOf("____")) > -1 )
+ {
+ ::sw::UndoGuard const undoGuard(m_rDoc.GetIDocumentUndoRedo());
+ IDocumentMarkAccess::const_iterator_t pMark = findAnnotationMark(rBookmarkName.copy(0, nPos));
+ if ( pMark != getAnnotationMarksEnd() )
+ {
+ const SwPaM aPam((**iter).GetMarkStart(), (**pMark).GetMarkEnd());
+ repositionMark(*pMark, aPam);
+ }
+ deleteMark(&**iter);
+ // this invalidates iter, have to start over...
+ iter = getBookmarksBegin();
+ }
+ else
+ ++iter;
+ }
+ }
+
OUString MarkManager::getUniqueMarkName(const OUString& rName) const
{
OSL_ENSURE(rName.getLength(),
diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
index 207ed07dd95c..292600a171d6 100644
--- a/sw/source/core/doc/docredln.cxx
+++ b/sw/source/core/doc/docredln.cxx
@@ -1442,6 +1442,35 @@ void SwRangeRedline::CopyToSection()
SwNodeIndex aNdIdx( *pSttNd, 1 );
SwTextNode* pTextNd = aNdIdx.GetNode().GetTextNode();
SwPosition aPos( aNdIdx, SwIndex( pTextNd ));
+
+ // tdf#115815 keep original start position of collapsed annotation ranges
+ // as temporary bookmarks (removed after file saving and file loading)
+ auto & rDMA(*rDoc.getIDocumentMarkAccess());
+ for (auto iter = rDMA.getAnnotationMarksBegin();
+ iter != rDMA.getAnnotationMarksEnd(); )
+ {
+ SwPosition const& rStartPos((**iter).GetMarkStart());
+ if ( *pStt <= rStartPos && rStartPos < *pEnd )
+ {
+ // at start of redlines use a 1-character length bookmark range
+ // instead of a 0-character length bookmark position to avoid its losing
+ sal_Int32 nLen = (*pStt == rStartPos) ? 1 : 0;
+ SwPaM aPam( rStartPos.nNode, rStartPos.nContent.GetIndex(),
+ rStartPos.nNode, rStartPos.nContent.GetIndex() + nLen);
+ ::sw::mark::IMark* pMark = rDMA.makeMark(
+ aPam,
+ (**iter).GetName() + "____",
+ IDocumentMarkAccess::MarkType::BOOKMARK, sw::mark::InsertMode::New);
+ ::sw::mark::IBookmark* pBookmark = dynamic_cast< ::sw::mark::IBookmark* >(pMark);
+ if (pBookmark)
+ {
+ pBookmark->SetKeyCode(vcl::KeyCode());
+ pBookmark->SetShortName(OUString());
+ }
+ }
+ ++iter;
+ }
+
rDoc.getIDocumentContentOperations().CopyRange(*this, aPos, SwCopyFlags::CheckPosInFly);
// Take over the style from the EndNode if needed
diff --git a/sw/source/core/inc/MarkManager.hxx b/sw/source/core/inc/MarkManager.hxx
index 11db9719d439..4bc216ff3c7d 100644
--- a/sw/source/core/inc/MarkManager.hxx
+++ b/sw/source/core/inc/MarkManager.hxx
@@ -117,6 +117,8 @@ namespace sw::mark {
typedef std::vector<sw::mark::MarkBase*> container_t;
+ virtual void restoreAnnotationMarks() override;
+
private:
MarkManager(MarkManager const&) = delete;
diff --git a/sw/source/filter/xml/swxml.cxx b/sw/source/filter/xml/swxml.cxx
index c3d9c50556da..7893321829c6 100644
--- a/sw/source/filter/xml/swxml.cxx
+++ b/sw/source/filter/xml/swxml.cxx
@@ -56,6 +56,7 @@
#include <docfunc.hxx>
#include <IDocumentSettingAccess.hxx>
#include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentMarkAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <DocumentRedlineManager.hxx>
#include <docary.hxx>
@@ -954,6 +955,9 @@ ErrCode XMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPaM, con
}
}
+ // tdf#115815 restore annotation ranges stored in temporary bookmarks
+ rDoc.getIDocumentMarkAccess()->restoreAnnotationMarks();
+
if (xStatusIndicator.is())
{
xStatusIndicator->end();
diff --git a/sw/source/filter/xml/wrtxml.cxx b/sw/source/filter/xml/wrtxml.cxx
index 71445d932f4e..4ae5964a7d2e 100644
--- a/sw/source/filter/xml/wrtxml.cxx
+++ b/sw/source/filter/xml/wrtxml.cxx
@@ -45,6 +45,7 @@
#include <doc.hxx>
#include <docfunc.hxx>
#include <IDocumentRedlineAccess.hxx>
+#include <IDocumentMarkAccess.hxx>
#include <IDocumentStatistics.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <rootfrm.hxx>
@@ -409,6 +410,9 @@ ErrCode SwXMLWriter::Write_( const uno::Reference < task::XStatusIndicator >& xS
nRedlineFlags |= nOrigRedlineFlags & RedlineFlags::ShowMask;
m_pDoc->getIDocumentRedlineAccess().SetRedlineFlags( nRedlineFlags );
+ // tdf#115815 restore annotation ranges collapsed by hide redlines
+ m_pDoc->getIDocumentMarkAccess()->restoreAnnotationMarks();
+
if (xStatusIndicator.is())
{
xStatusIndicator->end();