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-18 18:04:04 +0100 |
commit | a9ee8a09a353617061a376e10c56746813f06a6b (patch) | |
tree | 79ccbf3db2678ac785df3598cde6bcdc63b66420 | |
parent | 3f831e1ad98f965fb03834d65014dbf878b2e480 (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
(cherry picked from commit 1b4fdcf1b13c0be54cd4c4423122580948445069)
-rw-r--r-- | sw/inc/txtftn.hxx | 4 | ||||
-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 |
9 files changed, 27 insertions, 17 deletions
diff --git a/sw/inc/txtftn.hxx b/sw/inc/txtftn.hxx index faf0c727e83a..9d6aa60ff49b 100644 --- a/sw/inc/txtftn.hxx +++ b/sw/inc/txtftn.hxx @@ -26,7 +26,7 @@ class SwNodeIndex; class SwTextNode; class SwNodes; class SwDoc; -class SwFrame; +class SwRootFrame; class SW_DLLPUBLIC SwTextFootnote : public SwTextAttr { @@ -51,7 +51,7 @@ public: void MakeNewTextSection( SwNodes& rNodes ); // Delete the FootnoteFrame from page. - void DelFrames( const SwFrame* ); + void DelFrames(const SwRootFrame *); // Check conditional paragraph styles. void CheckCondColl(); diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx index 994580b529e9..a15c29e50937 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 b469e4169d78..3141980ad662 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 14793f210a83..b2ef40409422 100644 --- a/sw/source/core/text/redlnitr.cxx +++ b/sw/source/core/text/redlnitr.cxx @@ -270,7 +270,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 ea7a0d5ba0c7..5d24dde866b3 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 fa6e26e4ed21..88c0c2df3c64 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 5b7d5366bae1..8352db8aa2a7 100644 --- a/sw/source/core/undo/undel.cxx +++ b/sw/source/core/undo/undel.cxx @@ -1095,6 +1095,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 @@ -1105,7 +1106,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 } } |