summaryrefslogtreecommitdiff
path: root/sw/source
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2020-05-04 14:22:09 +0200
committerMichael Stahl <michael.stahl@cib.de>2020-05-04 16:38:50 +0200
commit49f26e7dae550aff6ca90b3cda7f89e11ac8cfd4 (patch)
tree2c5e9a8e2698c9e855a5b502c90e7ef6055fbd28 /sw/source
parentf6ac5e863c3c432c3b5e2643f16aa99a44a4e436 (diff)
tdf#132187 sw: fix creation of frames on end node in CopyWithFlyInFly()
The problem is that the rInsPos node is included in the range passed to MakeFrames(), but it already has a frame, so now it has 2 and that means the next call to MakeFrames() in this position will create all the frames twice. This is tricky because while in practice there is currently only one layout in theory there could be multiple, and then it could happen that RecreateStartTextFrames() will destroy the node's frame in one layout but not the other, while MakeFrames() always works on all layouts. Fix this by checking if all the existing frames survive RecreateStartTextFrames() and if it's not the case (like in tdf#130685) explicitly delete all the frames and including the node in MakeFrames(). (regression from 166b5010b402a41b192b1659093a25acf9065fd9) Change-Id: I1bba11da053fe1c6359b2f76f3a352e44c6a2a1d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93416 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.stahl@cib.de>
Diffstat (limited to 'sw/source')
-rw-r--r--sw/source/core/doc/DocumentContentOperationsManager.cxx36
1 files changed, 35 insertions, 1 deletions
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 771c4885004f..6e907d7495c7 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -3438,6 +3438,7 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
if (rRg.aStart != rRg.aEnd)
{
bool bEndIsEqualEndPos = rInsPos == rRg.aEnd;
+ bool isRecreateEndNode(false);
--aSavePos;
SaveRedlEndPosForRestore aRedlRest( rInsPos, 0 );
@@ -3448,7 +3449,40 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
{ // recreate from previous node (could be merged now)
if (SwTextNode *const pNode = aSavePos.GetNode().GetTextNode())
{
+ std::unordered_set<SwTextFrame*> frames;
+ SwTextNode *const pEndNode = rInsPos.GetNode().GetTextNode();
+ if (pEndNode)
+ {
+ SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pEndNode);
+ for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+ {
+ if (pFrame->getRootFrame()->IsHideRedlines())
+ {
+ frames.insert(pFrame);
+ }
+ }
+ }
sw::RecreateStartTextFrames(*pNode);
+ if (!frames.empty())
+ { // tdf#132187 check if the end node needs new frames
+ SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pEndNode);
+ for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+ {
+ if (pFrame->getRootFrame()->IsHideRedlines())
+ {
+ auto const it = frames.find(pFrame);
+ if (it != frames.end())
+ {
+ frames.erase(it);
+ }
+ }
+ }
+ if (!frames.empty()) // existing frame was deleted
+ { // all layouts because MakeFrames recreates all layouts
+ pEndNode->DelFrames(nullptr);
+ isRecreateEndNode = true;
+ }
+ }
}
}
bool const isAtStartOfSection(aSavePos.GetNode().IsStartNode());
@@ -3460,7 +3494,7 @@ void DocumentContentOperationsManager::CopyWithFlyInFly(
// if it was the first node in the document so that MakeFrames()
// will find the existing (wasn't deleted) frame on it
SwNodeIndex const end(rInsPos,
- (rInsPos.GetNode().IsEndNode() || isAtStartOfSection)
+ (!isRecreateEndNode || isAtStartOfSection)
? 0 : +1);
::MakeFrames(pDest, aSavePos, end);
}