summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2018-12-11 14:45:01 +0100
committerMichael Stahl <Michael.Stahl@cib.de>2018-12-18 18:04:04 +0100
commita9ee8a09a353617061a376e10c56746813f06a6b (patch)
tree79ccbf3db2678ac785df3598cde6bcdc63b66420
parent3f831e1ad98f965fb03834d65014dbf878b2e480 (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.hxx4
-rw-r--r--sw/source/core/doc/DocumentRedlineManager.cxx8
-rw-r--r--sw/source/core/inc/ftnfrm.hxx4
-rw-r--r--sw/source/core/layout/wsfrm.cxx7
-rw-r--r--sw/source/core/text/redlnitr.cxx2
-rw-r--r--sw/source/core/text/txtfrm.cxx8
-rw-r--r--sw/source/core/txtnode/atrftn.cxx3
-rw-r--r--sw/source/core/txtnode/ndtxt.cxx4
-rw-r--r--sw/source/core/undo/undel.cxx4
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
}
}