diff options
author | Michael Stahl <Michael.Stahl@cib.de> | 2018-12-11 14:45:01 +0100 |
---|---|---|
committer | Michael Stahl <Michael.Stahl@cib.de> | 2018-12-17 18:04:07 +0100 |
commit | e843b8571dcc6d6b5920bccbe06fe671650cb33c (patch) | |
tree | 24fb260b4c68a2529b4947fafd15ede2816d1c5e /sw/source/core | |
parent | a92411b1abfde9a45551055f89addd352d52ebba (diff) |
sw_redlinehide_4b: FrameMode::Existing is not idempotent
... so use it only once. The problem is that the second time it will
call DelFrames() on every non-first node, which then empties the first
frame's newly created MergedPara instance.
This can be reproduced by toggling Edit->Tracked Changes->Show in
tdf99766-2.odt.
Also change some function parameters on e.g. SwTextFootnote::DelFrames()
to SwRootFrame to make it obvious that these don't actually need a
particular SwTextFrame.
Change-Id: I129be5db4a30546905c24c5e8820a5f105a33109
Diffstat (limited to 'sw/source/core')
-rw-r--r-- | sw/source/core/doc/DocumentRedlineManager.cxx | 8 | ||||
-rw-r--r-- | sw/source/core/inc/ftnfrm.hxx | 4 | ||||
-rw-r--r-- | sw/source/core/layout/wsfrm.cxx | 7 | ||||
-rw-r--r-- | sw/source/core/text/redlnitr.cxx | 2 | ||||
-rw-r--r-- | sw/source/core/text/txtfrm.cxx | 8 | ||||
-rw-r--r-- | sw/source/core/txtnode/atrftn.cxx | 3 | ||||
-rw-r--r-- | sw/source/core/txtnode/ndtxt.cxx | 4 | ||||
-rw-r--r-- | sw/source/core/undo/undel.cxx | 4 |
8 files changed, 25 insertions, 15 deletions
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index de795085681d..377d776a7db2 100644 --- a/sw/source/core/doc/DocumentRedlineManager.cxx +++ b/sw/source/core/doc/DocumentRedlineManager.cxx @@ -171,6 +171,7 @@ void UpdateFramesForAddDeleteRedline(SwDoc & rDoc, SwPaM const& rPam) frames.push_back(pFrame); } } + auto eMode(sw::FrameMode::Existing); for (SwTextFrame * pFrame : frames) { SwTextNode & rFirstNode(pFrame->GetMergedPara() @@ -180,7 +181,8 @@ void UpdateFramesForAddDeleteRedline(SwDoc & rDoc, SwPaM const& rPam) // clear old one first to avoid DelFrames confusing updates & asserts... pFrame->SetMergedPara(nullptr); pFrame->SetMergedPara(sw::CheckParaRedlineMerge( - *pFrame, rFirstNode, sw::FrameMode::Existing)); + *pFrame, rFirstNode, eMode)); + eMode = sw::FrameMode::New; // Existing is not idempotent! // the first node of the new redline is not necessarily the first // node of the merged frame, there could be another redline nearby sw::AddRemoveFlysAnchoredToFrameStartingAtNode(*pFrame, *pStartNode, nullptr); @@ -234,6 +236,7 @@ void UpdateFramesForRemoveDeleteRedline(SwDoc & rDoc, SwPaM const& rPam) { // first, call CheckParaRedlineMerge on the first paragraph, // to init flag on new merge range (if any) + 1st node post the merge + auto eMode(sw::FrameMode::Existing); for (SwTextFrame * pFrame : frames) { if (auto const pMergedPara = pFrame->GetMergedPara()) @@ -243,7 +246,8 @@ void UpdateFramesForRemoveDeleteRedline(SwDoc & rDoc, SwPaM const& rPam) SwTextNode & rFirstNode(*pMergedPara->pFirstNode); pFrame->SetMergedPara(nullptr); pFrame->SetMergedPara(sw::CheckParaRedlineMerge( - *pFrame, rFirstNode, sw::FrameMode::Existing)); + *pFrame, rFirstNode, eMode)); + eMode = sw::FrameMode::New; // Existing is not idempotent! } } // now start node until end of merge + 1 has proper flags; MakeFrames diff --git a/sw/source/core/inc/ftnfrm.hxx b/sw/source/core/inc/ftnfrm.hxx index c0848948848f..1d2ddafb8385 100644 --- a/sw/source/core/inc/ftnfrm.hxx +++ b/sw/source/core/inc/ftnfrm.hxx @@ -23,7 +23,7 @@ #include "layfrm.hxx" class SwContentFrame; -class SwTextFrame; +class SwRootFrame; class SwTextNode; class SwTextFootnote; class SwBorderAttrs; @@ -34,7 +34,7 @@ void sw_RemoveFootnotes( SwFootnoteBossFrame* pBoss, bool bPageOnly, bool bEndNo namespace sw { void RemoveFootnotesForNode( - SwTextFrame const& rTextFrame, SwTextNode const& rTextNode, + SwRootFrame const& rLayout, SwTextNode const& rTextNode, std::vector<std::pair<sal_Int32, sal_Int32>> const*const pExtents); } diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index 0a3d6ee6b66d..03997c7b7e81 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -4256,6 +4256,7 @@ static void UnHideRedlines(SwRootFrame & rLayout, } } // this messes with pRegisteredIn so do it outside SwIterator + auto eMode(sw::FrameMode::Existing); for (SwTextFrame * pFrame : frames) { if (rLayout.IsHideRedlines()) @@ -4266,7 +4267,7 @@ static void UnHideRedlines(SwRootFrame & rLayout, { { auto pMerged(CheckParaRedlineMerge(*pFrame, - rTextNode, sw::FrameMode::Existing)); + rTextNode, eMode)); pFrame->SetMergedPara(std::move(pMerged)); } auto const pMerged(pFrame->GetMergedPara()); @@ -4285,6 +4286,8 @@ static void UnHideRedlines(SwRootFrame & rLayout, } } sw::AddRemoveFlysAnchoredToFrameStartingAtNode(*pFrame, rTextNode, pSkipped); + // only *first* frame of node gets Existing because it + eMode = sw::FrameMode::New; // is not idempotent! } } else @@ -4324,7 +4327,7 @@ static void UnHideRedlines(SwRootFrame & rLayout, } else if (pNode->IsTextNode()) { - sw::RemoveFootnotesForNode(*pFrame, *pNode->GetTextNode(), nullptr); + sw::RemoveFootnotesForNode(rLayout, *pNode->GetTextNode(), nullptr); // similarly, remove the anchored flys if (auto const pFlys = pNode->GetAnchoredFlys()) { diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx index 7f4669290f9c..f948d0de950b 100644 --- a/sw/source/core/text/redlnitr.cxx +++ b/sw/source/core/text/redlnitr.cxx @@ -269,7 +269,7 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode, { hidden.emplace_back(nLast, pTextNode->Len()); } - sw::RemoveFootnotesForNode(rFrame, *pTextNode, &hidden); + sw::RemoveFootnotesForNode(*rFrame.getRootFrame(), *pTextNode, &hidden); } // unfortunately DelFrames() must be done before StartListening too, // otherwise footnotes cannot be deleted by SwTextFootnote::DelFrames! diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx index 7da4466d6c5d..2d17e3ec723c 100644 --- a/sw/source/core/text/txtfrm.cxx +++ b/sw/source/core/text/txtfrm.cxx @@ -738,7 +738,7 @@ SwTextFrame::SwTextFrame(SwTextNode * const pNode, SwFrame* pSib ) namespace sw { void RemoveFootnotesForNode( - SwTextFrame const& rTextFrame, SwTextNode const& rTextNode, + SwRootFrame const& rLayout, SwTextNode const& rTextNode, std::vector<std::pair<sal_Int32, sal_Int32>> const*const pExtents) { if (pExtents && pExtents->empty()) @@ -777,7 +777,7 @@ void RemoveFootnotesForNode( continue; } } - pTextFootnote->DelFrames( &rTextFrame ); + pTextFootnote->DelFrames(&rLayout); } } @@ -802,7 +802,7 @@ void SwTextFrame::DestroyImpl() // sw_redlinehide: not sure if it's necessary to check // if the nodes are still alive here, which would require // accessing WriterMultiListener::m_vDepends - sw::RemoveFootnotesForNode(*this, *pNode, nullptr); + sw::RemoveFootnotesForNode(*getRootFrame(), *pNode, nullptr); } } } @@ -811,7 +811,7 @@ void SwTextFrame::DestroyImpl() SwTextNode *const pNode(static_cast<SwTextNode*>(GetDep())); if (pNode) { - sw::RemoveFootnotesForNode(*this, *pNode, nullptr); + sw::RemoveFootnotesForNode(*getRootFrame(), *pNode, nullptr); } } } diff --git a/sw/source/core/txtnode/atrftn.cxx b/sw/source/core/txtnode/atrftn.cxx index e1a849b35d2c..81afed72030b 100644 --- a/sw/source/core/txtnode/atrftn.cxx +++ b/sw/source/core/txtnode/atrftn.cxx @@ -445,14 +445,13 @@ void SwTextFootnote::MakeNewTextSection( SwNodes& rNodes ) m_pStartNode.reset(new SwNodeIndex(*pSttNd)); } -void SwTextFootnote::DelFrames( const SwFrame* pSib ) +void SwTextFootnote::DelFrames(SwRootFrame const*const pRoot) { // delete the FootnoteFrames from the pages OSL_ENSURE( m_pTextNode, "SwTextFootnote: where is my TextNode?" ); if ( !m_pTextNode ) return; - const SwRootFrame* pRoot = pSib ? pSib->getRootFrame() : nullptr; bool bFrameFnd = false; { SwIterator<SwContentFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*m_pTextNode); diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx index e1df1ea4dea9..2db52f511bbc 100644 --- a/sw/source/core/txtnode/ndtxt.cxx +++ b/sw/source/core/txtnode/ndtxt.cxx @@ -911,6 +911,7 @@ void CheckResetRedlineMergeFlag(SwTextNode & rNode, Recreate const eRecreateMerg frames.push_back(pFrame); } } + auto eMode(sw::FrameMode::Existing); for (SwTextFrame * pFrame : frames) { SwTextNode & rFirstNode(pFrame->GetMergedPara() @@ -918,10 +919,11 @@ void CheckResetRedlineMergeFlag(SwTextNode & rNode, Recreate const eRecreateMerg : *pMergeNode); assert(rFirstNode.GetIndex() <= rNode.GetIndex()); pFrame->SetMergedPara(sw::CheckParaRedlineMerge( - *pFrame, rFirstNode, sw::FrameMode::Existing)); + *pFrame, rFirstNode, eMode)); assert(pFrame->GetMergedPara()); assert(pFrame->GetMergedPara()->listener.IsListeningTo(&rNode)); assert(rNode.GetIndex() <= pFrame->GetMergedPara()->pLastNode->GetIndex()); + eMode = sw::FrameMode::New; // Existing is not idempotent! } } else if (rNode.GetRedlineMergeFlag() != SwNode::Merge::None) diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx index 1e4cb8e7fcd9..1ec3a95be66e 100644 --- a/sw/source/core/undo/undel.cxx +++ b/sw/source/core/undo/undel.cxx @@ -1092,6 +1092,7 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) frames.push_back(pFrame); } } + auto eMode(sw::FrameMode::Existing); for (SwTextFrame * pFrame : frames) { // SplitNode could have moved the original frame to the start node @@ -1102,7 +1103,8 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext) : *pStartNode); assert(rFirstNode.GetIndex() <= pStartNode->GetIndex()); pFrame->SetMergedPara(sw::CheckParaRedlineMerge( - *pFrame, rFirstNode, sw::FrameMode::Existing)); + *pFrame, rFirstNode, eMode)); + eMode = sw::FrameMode::New; // Existing is not idempotent! // note: this may or may not delete frames on the end node } } |