From ab90d83d73b701747a56e09f71e3609a92378504 Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Thu, 21 Nov 2019 13:38:38 +0100 Subject: sw: check fieldmark overlap in SwpHints::TryInsertNesting() This is a follow-up to bd2ada701aad2c4e85d03cd8db68eaeae081d91c, which added the check for nesting hints in MarkManager::makeMark(). Change-Id: Ife847a677514fb1aeb28dc8d6254caea365b754d Reviewed-on: https://gerrit.libreoffice.org/83388 Tested-by: Jenkins Reviewed-by: Michael Stahl --- .../core/doc/DocumentContentOperationsManager.cxx | 18 ++++---- .../core/inc/DocumentContentOperationsManager.hxx | 3 ++ sw/source/core/txtnode/thints.cxx | 48 +++++++++++++++++++--- 3 files changed, 56 insertions(+), 13 deletions(-) diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index 3b9433619ae6..731bac5b7b49 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -484,10 +484,10 @@ namespace } //local functions originally from sw/source/core/doc/docedt.cxx -namespace +namespace sw { - void - lcl_CalcBreaks(std::vector> & rBreaks, SwPaM const & rPam, bool const isOnlyFieldmarks = false) + void CalcBreaks(std::vector> & rBreaks, + SwPaM const & rPam, bool const isOnlyFieldmarks) { sal_uLong const nStartNode(rPam.Start()->nNode.GetIndex()); sal_uLong const nEndNode(rPam.End()->nNode.GetIndex()); @@ -589,13 +589,17 @@ namespace rBreaks.insert(it, pos); } } +} + +namespace +{ bool lcl_DoWithBreaks(::sw::DocumentContentOperationsManager & rDocumentContentOperations, SwPaM & rPam, bool (::sw::DocumentContentOperationsManager::*pFunc)(SwPaM&, bool), const bool bForceJoinNext = false) { std::vector> Breaks; - lcl_CalcBreaks(Breaks, rPam); + sw::CalcBreaks(Breaks, rPam); if (Breaks.empty()) { @@ -1802,7 +1806,7 @@ namespace mark bool IsFieldmarkOverlap(SwPaM const& rPaM) { std::vector> Breaks; - lcl_CalcBreaks(Breaks, rPaM); + sw::CalcBreaks(Breaks, rPaM); return !Breaks.empty(); } } @@ -3181,7 +3185,7 @@ bool DocumentContentOperationsManager::ReplaceRange( SwPaM& rPam, const OUString } OSL_ENSURE((aPam.GetPoint()->nNode == aPam.GetMark()->nNode), "invalid pam?"); - lcl_CalcBreaks(Breaks, aPam); + sw::CalcBreaks(Breaks, aPam); while (!Breaks.empty() // skip over prefix of dummy chars && (aPam.GetMark()->nNode.GetIndex() == Breaks.begin()->first) @@ -4444,7 +4448,7 @@ bool DocumentContentOperationsManager::CopyImpl(SwPaM& rPam, SwPosition& rPos, { std::vector> Breaks; - lcl_CalcBreaks(Breaks, rPam, true); + sw::CalcBreaks(Breaks, rPam, true); if (Breaks.empty()) { diff --git a/sw/source/core/inc/DocumentContentOperationsManager.hxx b/sw/source/core/inc/DocumentContentOperationsManager.hxx index bf765d291d46..21829eaf22a5 100644 --- a/sw/source/core/inc/DocumentContentOperationsManager.hxx +++ b/sw/source/core/inc/DocumentContentOperationsManager.hxx @@ -180,6 +180,9 @@ private: void CopyBookmarks(const SwPaM& rPam, SwPosition& rTarget); +void CalcBreaks(std::vector> & rBreaks, + SwPaM const & rPam, bool const isOnlyFieldmarks = false); + } #endif // INCLUDED_SW_SOURCE_CORE_INC_DOCUMENTCONTENTOPERATIONSMANAGER_HXX diff --git a/sw/source/core/txtnode/thints.cxx b/sw/source/core/txtnode/thints.cxx index 0005d65e276a..35819fa8214d 100644 --- a/sw/source/core/txtnode/thints.cxx +++ b/sw/source/core/txtnode/thints.cxx @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -259,6 +260,19 @@ MakeTextAttrNesting(SwTextNode & rNode, SwTextAttrNesting & rNesting, typedef std::vector NestList_t; +static NestList_t::iterator +lcl_DoSplitImpl(NestList_t & rSplits, SwTextNode & rNode, + NestList_t::iterator const iter, sal_Int32 const nSplitPos, + bool const bSplitAtStart, bool const bOtherDummy) +{ + const sal_Int32 nStartPos( // skip other's dummy character! + (bSplitAtStart && bOtherDummy) ? nSplitPos + 1 : nSplitPos ); + SwTextAttrNesting * const pNew( MakeTextAttrNesting( + rNode, **iter, nStartPos, *(*iter)->GetEnd() ) ); + (*iter)->SetEnd(nSplitPos); + return rSplits.insert(iter + 1, pNew); +} + static void lcl_DoSplitNew(NestList_t & rSplits, SwTextNode & rNode, const sal_Int32 nNewStart, @@ -274,12 +288,7 @@ lcl_DoSplitNew(NestList_t & rSplits, SwTextNode & rNode, } ) ); if (iter != rSplits.end()) // already split here? { - const sal_Int32 nStartPos( // skip other's dummy character! - (bSplitAtStart && bOtherDummy) ? nSplitPos + 1 : nSplitPos ); - SwTextAttrNesting * const pNew( MakeTextAttrNesting( - rNode, **iter, nStartPos, *(*iter)->GetEnd() ) ); - (*iter)->SetEnd(nSplitPos); - rSplits.insert(iter + 1, pNew); + lcl_DoSplitImpl(rSplits, rNode, iter, nSplitPos, bSplitAtStart, bOtherDummy); } } @@ -441,6 +450,33 @@ SwpHints::TryInsertNesting( SwTextNode & rNode, SwTextAttrNesting & rNewHint ) } } + // pass 1b: tragically need to check for fieldmarks here too + for (auto iter = SplitNew.begin(); iter != SplitNew.end(); ++iter) + { + SwPaM const temp(rNode, (*iter)->GetStart(), rNode, *(*iter)->GetEnd()); + std::vector> Breaks; + sw::CalcBreaks(Breaks, temp, true); + if (!Breaks.empty()) + { + if (!isSplittable(nNewWhich)) + { + SAL_INFO("sw.core", "cannot insert hint: fieldmark overlap"); + assert(SplitNew.size() == 1); + TextAttrDelete(*rNode.GetDoc(), &rNewHint); + return false; + } + else + { + for (auto const& rPos : Breaks) + { + assert(rPos.first == rNode.GetIndex()); + iter = lcl_DoSplitImpl(SplitNew, rNode, iter, + rPos.second, true, true); + } + } + } + } + assert((isSplittable(nNewWhich) || SplitNew.size() == 1) && "splitting the unsplittable ???"); -- cgit