[Libreoffice-commits] core.git: Branch 'private/mst/sw_redlinehide_2' - 34 commits - sw/inc sw/source
Libreoffice Gerrit user
logerrit at kemper.freedesktop.org
Wed Aug 15 10:36:39 UTC 2018
Rebased ref, commits from common ancestor:
commit 0f5e41459c4ed1fa751dcee57e6eac3fbb97d7d4
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 14 15:58:35 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: move SwInsText/SwDelText hint in CutImpl before attributes
An unfortunate incident involving a footnote accessing its old anchor
node's layout frame during InsertHint and the MapModelToViewPos needing
to have a mapping for this index...
6 SwTextFrame::MapModelToViewPos(SwPosition const&) const (this=0x8937760, rPos=SwPosition (node 41, offset 4)) at sw/source/core/text/txtfrm.cxx:1005
7 SwTextFrame::GetFrameAtPos(SwPosition const&) (this=0x8937760, rPos=SwPosition (node 41, offset 4)) at sw/source/core/text/frmcrsr.cxx:153
8 GetFrameOfModify(SwRootFrame const*, SwModify const&, SwFrameType, Point const*, SwPosition const*, bool) (pLayout=0x6a0a240, rMod=..., nFrameType=(SwFrameType::Txt | SwFrameType::NoTxt), pPoint=0x0, pPos=0x7ffcfa9d70a0, bCalcFrame=false) at sw/source/core/layout/frmtool.cxx:3517
9 SwContentNode::getLayoutFrame(SwRootFrame const*, Point const*, SwPosition const*, bool) const (this=0x6a67e20, _pRoot=0x6a0a240, pPoint=0x0, pPos=0x7ffcfa9d70a0, bCalcFrame=false) at sw/source/core/docnode/node.cxx:1137
10 SwFootnoteFrame::GetRefFromAttr() (this=0x8970a30) at sw/source/core/layout/ftnfrm.cxx:2839
11 SwContentNode::DelFrames(SwRootFrame const*, bool) (this=0x897ead0, pLayout=0x0, fromDtor=false) at sw/source/core/docnode/node.cxx:1419
12 SwTextNode::InsertHint(SwTextAttr*, SetAttrMode) (this=0x89ac890, pAttr=0x6a3ff60, nMode=(SetAttrMode::DONTREPLACE | SetAttrMode::NOTXTATRCHR)) at sw/source/core/txtnode/thints.cxx:1408
13 SwTextNode::CutImpl(SwTextNode*, SwIndex const&, SwIndex const&, int, bool) (this=0x6a67e20, pDest=0x89ac890, rDestStart=SwIndex (offset 2), rStart=SwIndex (offset 0), nLen=3, bUpdate=false) at sw/source/core/txtnode/ndtxt.cxx:2374
14 SwTextNode::CutText(SwTextNode*, SwIndex const&, int) (this=0x6a67e20, pDest=0x89ac890, rStart=SwIndex (offset 0), nLen=3) at sw/source/core/txtnode/ndtxt.cxx:2199
15 SwTextNode::JoinNext() (this=0x89ac890) at sw/source/core/txtnode/ndtxt.cxx:812
Change-Id: If0dc0f16eb124dc8a070b84684ee9ec9ab0dc70f
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index d57b9b266a90..a77cfe42382e 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -2306,6 +2306,13 @@ void SwTextNode::CutImpl( SwTextNode * const pDest, const SwIndex & rDestStart,
}
}
+ // notify frames - before moving hints, because footnotes
+ // want to find their anchor text frame in the follow chain
+ SwInsText aInsHint( nDestStart, nLen );
+ pDest->ModifyNotification( nullptr, &aInsHint );
+ SwDelText aDelHint( nTextStartIdx, nLen );
+ ModifyNotification( nullptr, &aDelHint );
+
// 2. move attributes
// Iterate over attribute array until the start of the attribute
// is behind the moved range
@@ -2441,12 +2448,6 @@ void SwTextNode::CutImpl( SwTextNode * const pDest, const SwIndex & rDestStart,
CHECK_SWPHINTS(this);
TryDeleteSwpHints();
-
- // notify layout frames
- SwInsText aInsHint( nDestStart, nLen );
- pDest->ModifyNotification( nullptr, &aInsHint );
- SwDelText aDelHint( nTextStartIdx, nLen );
- ModifyNotification( nullptr, &aDelHint );
}
void SwTextNode::EraseText(const SwIndex &rIdx, const sal_Int32 nCount,
commit f3a59cae32b851a41f0fba9575443f6e3cc04c90
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 14 15:48:31 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: fix SplitNode handling of merged frames
The first branch is a bit easier, because it always moves the existing
frame onto the first node of the split anyway; the second branch may or
may not need to do that, but it has to move it just to be sure if it
needs to move it, which is a bit annoying...
Change-Id: Ib2fc69c2bd99dffa958f1620211ec657a8cc1be8
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 6c7b07e4819b..d57b9b266a90 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -367,6 +367,7 @@ static void lcl_ChangeFootnoteRef( SwTextNode &rNode )
SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
std::function<void (SwTextNode *, sw::mark::RestoreMode)> const*const pContentIndexRestore)
{
+ SwNode::Merge const eOldMergeFlag(GetRedlineMergeFlag());
bool parentIsOutline = IsOutline();
// create a node "in front" of me
@@ -480,6 +481,10 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
{ // call before making frames and before RegisterToNode
(*pContentIndexRestore)(pNode, sw::mark::RestoreMode::NonFlys);
}
+ if (eOldMergeFlag != SwNode::Merge::None)
+ { // clear before making frames and before RegisterToNode
+ SetRedlineMergeFlag(SwNode::Merge::None);
+ } // now RegisterToNode will set merge flags in both nodes properly!
SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*this);
for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
@@ -523,6 +528,7 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
{
MoveTextAttr_To_AttrSet();
}
+ // in case there are frames, the RegisterToNode has set the merge flag
pNode->MakeFramesForAdjacentContentNode(*this);
lcl_ChangeFootnoteRef( *this );
if (pContentIndexRestore)
@@ -585,15 +591,61 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
}
if (pContentIndexRestore)
- { // call before making frames
+ { // call before making frames and before RegisterToNode
(*pContentIndexRestore)(pNode, sw::mark::RestoreMode::NonFlys);
}
- if ( HasWriterListeners() )
+ std::vector<SwTextFrame*> frames;
+ SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*this);
+ for (SwTextFrame * pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+ {
+ frames.push_back(pFrame);
+ }
+ bool bNonMerged(false);
+ bool bRecreateThis(false);
+ for (SwTextFrame * pFrame : frames)
+ {
+ // sw_redlinehide: for this to work properly with hidden nodes,
+ // the frame needs to listen on them too.
+ // also: have to check the frame; this->GetRedlineMergeFlag()
+ // is None in case there's a delete redline inside the paragraph,
+ // but that could still result in a merged frame after split...
+ if (auto const pMergedPara = pFrame->GetMergedPara())
+ {
+ // Can't special case this == First here - that could (if
+ // both nodes are still merged by redline) lead to
+ // duplicate frames on "this".
+ // Update the extents with new node; also inits merge flag,
+ // so the MakeFramesForAdjacentContentNode below respects it
+ pFrame->RegisterToNode(*pNode);
+ if (!pFrame->GetMergedPara() ||
+ !pFrame->GetMergedPara()->listener.IsListeningTo(this))
+ {
+ // it's no longer listening - need to recreate frame
+ // (note this is idempotent, can be done once per frame)
+ SetRedlineMergeFlag(SwNode::Merge::None);
+ bRecreateThis = true;
+ }
+ }
+ else
+ {
+ bNonMerged = true;
+ }
+ }
+ assert(!(bNonMerged && bRecreateThis)); // 2 layouts not handled yet - maybe best to simply use the other branch then?
+ if (!frames.empty() && bNonMerged)
{
+ // the existing frame on "this" should have been updated by Cut
MakeFramesForAdjacentContentNode(*pNode);
+ lcl_ChangeFootnoteRef(*pNode);
+ }
+ else if (bRecreateThis)
+ {
+ assert(pNode->HasWriterListeners()); // was just moved there
+ pNode->MakeFramesForAdjacentContentNode(*this);
+ lcl_ChangeFootnoteRef(*this);
}
- lcl_ChangeFootnoteRef( *pNode );
+
if (pContentIndexRestore)
{ // call after making frames; listeners will take care of adding to the right frame
(*pContentIndexRestore)(pNode, sw::mark::RestoreMode::Flys);
@@ -601,6 +653,49 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
}
{
+ // First
+ // -> First,NonFirst
+ // -> First,Hidden
+ // -> None,First
+ // Hidden
+ // -> Hidden,Hidden (if still inside merge rl)
+ // -> NonFirst,First (if redline was split)
+ // NonFirst
+ // -> NonFirst,First (if split after end of "incoming" redline &
+ // before start of "outgoing" redline)
+ // -> NonFirst,None (if split after end of "incoming" redline)
+ // -> NonFirst,Hidden (if split after start of "outgoing" redline)
+ // -> Hidden, NonFirst (if split before end of "incoming" redline)
+ // None
+ // -> None,None
+ // -> First,NonFirst (if splitting inside a delete redline)
+ SwNode::Merge const eFirst(pNode->GetRedlineMergeFlag());
+ SwNode::Merge const eSecond(GetRedlineMergeFlag());
+ switch (eOldMergeFlag)
+ {
+ case Merge::First:
+ assert((eFirst == Merge::First && eSecond == Merge::NonFirst)
+ || (eFirst == Merge::First && eSecond == Merge::Hidden)
+ || (eFirst == Merge::None && eSecond == Merge::First));
+ break;
+ case Merge::Hidden:
+ assert((eFirst == Merge::Hidden && eSecond == Merge::Hidden)
+ || (eFirst == Merge::NonFirst && eSecond == Merge::First));
+ break;
+ case Merge::NonFirst:
+ assert((eFirst == Merge::NonFirst && eSecond == Merge::First)
+ || (eFirst == Merge::NonFirst && eSecond == Merge::None)
+ || (eFirst == Merge::NonFirst && eSecond == Merge::Hidden)
+ || (eFirst == Merge::Hidden && eSecond == Merge::NonFirst));
+ break;
+ case Merge::None:
+ assert((eFirst == Merge::None && eSecond == Merge::None)
+ || (eFirst == Merge::First && eSecond == Merge::NonFirst));
+ break;
+ }
+ }
+
+ {
// Send Hint for PageDesc. This should be done in the Layout when
// pasting the frames, but that causes other problems that look
// expensive to solve.
commit 3759deba1d2b58437910b6e9efa2985bf8c62091
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 14 11:20:46 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: let's have MergedPara listen on hidden nodes
... in particular all SwTextNodes on the same nodes-array nesting level
as the first one; then UpdateMergedParaForInsert can handle insertions
there.
Change-Id: I59d12b87c1296c322ab1f21779240ec611919cb0
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index b7cde56120e1..1d308a50e937 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4202,7 +4202,7 @@ static void UnHideRedlines(SwRootFrame & rLayout,
if (rLayout.IsHideRedlines())
{
assert(!pFrame->GetMergedPara() ||
- rNode.GetRedlineMergeFlag() == SwNode::Merge::NonFirst);
+ !rNode.IsCreateFrameWhenHidingRedlines());
if (rNode.IsCreateFrameWhenHidingRedlines())
{
{
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index 09480c84852e..58e42190f278 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -89,9 +89,23 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode,
{
pNode->SetRedlineMergeFlag(SwNode::Merge::First);
} // else: was already set before
+ int nLevel(0);
for (sal_uLong j = pNode->GetIndex() + 1; j < pEnd->nNode.GetIndex(); ++j)
{
- pNode->GetNodes()[j]->SetRedlineMergeFlag(SwNode::Merge::Hidden);
+ SwNode *const pTmp(pNode->GetNodes()[j]);
+ if (pTmp->IsStartNode())
+ {
+ ++nLevel;
+ }
+ else if (pTmp->IsEndNode())
+ {
+ --nLevel;
+ }
+ else if (nLevel == 0 && pTmp->IsTextNode())
+ {
+ nodes.push_back(pTmp->GetTextNode());
+ }
+ pTmp->SetRedlineMergeFlag(SwNode::Merge::Hidden);
}
pNode = pEnd->nNode.GetNode().GetTextNode();
assert(pNode);
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index f5aca5cc2c45..eba5ec65b400 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -724,6 +724,7 @@ namespace sw {
void UpdateMergedParaForInsert(MergedPara & rMerged,
SwTextNode const& rNode, sal_Int32 const nIndex, sal_Int32 const nLen)
{
+ assert(nLen); // can 0 happen?
assert(nIndex <= rNode.Len());
assert(nIndex + nLen <= rNode.Len());
assert(rMerged.pFirstNode->GetIndex() <= rNode.GetIndex() && rNode.GetIndex() <= rMerged.pLastNode->GetIndex());
@@ -754,7 +755,7 @@ void UpdateMergedParaForInsert(MergedPara & rMerged,
it->nEnd += nLen;
}
}
- else if (bFoundNode)
+ else if (rNode.GetIndex() < it->pNode->GetIndex() || bFoundNode)
{
itInsert = it;
break;
@@ -766,6 +767,10 @@ void UpdateMergedParaForInsert(MergedPara & rMerged,
{ // must be in a gap
rMerged.extents.emplace(itInsert, const_cast<SwTextNode*>(&rNode), nIndex, nIndex + nLen);
text.insert(nTFIndex, rNode.GetText().copy(nIndex, nLen));
+ if (rNode.GetIndex() < rMerged.pParaPropsNode->GetIndex())
+ { // text inserted before current para-props node
+ rMerged.pParaPropsNode = &rNode;
+ }
}
rMerged.mergedText = text.makeStringAndClear();
}
commit fa4248ec636f7900a84b4a672479f926c7eb0ef7
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Aug 13 18:18:40 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: try to keep the pLastNode updated if it's deleted...
Change-Id: Ied4ca532b336cacf3c4a8d96b9e75dcbaf47ba29
diff --git a/sw/inc/node.hxx b/sw/inc/node.hxx
index 1b0d7ad140db..ccded8e5eaf5 100644
--- a/sw/inc/node.hxx
+++ b/sw/inc/node.hxx
@@ -417,7 +417,7 @@ public:
/** Method deletes all views of document for the node. The content-
frames are removed from the respective layout.
*/
- void DelFrames(SwRootFrame const* pLayout);
+ void DelFrames(SwRootFrame const* pLayout, bool fromDtor = false);
/** @return count of elements of node content. Default is 1.
There are differences between text node and formula node. */
diff --git a/sw/source/core/docnode/node.cxx b/sw/source/core/docnode/node.cxx
index 0d97e9febba9..9175a1b076be 100644
--- a/sw/source/core/docnode/node.cxx
+++ b/sw/source/core/docnode/node.cxx
@@ -1320,7 +1320,7 @@ void SwContentNode::MakeFramesForAdjacentContentNode(SwContentNode& rNode)
* Deletes all Views from the Doc for this Node.
* The ContentFrames are removed from the corresponding Layout.
*/
-void SwContentNode::DelFrames(SwRootFrame const*const pLayout)
+void SwContentNode::DelFrames(SwRootFrame const*const pLayout, bool const fromDtor)
{
if( !HasWriterListeners() )
return;
@@ -1334,15 +1334,32 @@ void SwContentNode::DelFrames(SwRootFrame const*const pLayout)
}
if (pFrame->IsTextFrame())
{
- if (sw::MergedPara const* pMerged =
- static_cast<SwTextFrame const*>(pFrame)->GetMergedPara())
+ if (sw::MergedPara * pMerged =
+ static_cast<SwTextFrame *>(pFrame)->GetMergedPara())
{
if (this != pMerged->pFirstNode)
{
+ if (fromDtor)
+ {
+ // pointer should have been updated to a different node
+ assert(this != pMerged->pParaPropsNode);
+ // manual update required i'm afraid...
+ if (this == pMerged->pLastNode)
+ {
+ pMerged->pLastNode = GetNodes()[GetIndex()-1]->GetTextNode();
+ // at first glance nothing guarantees this...
+ // but the redline must end on a text-node...
+ // so everything before this node that isn't a text
+ // node should have been deleted already so that
+ // there's a text node before.
+ assert(pMerged->pLastNode->IsTextNode());
+ }
+ // avoid re-parenting mess (ModifyChangedHint)
+ pMerged->listener.EndListening(this);
+ }
continue; // don't delete
}
}
-
// #i27138#
// notify accessibility paragraphs objects about changed
// CONTENT_FLOWS_FROM/_TO relation.
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 7797626e46e2..ef9f806d5710 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -394,9 +394,7 @@ public:
{ return GetFollow() && !GetFollow()->GetOfst(); }
void SetMergedPara(std::unique_ptr<sw::MergedPara> p);
-#if 0
sw::MergedPara * GetMergedPara() { return m_pMergedPara.get(); }
-#endif
sw::MergedPara const* GetMergedPara() const { return m_pMergedPara.get(); }
/// Returns the text portion we want to edit (for inline see underneath)
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index c3780bfd368d..f5aca5cc2c45 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -726,6 +726,7 @@ void UpdateMergedParaForInsert(MergedPara & rMerged,
{
assert(nIndex <= rNode.Len());
assert(nIndex + nLen <= rNode.Len());
+ assert(rMerged.pFirstNode->GetIndex() <= rNode.GetIndex() && rNode.GetIndex() <= rMerged.pLastNode->GetIndex());
OUStringBuffer text(rMerged.mergedText);
sal_Int32 nTFIndex(0);
bool bInserted(false);
@@ -760,7 +761,7 @@ void UpdateMergedParaForInsert(MergedPara & rMerged,
}
nTFIndex += it->nEnd - it->nStart;
}
- assert((bFoundNode || rMerged.extents.empty()) && "text node not found - why is it sending hints to us");
+// assert((bFoundNode || rMerged.extents.empty()) && "text node not found - why is it sending hints to us");
if (!bInserted)
{ // must be in a gap
rMerged.extents.emplace(itInsert, const_cast<SwTextNode*>(&rNode), nIndex, nIndex + nLen);
@@ -776,6 +777,7 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged,
SwTextNode const& rNode, sal_Int32 nIndex, sal_Int32 const nLen)
{
assert(nIndex <= rNode.Len());
+ assert(rMerged.pFirstNode->GetIndex() <= rNode.GetIndex() && rNode.GetIndex() <= rMerged.pLastNode->GetIndex());
OUStringBuffer text(rMerged.mergedText);
sal_Int32 nTFIndex(0);
sal_Int32 nToDelete(nLen);
@@ -867,13 +869,13 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged,
++it;
}
}
- assert(nFoundNode != 0 && "text node not found - why is it sending hints to us");
+// assert(nFoundNode != 0 && "text node not found - why is it sending hints to us");
assert(nIndex - nDeleted <= rNode.Len());
// if there's a remaining deletion, it must be in gap at the end of the node
// can't do: might be last one in node was erased assert(nLen == 0 || rMerged.empty() || (it-1)->nEnd <= nIndex);
// note: if first node gets deleted then that must call DelFrames as
// pFirstNode is never updated
- if (nErased == nFoundNode)
+ if (nErased && nErased == nFoundNode)
{ // all visible text from node was erased
if (rMerged.pParaPropsNode == &rNode)
{
@@ -881,7 +883,7 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged,
? rMerged.pFirstNode
: rMerged.extents.front().pNode;
}
- rMerged.listener.EndListening(&const_cast<SwTextNode&>(rNode));
+// NOPE must listen on all non-hidden nodes; particularly on pLastNode rMerged.listener.EndListening(&const_cast<SwTextNode&>(rNode));
}
rMerged.mergedText = text.makeStringAndClear();
return TextFrameIndex(nDeleted);
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 933069872e6d..6c7b07e4819b 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -263,8 +263,7 @@ SwTextNode::~SwTextNode()
RemoveFromList();
InitSwParaStatistics( false );
-
- DelFrames(nullptr); // must be called here while it's still a SwTextNode
+ DelFrames(nullptr, true); // must be called here while it's still a SwTextNode
DelFrames_TextNodePart();
}
commit 66acb6edef9f1aeee714490ce55d7b340e6a633f
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Aug 13 18:05:03 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: fix infinite loop caused by SwAttrIter::Seek(0)
The problem is if there is a delete redline that deletes the entire
pFirstNode and ends in a different node, at the position where a
hint starts; first m_pRedline->Seek() will be called with the wrong
node, then the GetNextAttr() will call MapModelToView() and get 0
back again...
Change-Id: Ie3eb1250267429ea3e3f6281685c955a79d4e960
diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx
index 0eeeff080669..82bdc5910d1b 100644
--- a/sw/source/core/text/itratr.cxx
+++ b/sw/source/core/text/itratr.cxx
@@ -340,13 +340,16 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
assert(m_pRedline);
}
- if (!nNewPos || newPos.second < m_nPosition)
+ // sw_redlinehide: Seek(0) must move before the first character, which
+ // has a special case where the first node starts with delete redline.
+ if ((!nNewPos && (!m_pMergedPara || newPos.first != m_pTextNode))
+ || newPos.second < m_nPosition)
{
if (m_pMergedPara)
{
- if (m_pTextNode != m_pMergedPara->pFirstNode)
+ if (m_pTextNode != newPos.first)
{
- m_pTextNode = m_pMergedPara->pFirstNode;
+ m_pTextNode = newPos.first;
// sw_redlinehide: hope it's okay to use the current text node
// here; the AttrHandler shouldn't care about non-char items
InitFontAndAttrHandler(*m_pTextNode, m_pMergedPara->mergedText, nullptr);
@@ -410,7 +413,7 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
m_pFont->SetActual( m_pScriptInfo->WhichFont(nNewPos) );
if( m_pRedline )
- m_nChgCnt = m_nChgCnt + m_pRedline->Seek(*m_pFont, newPos.first->GetIndex(), newPos.second, m_nPosition);
+ m_nChgCnt = m_nChgCnt + m_pRedline->Seek(*m_pFont, m_pTextNode->GetIndex(), newPos.second, m_nPosition);
m_nPosition = newPos.second;
if( m_nPropFont )
commit ccba6604e8b9a7f7910bc1681f49b70670a95847
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Aug 13 15:59:16 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: check merge flag in various MakeFrames
Change-Id: I2d54ae4069c0c6813059f90a1003387512ee9ba1
diff --git a/sw/source/core/docnode/ndsect.cxx b/sw/source/core/docnode/ndsect.cxx
index add674689e85..b97188b316d8 100644
--- a/sw/source/core/docnode/ndsect.cxx
+++ b/sw/source/core/docnode/ndsect.cxx
@@ -1048,6 +1048,11 @@ void SwSectionNode::MakeFramesForAdjacentContentNode(const SwNodeIndex & rIdx)
while( nullptr != (pFrame = aNode2Layout.NextFrame()) )
{
OSL_ENSURE( pFrame->IsSctFrame(), "Depend of Section not a Section." );
+ if (pFrame->getRootFrame()->IsHideRedlines()
+ && !rIdx.GetNode().IsCreateFrameWhenHidingRedlines())
+ {
+ continue;
+ }
SwFrame *pNew = rIdx.GetNode().GetContentNode()->MakeFrame( pFrame );
SwSectionNode* pS = rIdx.GetNode().FindSectionNode();
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index 629f1e75e2b9..19bb5403e4eb 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -2381,6 +2381,11 @@ void SwTableNode::MakeFramesForAdjacentContentNode(const SwNodeIndex & rIdx)
while( nullptr != (pFrame = aNode2Layout.NextFrame()) )
{
+ if (pFrame->getRootFrame()->IsHideRedlines()
+ && !pNode->IsCreateFrameWhenHidingRedlines())
+ {
+ continue;
+ }
SwFrame *pNew = pNode->MakeFrame( pFrame );
// Will the Node receive Frames before or after?
if ( bBefore )
@@ -2408,6 +2413,11 @@ void SwTableNode::MakeOwnFrames(SwNodeIndex* pIdxBehind)
SwNode2Layout aNode2Layout( *pNd, GetIndex() );
while( nullptr != (pUpper = aNode2Layout.UpperFrame( pFrame, *this )) )
{
+ if (pUpper->getRootFrame()->IsHideRedlines()
+ && !IsCreateFrameWhenHidingRedlines())
+ {
+ continue;
+ }
SwTabFrame* pNew = MakeFrame( pUpper );
pNew->Paste( pUpper, pFrame );
// #i27138#
diff --git a/sw/source/core/docnode/node.cxx b/sw/source/core/docnode/node.cxx
index 65e60ce15d63..0d97e9febba9 100644
--- a/sw/source/core/docnode/node.cxx
+++ b/sw/source/core/docnode/node.cxx
@@ -1290,6 +1290,11 @@ void SwContentNode::MakeFramesForAdjacentContentNode(SwContentNode& rNode)
while( nullptr != (pUpper = aNode2Layout.UpperFrame( pFrame, rNode )) )
{
+ if (pUpper->getRootFrame()->IsHideRedlines()
+ && !rNode.IsCreateFrameWhenHidingRedlines())
+ {
+ continue;
+ }
SwFrame *pNew = rNode.MakeFrame( pUpper );
pNew->Paste( pUpper, pFrame );
// #i27138#
commit 966294d963016f022b56f75cfad6080fcf46838b
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Aug 13 13:35:42 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: SplitNode: move more code into restoreFunc
In DocumentContentOperationsManager::SplitNode(), ensure that all
redline updating is done in the restoreFunc.
Change-Id: I918b8f24dcda0cc181cb0f33bb2ca170a14b0e98
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 2f997aea27ec..58a4fe796c54 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -2945,22 +2945,29 @@ bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool b
{ // move all bookmarks, TOXMarks, FlyAtCnt
pContentStore->Restore(&m_rDoc, rPos.nNode.GetIndex()-1, 0, true, eMode);
}
+ if (eMode & sw::mark::RestoreMode::NonFlys)
+ {
+ // To-Do - add 'SwExtraRedlineTable' also ?
+ if (m_rDoc.getIDocumentRedlineAccess().IsRedlineOn() ||
+ (!m_rDoc.getIDocumentRedlineAccess().IsIgnoreRedline() &&
+ !m_rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty()))
+ {
+ SwPaM aPam( rPos );
+ aPam.SetMark();
+ aPam.Move( fnMoveBackward );
+ if (m_rDoc.getIDocumentRedlineAccess().IsRedlineOn())
+ {
+ m_rDoc.getIDocumentRedlineAccess().AppendRedline(
+ new SwRangeRedline(nsRedlineType_t::REDLINE_INSERT, aPam), true);
+ }
+ else
+ {
+ m_rDoc.getIDocumentRedlineAccess().SplitRedline(aPam);
+ }
+ }
+ }
});
- pNode = pNode->GetTextNode()->SplitContentNode(rPos, &restoreFunc);
- if (pNode)
- {
- // To-Do - add 'SwExtraRedlineTable' also ?
- if( m_rDoc.getIDocumentRedlineAccess().IsRedlineOn() || (!m_rDoc.getIDocumentRedlineAccess().IsIgnoreRedline() && !m_rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty() ))
- {
- SwPaM aPam( rPos );
- aPam.SetMark();
- aPam.Move( fnMoveBackward );
- if( m_rDoc.getIDocumentRedlineAccess().IsRedlineOn() )
- m_rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_INSERT, aPam ), true);
- else
- m_rDoc.getIDocumentRedlineAccess().SplitRedline( aPam );
- }
- }
+ pNode->GetTextNode()->SplitContentNode(rPos, &restoreFunc);
m_rDoc.getIDocumentState().SetModified();
return true;
commit ae5be2051034253ccbdc9ba3e4b2f5236460bbe5
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Aug 13 11:10:20 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: MapModelToView needs to work on hidden nodes...
... that have no extents as well; add a pointer to the last node that
can be used for comparing.
Change-Id: Ibe7a84b523bb5921b3ca7fed2e330c54d85c5498
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 965b4f911647..7797626e46e2 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -926,14 +926,18 @@ struct MergedPara
SwTextNode const* pParaPropsNode;
/// except break attributes, those are taken from the first node
SwTextNode *const pFirstNode;
+ /// mainly for sanity checks
+ SwTextNode const* pLastNode;
MergedPara(SwTextFrame & rFrame, std::vector<Extent>&& rExtents,
OUString const& rText,
- SwTextNode const*const pProps, SwTextNode *const pFirst)
+ SwTextNode const*const pProps, SwTextNode *const pFirst,
+ SwTextNode const*const pLast)
: listener(rFrame), extents(std::move(rExtents)), mergedText(rText)
- , pParaPropsNode(pProps), pFirstNode(pFirst)
+ , pParaPropsNode(pProps), pFirstNode(pFirst), pLastNode(pLast)
{
assert(pParaPropsNode);
assert(pFirstNode);
+ assert(pLastNode);
}
};
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index 21de262420bf..09480c84852e 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -157,7 +157,8 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode,
}
}
auto pRet(o3tl::make_unique<sw::MergedPara>(rFrame, std::move(extents),
- mergedText.makeStringAndClear(), pParaPropsNode, &rTextNode));
+ mergedText.makeStringAndClear(), pParaPropsNode, &rTextNode,
+ nodes.back()));
for (SwTextNode * pTmp : nodes)
{
pRet->listener.StartListening(pTmp);
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index a548c55ed2cc..c3780bfd368d 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -909,10 +909,16 @@ MapViewToModel(MergedPara const& rMerged, TextFrameIndex const i_nIndex)
TextFrameIndex MapModelToView(MergedPara const& rMerged, SwTextNode const*const pNode, sal_Int32 const nIndex)
{
+ assert(rMerged.pFirstNode->GetIndex() <= pNode->GetIndex()
+ && pNode->GetIndex() <= rMerged.pLastNode->GetIndex());
sal_Int32 nRet(0);
bool bFoundNode(false);
for (auto const& e : rMerged.extents)
{
+ if (pNode->GetIndex() < e.pNode->GetIndex())
+ {
+ return TextFrameIndex(nRet);
+ }
if (e.pNode == pNode)
{
if (e.nStart <= nIndex && nIndex <= e.nEnd)
@@ -943,7 +949,6 @@ TextFrameIndex MapModelToView(MergedPara const& rMerged, SwTextNode const*const
assert(nIndex <= pNode->Len());
return TextFrameIndex(0);
}
- assert(!"text node not found");
return TextFrameIndex(COMPLETE_STRING);
}
commit 7b3ec6c10c8fbfd547c5d82a602ab597a2b116aa
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 9 17:26:50 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: also reset Merge flag in CheckParaRedlineMerge
If it sets the Merge flag, it needs to reset it too.
Change-Id: I0b07ca87ff9911db37166312ca07edd15e8b496c
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index f023d069b740..21de262420bf 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -102,6 +102,10 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode,
}
if (!bHaveRedlines)
{
+ if (pNode->GetRedlineMergeFlag() != SwNode::Merge::None)
+ {
+ pNode->SetRedlineMergeFlag(SwNode::Merge::None);
+ }
return nullptr;
}
if (nLastEnd != pNode->Len())
commit 572ba0f8c3d40373b16a037d761e4a057029a8ee
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 9 17:25:15 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: when switching show/hide, invalidate Insert redlines
... so that the frames are repainted with/without font color.
Change-Id: I68f105868d262c9d0a88f124c98243a64159aa38
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index 513e8c339f8a..b7cde56120e1 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -31,6 +31,7 @@
#include <IDocumentSettingAccess.hxx>
#include <IDocumentFieldsAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
+#include <redline.hxx>
#include <fesh.hxx>
#include <docsh.hxx>
#include <ftninfo.hxx>
@@ -4461,6 +4462,15 @@ void SwRootFrame::SetHideRedlines(bool const bHideRedlines)
AppendAllObjs(rDoc.GetSpzFrameFormats(), this);
}
+ for (auto const pRedline : rDoc.getIDocumentRedlineAccess().GetRedlineTable())
+ { // DELETE are handled by the code above; for other types, need to
+ // trigger repaint of text frames to add/remove the redline color font
+ if (pRedline->GetType() != nsRedlineType_t::REDLINE_DELETE)
+ {
+ pRedline->InvalidateRange();
+ }
+ }
+
// InvalidateAllContent(SwInvalidateFlags::Size); // ??? TODO what to invalidate? this is the big hammer
}
commit b98a3b1ccda6aa13cd67510114e42125ba4186f0
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 9 17:24:05 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: fix painting of "bars" in the margin
If the layout wants to hide redlines, these should not be painted.
Change-Id: I3cc725b466ca3874a00c6b96eb0e02ff70dcc42b
diff --git a/sw/source/core/text/frmpaint.cxx b/sw/source/core/text/frmpaint.cxx
index 4d2adf502528..4b3007087c6d 100644
--- a/sw/source/core/text/frmpaint.cxx
+++ b/sw/source/core/text/frmpaint.cxx
@@ -288,8 +288,12 @@ void SwTextFrame::PaintExtraData( const SwRect &rRect ) const
bool bLineNum = !IsInTab() && rLineInf.IsPaintLineNumbers() &&
( !IsInFly() || rLineInf.IsCountInFlys() ) && rLineNum.IsCount();
sal_Int16 eHor = static_cast<sal_Int16>(SW_MOD()->GetRedlineMarkPos());
- if( eHor != text::HoriOrientation::NONE && !IDocumentRedlineAccess::IsShowChanges( rIDRA.GetRedlineFlags() ) )
+ if (eHor != text::HoriOrientation::NONE
+ && (!IDocumentRedlineAccess::IsShowChanges(rIDRA.GetRedlineFlags())
+ || getRootFrame()->IsHideRedlines()))
+ {
eHor = text::HoriOrientation::NONE;
+ }
bool bRedLine = eHor != text::HoriOrientation::NONE;
if ( !bLineNum && !bRedLine )
return;
@@ -475,7 +479,8 @@ bool SwTextFrame::PaintEmpty( const SwRect &rRect, bool bCheck ) const
}
const IDocumentRedlineAccess& rIDRA = rTextNode.getIDocumentRedlineAccess();
- if( IDocumentRedlineAccess::IsShowChanges( rIDRA.GetRedlineFlags() ) )
+ if (IDocumentRedlineAccess::IsShowChanges(rIDRA.GetRedlineFlags())
+ && !getRootFrame()->IsHideRedlines())
{
const SwRedlineTable::size_type nRedlPos = rIDRA.GetRedlinePos( rTextNode, USHRT_MAX );
if( SwRedlineTable::npos != nRedlPos )
diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx
index 24778b6ec9d6..727e0319a730 100644
--- a/sw/source/core/text/porrst.cxx
+++ b/sw/source/core/text/porrst.cxx
@@ -250,7 +250,8 @@ SwTwips SwTextFrame::EmptyHeight() const
}
const IDocumentRedlineAccess& rIDRA = rTextNode.getIDocumentRedlineAccess();
- if( IDocumentRedlineAccess::IsShowChanges( rIDRA.GetRedlineFlags() ) )
+ if (IDocumentRedlineAccess::IsShowChanges(rIDRA.GetRedlineFlags())
+ && !getRootFrame()->IsHideRedlines())
{
const SwRedlineTable::size_type nRedlPos = rIDRA.GetRedlinePos( rTextNode, USHRT_MAX );
if( SwRedlineTable::npos != nRedlPos )
commit 577bc9dcf1060757dae965a68840072076ed6669
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 9 17:22:36 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: fix init of SwRedlineIter::Mode
If there are no delete redlines in a frame, the mode must be Ignore,
otherwise the insert redlines will be colorful...
Change-Id: Ibd57f2827b0805ac2fdb29ed347d9b2ed0b00737
diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index 5bcb4d1b4350..f023d069b740 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -287,7 +287,8 @@ void SwAttrIter::CtorInitAttrIter(SwTextNode & rTextNode,
}
}
}
- const bool bShow = IDocumentRedlineAccess::IsShowChanges( rIDRA.GetRedlineFlags() );
+ const bool bShow = IDocumentRedlineAccess::IsShowChanges(rIDRA.GetRedlineFlags())
+ && pRootFrame && !pRootFrame->IsHideRedlines();
if (pExtInp || m_pMergedPara || bShow)
{
SwRedlineTable::size_type nRedlPos = rIDRA.GetRedlinePos( rTextNode, USHRT_MAX );
commit 1cc86f2ea969558b6c4e58efa68c781019bfc893
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 9 15:10:13 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: fix ordering of SplitNode usage of ContentIdxStore 2
The flys have their anchor positions updated, and that causes lookups
from the layout frame to the anchor SwTextFrame, but that isn't updated
yet; it looks like the fly restore must be done after adapting the
SwTextFrames, while the redline restore must be done before.
Also RegisterToNode must call Check only for the 1st node.
Change-Id: If87a62108f1bcaf794e5be1cc38dc936f08cd69e
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index a32ea79c310a..82044796a5eb 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -62,6 +62,8 @@ class SwGrammarMarkUp;
struct SwDocStat;
struct SwParaIdleData_Impl;
+namespace sw { namespace mark { enum class RestoreMode; } }
+
namespace com { namespace sun { namespace star {
namespace uno {
template < class > class Sequence;
@@ -349,7 +351,7 @@ public:
/// Virtual methods from ContentNode.
virtual SwContentFrame *MakeFrame( SwFrame* ) override;
SwTextNode * SplitContentNode(const SwPosition &,
- std::function<void (SwTextNode *)> const* pContentIndexRestore);
+ std::function<void (SwTextNode *, sw::mark::RestoreMode)> const* pContentIndexRestore);
virtual SwContentNode *JoinNext() override;
void JoinPrev();
diff --git a/sw/source/core/doc/CntntIdxStore.cxx b/sw/source/core/doc/CntntIdxStore.cxx
index 68a8c29ea888..7703c1175094 100644
--- a/sw/source/core/doc/CntntIdxStore.cxx
+++ b/sw/source/core/doc/CntntIdxStore.cxx
@@ -152,26 +152,38 @@ namespace
SaveUnoCursors(pDoc, nNode, nContent);
SaveShellCursors(pDoc, nNode, nContent);
}
- virtual void Restore(SwDoc* pDoc, sal_uLong nNode, sal_Int32 nOffset=0, bool bAuto = false) override
+ virtual void Restore(SwDoc* pDoc, sal_uLong nNode, sal_Int32 nOffset=0, bool bAuto = false, RestoreMode eMode = RestoreMode::All) override
{
SwContentNode* pCNd = pDoc->GetNodes()[ nNode ]->GetContentNode();
updater_t aUpdater = OffsetUpdater(pCNd, nOffset);
- RestoreBkmks(pDoc, aUpdater);
- RestoreRedlines(pDoc, aUpdater);
- RestoreFlys(pDoc, aUpdater, bAuto);
- RestoreUnoCursors(aUpdater);
- RestoreShellCursors(aUpdater);
+ if (eMode & RestoreMode::NonFlys)
+ {
+ RestoreBkmks(pDoc, aUpdater);
+ RestoreRedlines(pDoc, aUpdater);
+ RestoreUnoCursors(aUpdater);
+ RestoreShellCursors(aUpdater);
+ }
+ if (eMode & RestoreMode::Flys)
+ {
+ RestoreFlys(pDoc, aUpdater, bAuto);
+ }
}
- virtual void Restore(SwNode& rNd, sal_Int32 nLen, sal_Int32 nCorrLen) override
+ virtual void Restore(SwNode& rNd, sal_Int32 nLen, sal_Int32 nCorrLen, RestoreMode eMode = RestoreMode::All) override
{
SwContentNode* pCNd = rNd.GetContentNode();
SwDoc* pDoc = rNd.GetDoc();
updater_t aUpdater = LimitUpdater(pCNd, nLen, nCorrLen);
- RestoreBkmks(pDoc, aUpdater);
- RestoreRedlines(pDoc, aUpdater);
- RestoreFlys(pDoc, aUpdater, false);
- RestoreUnoCursors(aUpdater);
- RestoreShellCursors(aUpdater);
+ if (eMode & RestoreMode::NonFlys)
+ {
+ RestoreBkmks(pDoc, aUpdater);
+ RestoreRedlines(pDoc, aUpdater);
+ RestoreUnoCursors(aUpdater);
+ RestoreShellCursors(aUpdater);
+ }
+ if (eMode & RestoreMode::Flys)
+ {
+ RestoreFlys(pDoc, aUpdater, false);
+ }
}
private:
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index bb419904ef95..2f997aea27ec 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -1992,12 +1992,12 @@ bool DocumentContentOperationsManager::MoveRange( SwPaM& rPaM, SwPosition& rPos,
assert(aSavePam.GetPoint()->nNode == rPos.nNode.GetIndex());
assert(rPos.nNode.GetIndex() == pOrigNode->GetIndex());
- std::function<void (SwTextNode *)> restoreFunc(
- [&](SwTextNode *const)
+ std::function<void (SwTextNode *, sw::mark::RestoreMode)> restoreFunc(
+ [&](SwTextNode *const, sw::mark::RestoreMode const eMode)
{
if (!pContentStore->Empty())
{
- pContentStore->Restore(&m_rDoc, pOrigNode->GetIndex()-1, 0, true);
+ pContentStore->Restore(&m_rDoc, pOrigNode->GetIndex()-1, 0, true, eMode);
}
});
pTNd = pTNd->SplitContentNode(rPos, &restoreFunc)->GetTextNode();
@@ -2938,12 +2938,12 @@ bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool b
const std::shared_ptr<sw::mark::ContentIdxStore> pContentStore(sw::mark::ContentIdxStore::Create());
pContentStore->Save( &m_rDoc, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(), true );
assert(pNode->IsTextNode());
- std::function<void (SwTextNode *)> restoreFunc(
- [&](SwTextNode *const)
+ std::function<void (SwTextNode *, sw::mark::RestoreMode)> restoreFunc(
+ [&](SwTextNode *const, sw::mark::RestoreMode const eMode)
{
if (!pContentStore->Empty())
{ // move all bookmarks, TOXMarks, FlyAtCnt
- pContentStore->Restore(&m_rDoc, rPos.nNode.GetIndex()-1, 0, true);
+ pContentStore->Restore(&m_rDoc, rPos.nNode.GetIndex()-1, 0, true, eMode);
}
});
pNode = pNode->GetTextNode()->SplitContentNode(rPos, &restoreFunc);
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index e48ebee042d7..629f1e75e2b9 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -1070,12 +1070,12 @@ SwTableNode* SwNodes::TextToTable( const SwNodeRange& rRange, sal_Unicode cCh,
if (pTextNd->GetText()[nChPos] == cCh)
{
aCntPos.nContent = nChPos;
- std::function<void (SwTextNode *)> restoreFunc(
- [&](SwTextNode *const pNewNode)
+ std::function<void (SwTextNode *, sw::mark::RestoreMode)> restoreFunc(
+ [&](SwTextNode *const pNewNode, sw::mark::RestoreMode const eMode)
{
if (!pContentStore->Empty())
{
- pContentStore->Restore(*pNewNode, nChPos, nChPos + 1);
+ pContentStore->Restore(*pNewNode, nChPos, nChPos + 1, eMode);
}
});
SwContentNode *const pNewNd =
diff --git a/sw/source/core/inc/mvsave.hxx b/sw/source/core/inc/mvsave.hxx
index 1279617ef313..ec0a1e412787 100644
--- a/sw/source/core/inc/mvsave.hxx
+++ b/sw/source/core/inc/mvsave.hxx
@@ -23,6 +23,7 @@
#include <IDocumentMarkAccess.hxx>
#include <vector>
#include <deque>
+#include <o3tl/typed_flags_set.hxx>
namespace sfx2 {
class MetadatableUndo;
@@ -66,20 +67,27 @@ namespace sw { namespace mark
std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndo;
};
+ enum class RestoreMode { Flys = 1, NonFlys = 2, All = 3 };
+
/// Takes care of storing relevant attributes of an SwTextNode before split, then restore them on the new node.
class ContentIdxStore
{
public:
+
virtual void Clear() =0;
virtual bool Empty() =0;
virtual void Save(SwDoc* pDoc, sal_uLong nNode, sal_Int32 nContent, bool bSaveFlySplit=false) =0;
- virtual void Restore(SwDoc* pDoc, sal_uLong nNode, sal_Int32 nOffset=0, bool bAuto = false) =0;
- virtual void Restore(SwNode& rNd, sal_Int32 nLen, sal_Int32 nCorrLen) =0;
+ virtual void Restore(SwDoc* pDoc, sal_uLong nNode, sal_Int32 nOffset=0, bool bAuto = false, RestoreMode = RestoreMode::All) =0;
+ virtual void Restore(SwNode& rNd, sal_Int32 nLen, sal_Int32 nCorrLen, RestoreMode = RestoreMode::All) =0;
virtual ~ContentIdxStore() {};
static std::shared_ptr<ContentIdxStore> Create();
};
}}
+namespace o3tl {
+ template<> struct typed_flags<sw::mark::RestoreMode> : is_typed_flags<sw::mark::RestoreMode, 3> {};
+}
+
void DelBookmarks(const SwNodeIndex& rStt,
const SwNodeIndex& rEnd,
std::vector< ::sw::mark::SaveBookmark> * SaveBkmk =nullptr,
diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx
index abe62e8b3968..3a37ae92bc7f 100644
--- a/sw/source/core/layout/ssfrm.cxx
+++ b/sw/source/core/layout/ssfrm.cxx
@@ -443,8 +443,15 @@ SwContentFrame::~SwContentFrame()
void SwTextFrame::RegisterToNode(SwTextNode & rNode)
{
assert(&rNode != GetDep());
+ assert(!m_pMergedPara
+ || (m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex())
+ || (rNode.GetIndex() + 1 == m_pMergedPara->pFirstNode->GetIndex()));
+ SwTextNode & rFirstNode(
+ (m_pMergedPara && m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex())
+ ? *m_pMergedPara->pFirstNode
+ : rNode);
// sw_redlinehide: use New here, because the only caller also calls lcl_ChangeFootnoteRef
- m_pMergedPara = sw::CheckParaRedlineMerge(*this, rNode, sw::FrameMode::New);
+ m_pMergedPara = sw::CheckParaRedlineMerge(*this, rFirstNode, sw::FrameMode::New);
if (!m_pMergedPara)
{
rNode.Add(this);
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index a082a7eac14a..933069872e6d 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -366,7 +366,7 @@ static void lcl_ChangeFootnoteRef( SwTextNode &rNode )
}
SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
- std::function<void (SwTextNode *)> const*const pContentIndexRestore)
+ std::function<void (SwTextNode *, sw::mark::RestoreMode)> const*const pContentIndexRestore)
{
bool parentIsOutline = IsOutline();
@@ -479,7 +479,7 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
if (pContentIndexRestore)
{ // call before making frames and before RegisterToNode
- (*pContentIndexRestore)(pNode);
+ (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::NonFlys);
}
SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*this);
@@ -526,6 +526,10 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
}
pNode->MakeFramesForAdjacentContentNode(*this);
lcl_ChangeFootnoteRef( *this );
+ if (pContentIndexRestore)
+ { // call after making frames; listeners will take care of adding to the right frame
+ (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::Flys);
+ }
}
else
{
@@ -583,7 +587,7 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
if (pContentIndexRestore)
{ // call before making frames
- (*pContentIndexRestore)(pNode);
+ (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::NonFlys);
}
if ( HasWriterListeners() )
@@ -591,6 +595,10 @@ SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
MakeFramesForAdjacentContentNode(*pNode);
}
lcl_ChangeFootnoteRef( *pNode );
+ if (pContentIndexRestore)
+ { // call after making frames; listeners will take care of adding to the right frame
+ (*pContentIndexRestore)(pNode, sw::mark::RestoreMode::Flys);
+ }
}
{
diff --git a/sw/source/core/undo/untbl.cxx b/sw/source/core/undo/untbl.cxx
index c03142eb2423..1705d281a12c 100644
--- a/sw/source/core/undo/untbl.cxx
+++ b/sw/source/core/undo/untbl.cxx
@@ -557,12 +557,12 @@ SwTableNode* SwNodes::UndoTableToText( sal_uLong nSttNd, sal_uLong nEndNd,
pTextNd->EraseText( aCntPos, 1 );
- std::function<void (SwTextNode *)> restoreFunc(
- [&](SwTextNode *const pNewNode)
+ std::function<void (SwTextNode *, sw::mark::RestoreMode)> restoreFunc(
+ [&](SwTextNode *const pNewNode, sw::mark::RestoreMode const eMode)
{
if (!pContentStore->Empty())
{
- pContentStore->Restore(*pNewNode, pSave->m_nContent, pSave->m_nContent + 1);
+ pContentStore->Restore(*pNewNode, pSave->m_nContent, pSave->m_nContent + 1, eMode);
}
});
pTextNd->SplitContentNode(
commit 97f566bf2b5af94dac664a701c6e68be040b69b7
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 8 16:13:58 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: fix ordering of SplitNode usage of ContentIdxStore
The problem is that now the ctor of SwTextFrame will check the redline
positions, but the call to MakeFramesForAdjacentContentNode()
happens before the call to ContentIdxStore::Restore() that updates
the SwPositions of the redlines, hence they point to the wrong node.
Try to fix this by not calling Restore directly but pass in a closure
to SwTextNode::SplitContentNode() so that it can call
ContentIdxStore::Restore() before frames are created and redline positions
are checked.
Also remove the useless SwContentNode::SplitContentNode() - only the
SwTextNode override actually did anything.
Change-Id: I2088fd124d04cf354f4f0f691a50ff5217d778d7
diff --git a/sw/inc/ndgrf.hxx b/sw/inc/ndgrf.hxx
index a5e4e0cc2969..74c46f20b238 100644
--- a/sw/inc/ndgrf.hxx
+++ b/sw/inc/ndgrf.hxx
@@ -80,7 +80,6 @@ public:
const Graphic& GetGrf(bool bWait = false) const;
const GraphicObject& GetGrfObj(bool bWait = false) const;
const GraphicObject* GetReplacementGrfObj() const;
- virtual SwContentNode *SplitContentNode( const SwPosition & ) override;
/// isolated only way to set GraphicObject to allow more actions when doing so
void SetGraphic(const Graphic& rGraphic);
diff --git a/sw/inc/ndole.hxx b/sw/inc/ndole.hxx
index 4f6f4596736d..93139c986526 100644
--- a/sw/inc/ndole.hxx
+++ b/sw/inc/ndole.hxx
@@ -111,8 +111,6 @@ public:
SwOLEObj& GetOLEObj() { return maOLEObj; }
virtual ~SwOLENode() override;
- virtual SwContentNode *SplitContentNode( const SwPosition & ) override;
-
/// Is in ndcopy.cxx.
virtual SwContentNode* MakeCopy( SwDoc*, const SwNodeIndex& ) const override;
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index d1a8801eb9c7..a32ea79c310a 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -34,6 +34,7 @@
#include <memory>
#include <vector>
#include <set>
+#include <functional>
class SfxHint;
class SwNumRule;
@@ -347,7 +348,8 @@ public:
/// Virtual methods from ContentNode.
virtual SwContentFrame *MakeFrame( SwFrame* ) override;
- virtual SwContentNode *SplitContentNode( const SwPosition & ) override;
+ SwTextNode * SplitContentNode(const SwPosition &,
+ std::function<void (SwTextNode *)> const* pContentIndexRestore);
virtual SwContentNode *JoinNext() override;
void JoinPrev();
diff --git a/sw/inc/node.hxx b/sw/inc/node.hxx
index a57af24582bb..1b0d7ad140db 100644
--- a/sw/inc/node.hxx
+++ b/sw/inc/node.hxx
@@ -387,8 +387,6 @@ public:
pSib is another SwFrame of the same layout (e.g. the SwRootFrame itself, a sibling, the parent) */
virtual SwContentFrame *MakeFrame( SwFrame* pSib ) = 0;
- virtual SwContentNode *SplitContentNode(const SwPosition & ) = 0;
-
virtual SwContentNode *JoinNext();
/** Is it possible to join two nodes?
In pIdx the second position can be returned. */
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 788cb61dd7df..bb419904ef95 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -1992,7 +1992,15 @@ bool DocumentContentOperationsManager::MoveRange( SwPaM& rPaM, SwPosition& rPos,
assert(aSavePam.GetPoint()->nNode == rPos.nNode.GetIndex());
assert(rPos.nNode.GetIndex() == pOrigNode->GetIndex());
- pTNd = pTNd->SplitContentNode( rPos )->GetTextNode();
+ std::function<void (SwTextNode *)> restoreFunc(
+ [&](SwTextNode *const)
+ {
+ if (!pContentStore->Empty())
+ {
+ pContentStore->Restore(&m_rDoc, pOrigNode->GetIndex()-1, 0, true);
+ }
+ });
+ pTNd = pTNd->SplitContentNode(rPos, &restoreFunc)->GetTextNode();
//A new node was inserted before the orig pTNd and the content up to
//rPos moved into it. The old node is returned with the remainder
@@ -2012,9 +2020,6 @@ bool DocumentContentOperationsManager::MoveRange( SwPaM& rPaM, SwPosition& rPos,
aSavePam.GetPoint()->nContent.Assign(pOrigNode, 0);
rPos = *aSavePam.GetMark() = *aSavePam.GetPoint();
- if( !pContentStore->Empty() )
- pContentStore->Restore( &m_rDoc, rPos.nNode.GetIndex()-1, 0, true );
-
// correct the PaM!
if( rPos.nNode == rPaM.GetMark()->nNode )
{
@@ -2932,15 +2937,18 @@ bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool b
const std::shared_ptr<sw::mark::ContentIdxStore> pContentStore(sw::mark::ContentIdxStore::Create());
pContentStore->Save( &m_rDoc, rPos.nNode.GetIndex(), rPos.nContent.GetIndex(), true );
- // FIXME: only SwTextNode has a valid implementation of SplitContentNode!
- OSL_ENSURE(pNode->IsTextNode(), "splitting non-text node?");
- pNode = pNode->SplitContentNode( rPos );
+ assert(pNode->IsTextNode());
+ std::function<void (SwTextNode *)> restoreFunc(
+ [&](SwTextNode *const)
+ {
+ if (!pContentStore->Empty())
+ { // move all bookmarks, TOXMarks, FlyAtCnt
+ pContentStore->Restore(&m_rDoc, rPos.nNode.GetIndex()-1, 0, true);
+ }
+ });
+ pNode = pNode->GetTextNode()->SplitContentNode(rPos, &restoreFunc);
if (pNode)
{
- // move all bookmarks, TOXMarks, FlyAtCnt
- if( !pContentStore->Empty() )
- pContentStore->Restore( &m_rDoc, rPos.nNode.GetIndex()-1, 0, true );
-
// To-Do - add 'SwExtraRedlineTable' also ?
if( m_rDoc.getIDocumentRedlineAccess().IsRedlineOn() || (!m_rDoc.getIDocumentRedlineAccess().IsIgnoreRedline() && !m_rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty() ))
{
diff --git a/sw/source/core/docnode/ndtbl.cxx b/sw/source/core/docnode/ndtbl.cxx
index 21733a1e8cc8..e48ebee042d7 100644
--- a/sw/source/core/docnode/ndtbl.cxx
+++ b/sw/source/core/docnode/ndtbl.cxx
@@ -1070,10 +1070,16 @@ SwTableNode* SwNodes::TextToTable( const SwNodeRange& rRange, sal_Unicode cCh,
if (pTextNd->GetText()[nChPos] == cCh)
{
aCntPos.nContent = nChPos;
- SwContentNode* pNewNd = pTextNd->SplitContentNode( aCntPos );
-
- if( !pContentStore->Empty() )
- pContentStore->Restore( *pNewNd, nChPos, nChPos + 1 );
+ std::function<void (SwTextNode *)> restoreFunc(
+ [&](SwTextNode *const pNewNode)
+ {
+ if (!pContentStore->Empty())
+ {
+ pContentStore->Restore(*pNewNode, nChPos, nChPos + 1);
+ }
+ });
+ SwContentNode *const pNewNd =
+ pTextNd->SplitContentNode(aCntPos, &restoreFunc);
// Delete separator and correct search string
pTextNd->EraseText( aCntPos.nContent, 1 );
diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx
index 22c84a19b1c4..4aa473c4308e 100644
--- a/sw/source/core/docnode/nodes.cxx
+++ b/sw/source/core/docnode/nodes.cxx
@@ -1512,7 +1512,7 @@ void SwNodes::MoveRange( SwPaM & rPam, SwPosition & rPos, SwNodes& rNodes )
}
else
{
- pDestNd->SplitContentNode( rPos );
+ pDestNd->SplitContentNode(rPos, nullptr);
}
if( rPos.nNode == aEndIdx )
@@ -1577,7 +1577,7 @@ void SwNodes::MoveRange( SwPaM & rPam, SwPosition & rPos, SwNodes& rNodes )
}
else
{
- pDestNd->SplitContentNode( rPos );
+ pDestNd->SplitContentNode(rPos, nullptr);
}
if ( bCorrEnd )
diff --git a/sw/source/core/graphic/ndgrf.cxx b/sw/source/core/graphic/ndgrf.cxx
index d95e574c404c..0ff3cd1889de 100644
--- a/sw/source/core/graphic/ndgrf.cxx
+++ b/sw/source/core/graphic/ndgrf.cxx
@@ -401,11 +401,6 @@ const GraphicObject* SwGrfNode::GetReplacementGrfObj() const
return mpReplacementGraphic.get();
}
-SwContentNode *SwGrfNode::SplitContentNode( const SwPosition & )
-{
- return this;
-}
-
SwGrfNode * SwNodes::MakeGrfNode( const SwNodeIndex & rWhere,
const OUString& rGrfName,
const OUString& rFltName,
diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx
index e4b6115fd0ec..8d59c502817c 100644
--- a/sw/source/core/ole/ndole.cxx
+++ b/sw/source/core/ole/ndole.cxx
@@ -242,13 +242,6 @@ const Graphic* SwOLENode::GetGraphic()
return nullptr;
}
-SwContentNode *SwOLENode::SplitContentNode( const SwPosition & )
-{
- // Multiply OLE objects?
- OSL_FAIL( "OleNode: can't split." );
- return this;
-}
-
/**
* Loading a OLE object that has been moved to the Undo Area
*/
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index e5bf6c36502d..a082a7eac14a 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -365,7 +365,8 @@ static void lcl_ChangeFootnoteRef( SwTextNode &rNode )
}
}
-SwContentNode *SwTextNode::SplitContentNode( const SwPosition &rPos )
+SwTextNode *SwTextNode::SplitContentNode(const SwPosition & rPos,
+ std::function<void (SwTextNode *)> const*const pContentIndexRestore)
{
bool parentIsOutline = IsOutline();
@@ -476,6 +477,11 @@ SwContentNode *SwTextNode::SplitContentNode( const SwPosition &rPos )
}
+ if (pContentIndexRestore)
+ { // call before making frames and before RegisterToNode
+ (*pContentIndexRestore)(pNode);
+ }
+
SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*this);
for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
{
@@ -575,6 +581,11 @@ SwContentNode *SwTextNode::SplitContentNode( const SwPosition &rPos )
SetSmartTags( pList2, false );
}
+ if (pContentIndexRestore)
+ { // call before making frames
+ (*pContentIndexRestore)(pNode);
+ }
+
if ( HasWriterListeners() )
{
MakeFramesForAdjacentContentNode(*pNode);
diff --git a/sw/source/core/undo/untbl.cxx b/sw/source/core/undo/untbl.cxx
index 37dd2af987e1..c03142eb2423 100644
--- a/sw/source/core/undo/untbl.cxx
+++ b/sw/source/core/undo/untbl.cxx
@@ -556,10 +556,17 @@ SwTableNode* SwNodes::UndoTableToText( sal_uLong nSttNd, sal_uLong nEndNd,
SwIndex aCntPos( pTextNd, pSave->m_nContent - 1 );
pTextNd->EraseText( aCntPos, 1 );
- SwContentNode* pNewNd = pTextNd->SplitContentNode(
- SwPosition( aSttIdx, aCntPos ));
- if( !pContentStore->Empty() )
- pContentStore->Restore( *pNewNd, pSave->m_nContent, pSave->m_nContent + 1 );
+
+ std::function<void (SwTextNode *)> restoreFunc(
+ [&](SwTextNode *const pNewNode)
+ {
+ if (!pContentStore->Empty())
+ {
+ pContentStore->Restore(*pNewNode, pSave->m_nContent, pSave->m_nContent + 1);
+ }
+ });
+ pTextNd->SplitContentNode(
+ SwPosition(aSttIdx, aCntPos), &restoreFunc);
}
else
{
commit eb4fa9b3084f43aa9c1e86647f09e0670c9c03cf
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 8 13:29:44 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: adapt SwFlyFrameFormat::MakeFrames() ...
... and SwDrawFrameFormat::MakeFrames() to do nothing if anchored in
hidden redline.
Change-Id: Idb0668db81b20ee52cd9c0237c22f8fa72beb7b3
diff --git a/sw/source/core/draw/dcontact.cxx b/sw/source/core/draw/dcontact.cxx
index efe04fe60bc1..3a33d6994fe1 100644
--- a/sw/source/core/draw/dcontact.cxx
+++ b/sw/source/core/draw/dcontact.cxx
@@ -1838,11 +1838,17 @@ void SwDrawContact::ConnectToLayout( const SwFormatAnchor* pAnch )
// (1) proposed anchor frame isn't a follow and
// (2) drawing object isn't a control object to be anchored
// in header/footer.
- const bool bAdd = ( !pFrame->IsContentFrame() ||
+ bool bAdd = ( !pFrame->IsContentFrame() ||
!static_cast<SwContentFrame*>(pFrame)->IsFollow() ) &&
( !::CheckControlLayer( GetMaster() ) ||
!pFrame->FindFooterOrHeader() );
+ if (bAdd && RndStdIds::FLY_AT_FLY != pAnch->GetAnchorId())
+ {
+ assert(pFrame->IsTextFrame());
+ bAdd = IsAnchoredObjShown(*static_cast<SwTextFrame*>(pFrame), *pAnch);
+ }
+
if( bAdd )
{
if ( RndStdIds::FLY_AT_FLY == pAnch->GetAnchorId() && !pFrame->IsFlyFrame() )
diff --git a/sw/source/core/inc/frmtool.hxx b/sw/source/core/inc/frmtool.hxx
index 05b2dc237253..fdc014d8a101 100644
--- a/sw/source/core/inc/frmtool.hxx
+++ b/sw/source/core/inc/frmtool.hxx
@@ -66,6 +66,8 @@ void RemoveHiddenObjsOfNode(SwTextNode const& rNode,
std::vector<sw::Extent>::const_iterator * pIter,
std::vector<sw::Extent>::const_iterator const* pEnd);
+bool IsAnchoredObjShown(SwTextFrame const& rFrame, SwFormatAnchor const& rAnchor);
+
void AppendAllObjs(const SwFrameFormats* pTable, const SwFrame* pSib);
// draw background with brush or graphics
diff --git a/sw/source/core/layout/atrfrm.cxx b/sw/source/core/layout/atrfrm.cxx
index 16a015377fc4..ab1721c70d05 100644
--- a/sw/source/core/layout/atrfrm.cxx
+++ b/sw/source/core/layout/atrfrm.cxx
@@ -57,6 +57,7 @@
#include <rootfrm.hxx>
#include <cntfrm.hxx>
#include <notxtfrm.hxx>
+#include <txtfrm.hxx>
#include <crsrsh.hxx>
#include <dflyobj.hxx>
#include <dcontact.hxx>
@@ -2999,7 +3000,24 @@ void SwFlyFrameFormat::MakeFrames()
}
}
- if( pFrame->GetDrawObjs() )
+ if (bAdd)
+ {
+ switch (aAnchorAttr.GetAnchorId())
+ {
+ case RndStdIds::FLY_AS_CHAR:
+ case RndStdIds::FLY_AT_PARA:
+ case RndStdIds::FLY_AT_CHAR:
+ {
+ assert(pFrame->IsTextFrame());
+ bAdd = IsAnchoredObjShown(*static_cast<SwTextFrame*>(pFrame), aAnchorAttr);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (bAdd && pFrame->GetDrawObjs())
{
// #i28701# - new type <SwSortedObjs>
SwSortedObjs &rObjs = *pFrame->GetDrawObjs();
diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx
index aa5b18415073..697b96f718ff 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -1193,6 +1193,46 @@ void AppendObjs(const SwFrameFormats *const pTable, sal_uLong const nIndex,
}
}
+bool IsAnchoredObjShown(SwTextFrame const& rFrame, SwFormatAnchor const& rAnchor)
+{
+ assert(rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA ||
+ rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR ||
+ rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR);
+ bool ret(true);
+ if (auto const pMergedPara = rFrame.GetMergedPara())
+ {
+ ret = false;
+ auto const pAnchor(rAnchor.GetContentAnchor());
+ auto iterFirst(pMergedPara->extents.cbegin());
+ auto iter(iterFirst);
+ SwTextNode const* pNode(pMergedPara->pFirstNode);
+ for ( ; ; ++iter)
+ {
+ if (iter == pMergedPara->extents.end()
+ || iter->pNode != pNode)
+ {
+ assert(pNode->GetRedlineMergeFlag() != SwNode::Merge::Hidden);
+ if (pNode == &pAnchor->nNode.GetNode())
+ {
+ ret = IsShown(pNode->GetIndex(), rAnchor, &iterFirst, &iter);
+ break;
+ }
+ if (iter == pMergedPara->extents.end())
+ {
+ break;
+ }
+ pNode = iter->pNode;
+ if (pAnchor->nNode.GetIndex() < pNode->GetIndex())
+ {
+ break;
+ }
+ iterFirst = iter;
+ }
+ }
+ }
+ return ret;
+}
+
void AppendAllObjs(const SwFrameFormats* pTable, const SwFrame* pSib)
{
//Connecting of all Objects, which are described in the SpzTable with the
commit 1ef454d76759d0159f6f883f10521bf265cd0c4f
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 7 16:40:02 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: handle flys anchored in flys
There is no way to iterate over the nodes-array such that flys are
ordered wrt. the flys in whose content they are anchored; this makes
it hard to ensure that flys anchored in flys are handled only once.
For the Hide implementation, when the flys anchored to a non-first
merged SwTextNode in a fly are inserted, ensure that the content of
the same fly is skipped if it happens to come later in the nodes-array.
For the Show implementation, the ::MakeFrames() would call
AppendAllObj() anyway; suppress that and manually call it at the end,
which should avoid the problem.
Change-Id: I7fb31cf14ef26c095fa7e09edd4ab530add9f253
diff --git a/sw/source/core/inc/frmtool.hxx b/sw/source/core/inc/frmtool.hxx
index e692bb900ef6..05b2dc237253 100644
--- a/sw/source/core/inc/frmtool.hxx
+++ b/sw/source/core/inc/frmtool.hxx
@@ -66,6 +66,8 @@ void RemoveHiddenObjsOfNode(SwTextNode const& rNode,
std::vector<sw::Extent>::const_iterator * pIter,
std::vector<sw::Extent>::const_iterator const* pEnd);
+void AppendAllObjs(const SwFrameFormats* pTable, const SwFrame* pSib);
+
// draw background with brush or graphics
// The 6th parameter indicates that the method should consider background
// transparency, saved in the color of the brush item.
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index 617c15d94731..513e8c339f8a 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -40,6 +40,7 @@
#include <txtftn.hxx>
#include <fmtftn.hxx>
#include <fmtsrnd.hxx>
+#include <fmtcntnt.hxx>
#include <ftnfrm.hxx>
#include <tabfrm.hxx>
#include <flyfrms.hxx>
@@ -4166,7 +4167,8 @@ void SwRootFrame::InvalidateAllObjPos()
}
static void UnHideRedlines(SwRootFrame & rLayout,
- SwNodes & rNodes, SwNode const& rEndOfSectionNode)
+ SwNodes & rNodes, SwNode const& rEndOfSectionNode,
+ std::set<sal_uLong> *const pSkipped)
{
assert(rEndOfSectionNode.IsEndNode());
for (sal_uLong i = rEndOfSectionNode.StartOfSectionNode()->GetIndex() + 1;
@@ -4251,6 +4253,20 @@ static void UnHideRedlines(SwRootFrame & rLayout,
pNode->GetIndex(), pFrame, pPage,
rTextNode.GetDoc(),
&iterFirst, &iter);
+ if (pSkipped)
+ {
+ // if a fly has been added by AppendObjsOfNode, it must be skipped; if not, then it doesn't matter if it's skipped or not because it has no frames and because of that it would be skipped anyway
+ if (auto const pFlys = pNode->GetAnchoredFlys())
+ {
+ for (auto const pFly : *pFlys)
+ {
+ if (pFly->Which() != RES_DRAWFRMFMT)
+ {
+ pSkipped->insert(pFly->GetContent().GetContentIdx()->GetIndex());
+ }
+ }
+ }
+ }
}
if (iter == pMerged->extents.end())
{
@@ -4302,33 +4318,8 @@ static void UnHideRedlines(SwRootFrame & rLayout,
pNode = rExtent.pNode;
}
}
- // add all flys in first node that are hidden
- std::vector<sw::Extent> hidden;
- sal_Int32 nLast(0);
- for (auto const& rExtent : pMergedPara->extents)
- {
- if (rExtent.pNode != &rTextNode)
- {
- break;
- }
- if (rExtent.nStart != 0)
- {
- assert(rExtent.nStart != nLast);
-
- hidden.emplace_back(&rTextNode, nLast, rExtent.nStart);
- }
- nLast = rExtent.nEnd;
- }
- if (nLast != rTextNode.Len())
- {
- hidden.emplace_back(&rTextNode, nLast, rTextNode.Len());
- }
- SwFrameFormats& rTable(*rTextNode.GetDoc()->GetSpzFrameFormats());
- auto iterBegin(hidden.cbegin());
- auto const iterEnd(hidden.cend());
- AppendObjsOfNode(&rTable, rTextNode.GetIndex(), pFrame,
- pFrame->FindPageFrame(), rTextNode.GetDoc(),
- &iterBegin, &iterEnd);
+ // rely on AppendAllObjs call at the end to add
+ // all flys in first node that are hidden
}
pFrame->SetMergedPara(nullptr);
// ??? TODO recreate? or is invalidate enough?
@@ -4356,6 +4347,7 @@ static void UnHideRedlines(SwRootFrame & rLayout,
}
else
{
+ assert(!rNode.IsContentNode() || !rNode.GetContentNode()->getLayoutFrame(&rLayout));
sal_uLong j = i + 1;
for ( ; j < rEndOfSectionNode.GetIndex(); ++j)
{
@@ -4368,7 +4360,10 @@ static void UnHideRedlines(SwRootFrame & rLayout,
// InsertCnt_ also checks for hidden sections
SwNodeIndex const start(rNodes, i);
SwNodeIndex const end(rNodes, j);
+ assert(!bDontCreateObjects);
+ bDontCreateObjects = true; // suppress here, to be called once
::MakeFrames(rLayout.GetFormat()->GetDoc(), start, end);
+ bDontCreateObjects = false;
i = j - 1; // will be incremented again
}
}
@@ -4376,7 +4371,8 @@ static void UnHideRedlines(SwRootFrame & rLayout,
}
static void UnHideRedlinesExtras(SwRootFrame & rLayout,
- SwNodes & rNodes, SwNode const& rEndOfExtraSectionNode)
+ SwNodes & rNodes, SwNode const& rEndOfExtraSectionNode,
+ std::set<sal_uLong> *const pSkipped)
{
assert(rEndOfExtraSectionNode.IsEndNode());
for (sal_uLong i = rEndOfExtraSectionNode.StartOfSectionNode()->GetIndex()
@@ -4386,8 +4382,8 @@ static void UnHideRedlinesExtras(SwRootFrame & rLayout,
assert(rStartNode.IsStartNode());
assert(rStartNode.GetRedlineMergeFlag() == SwNode::Merge::None);
SwNode const& rEndNode(*rStartNode.EndOfSectionNode());
+ bool bSkip(pSkipped ? pSkipped->find(i) != pSkipped->end() : false);
i = rEndNode.GetIndex();
- bool bSkip(false);
for (sal_uLong j = rStartNode.GetIndex() + 1; j < i; ++j)
{
// note: SwStartNode has no way to access the frames, so check
@@ -4411,7 +4407,7 @@ static void UnHideRedlinesExtras(SwRootFrame & rLayout,
}
if (!bSkip)
{
- UnHideRedlines(rLayout, rNodes, rEndNode);
+ UnHideRedlines(rLayout, rNodes, rEndNode, pSkipped);
}
}
}
@@ -4445,12 +4441,25 @@ void SwRootFrame::SetHideRedlines(bool const bHideRedlines)
// Flys before footnotes: because footnotes may contain flys but not
// vice-versa; alas flys may contain flys, so we skip some of them
// if they have already been created from scratch via their anchor flys.
- UnHideRedlinesExtras(*this, rNodes, rNodes.GetEndOfAutotext());
+ std::set<sal_uLong> skippedFlys;
+ UnHideRedlinesExtras(*this, rNodes, rNodes.GetEndOfAutotext(),
+ // when un-hiding, delay all fly frame creation to AppendAllObjs below
+ IsHideRedlines() ? &skippedFlys : nullptr);
// Footnotes are created automatically (after invalidation etc.) by
// ConnectFootnote(), but need to be deleted manually. Footnotes do not
// occur in flys or headers/footers.
- UnHideRedlinesExtras(*this, rNodes, rNodes.GetEndOfInserts());
- UnHideRedlines(*this, rNodes, rNodes.GetEndOfContent());
+ UnHideRedlinesExtras(*this, rNodes, rNodes.GetEndOfInserts(), nullptr);
+ UnHideRedlines(*this, rNodes, rNodes.GetEndOfContent(), nullptr);
+
+ if (!IsHideRedlines())
+ { // create all previously hidden flys at once:
+ // * Flys on first node of pre-existing merged frames that are hidden
+ // (in delete redline), to be added to the existing frame
+ // * Flys on non-first (hidden/merged) nodes of pre-existing merged
+ // frames, to be added to the new frame of their node
+ // * Flys anchored in other flys that are hidden
+ AppendAllObjs(rDoc.GetSpzFrameFormats(), this);
+ }
// InvalidateAllContent(SwInvalidateFlags::Size); // ??? TODO what to invalidate? this is the big hammer
}
commit 760ffc31353599da00f8dbf341115d5f3dde9f13
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Aug 6 13:31:37 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: disable hiding at-char flys again
Needs changes in Delete for consistency.
Change-Id: If9382ebca9b6335ffef8c738840813837316f841
diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx
index 6a7218bfe886..aa5b18415073 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -1044,7 +1044,10 @@ static bool IsShown(sal_uLong const nIndex,
{
return false;
}
- if (pIter && rAnch.GetAnchorId() != RndStdIds::FLY_AT_PARA)
+ if (pIter && rAnch.GetAnchorId() != RndStdIds::FLY_AT_PARA
+ // sw_redlinehide: we want to hide AT_CHAR, but currently can't
+ // because Delete and Accept Redline don't delete them!
+ && rAnch.GetAnchorId() != RndStdIds::FLY_AT_CHAR)
{
// note: frames are not sorted by anchor position.
assert(pEnd);
commit 5d4c64d73531f5f7bf84050d4f233d55fb23898d
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Aug 6 12:42:27 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: fix use-after-free in SwFootnoteFrame
On hide, the SwTextFootnote::DelFrames() for a note in a deleted frame
must actually delete the frames; if there's a follow SwTextFrame, then it
might erroneously return without deleting anything.
Change-Id: I7e9473b94feaf939be72e285553a8990c2ce1a06
diff --git a/sw/source/core/inc/ftnboss.hxx b/sw/source/core/inc/ftnboss.hxx
index a04c8ae172eb..ba363e53a2f7 100644
--- a/sw/source/core/inc/ftnboss.hxx
+++ b/sw/source/core/inc/ftnboss.hxx
@@ -75,7 +75,7 @@ public:
// footnote interface
void AppendFootnote( SwContentFrame *, SwTextFootnote * );
- void RemoveFootnote( const SwContentFrame *, const SwTextFootnote *, bool bPrep = true );
+ bool RemoveFootnote(const SwContentFrame *, const SwTextFootnote *, bool bPrep = true);
static SwFootnoteFrame *FindFootnote( const SwContentFrame *, const SwTextFootnote * );
SwFootnoteContFrame *FindFootnoteCont();
inline const SwFootnoteContFrame *FindFootnoteCont() const;
diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx
index ed003618424e..b82f23e56198 100644
--- a/sw/source/core/layout/ftnfrm.cxx
+++ b/sw/source/core/layout/ftnfrm.cxx
@@ -1642,12 +1642,15 @@ SwFootnoteFrame *SwFootnoteBossFrame::FindFootnote( const SwContentFrame *pRef,
return nullptr;
}
-void SwFootnoteBossFrame::RemoveFootnote( const SwContentFrame *pRef, const SwTextFootnote *pAttr,
+bool SwFootnoteBossFrame::RemoveFootnote(
+ const SwContentFrame *const pRef, const SwTextFootnote *const pAttr,
bool bPrep )
{
+ bool ret(false);
SwFootnoteFrame *pFootnote = FindFootnote( pRef, pAttr );
if( pFootnote )
{
+ ret = true;
do
{
SwFootnoteFrame *pFoll = pFootnote->GetFollow();
@@ -1664,6 +1667,7 @@ void SwFootnoteBossFrame::RemoveFootnote( const SwContentFrame *pRef, const SwTe
}
}
FindPageFrame()->UpdateFootnoteNum();
+ return ret;
}
void SwFootnoteBossFrame::ChangeFootnoteRef( const SwContentFrame *pOld, const SwTextFootnote *pAttr,
diff --git a/sw/source/core/txtnode/atrftn.cxx b/sw/source/core/txtnode/atrftn.cxx
index 26f41e0333eb..cc0e6f0ea12a 100644
--- a/sw/source/core/txtnode/atrftn.cxx
+++ b/sw/source/core/txtnode/atrftn.cxx
@@ -444,8 +444,12 @@ void SwTextFootnote::DelFrames( const SwFrame* pSib )
SwPageFrame* pPage = pFnd->FindPageFrame();
if( pPage )
{
- pPage->RemoveFootnote( pFnd, this );
- bFrameFnd = true;
+ // note: we have found the correct frame only if the footnote
+ // was actually removed; in case this is called from
+ // SwTextFrame::DestroyImpl(), then that frame isn't connected
+ // to SwPageFrame any more, and RemoveFootnote on any follow
+ // must not prevent the fall-back to the !bFrameFnd code.
+ bFrameFnd = pPage->RemoveFootnote(pFnd, this);
}
}
}
commit c5cd6c03fa09835da40f1fabe7f301b4f6eeba52
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 3 18:48:10 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: try to minimise invalidation on show/hide
InvalidateAllContent(Size) will basically format every paragraph
in the document from scratch; let's try to optimise this a bit
by invalidating only the SwTextFrames that actually contain redlines
and the SwPageFrames they're on, and also invalidate the position
of all flys anchored at these frames as a precautionary measure.
Change-Id: I22ed683dc2225992ee48faa6084f277ef8733e8b
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index bc5aadf13375..617c15d94731 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4208,6 +4208,20 @@ static void UnHideRedlines(SwRootFrame & rLayout,
pFrame->SetMergedPara(std::move(pMerged));
}
auto const pMerged(pFrame->GetMergedPara());
+ if (pMerged)
+ {
+ // invalidate SwInvalidateFlags::Size
+ pFrame->Prepare(PREP_CLEAR, nullptr, false);
+ pFrame->InvalidatePage();
+ if (auto const pObjs = pFrame->GetDrawObjs())
+ { // also invalidate position of existing flys
+ // because they may need to be moved
+ for (auto const pObject : *pObjs)
+ {
+ pObject->InvalidateObjPos();
+ }
+ }
+ }
if (pMerged
// do this only *once*, for the *last* frame
// otherwise AppendObj would create multiple frames for fly-frames!
@@ -4253,6 +4267,16 @@ static void UnHideRedlines(SwRootFrame & rLayout,
{
if (auto const& pMergedPara = pFrame->GetMergedPara())
{
+ // invalidate SwInvalidateFlags::Size
+ pFrame->Prepare(PREP_CLEAR, nullptr, false);
+ pFrame->InvalidatePage();
+ if (auto const pObjs = pFrame->GetDrawObjs())
+ { // also invalidate position of existing flys
+ for (auto const pObject : *pObjs)
+ {
+ pObject->InvalidateObjPos();
+ }
+ }
// SwFlyAtContentFrame::Modify() always appends to
// the master frame, so do the same here.
// (RemoveFootnotesForNode must be called at least once)
@@ -4428,7 +4452,7 @@ void SwRootFrame::SetHideRedlines(bool const bHideRedlines)
UnHideRedlinesExtras(*this, rNodes, rNodes.GetEndOfInserts());
UnHideRedlines(*this, rNodes, rNodes.GetEndOfContent());
- InvalidateAllContent(SwInvalidateFlags::Size); // ??? TODO what to invalidate?
+// InvalidateAllContent(SwInvalidateFlags::Size); // ??? TODO what to invalidate? this is the big hammer
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit cabbe6af56e1083ce3bb016eccb609647010ceb4
Author: Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 2 17:09:53 2018 +0200
Commit: Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Wed Aug 15 11:50:43 2018 +0200
sw_redlinehide_2: show/hide flys in redlines
The old implementation would not actually hide at-char flys but move
the anchor, which is clearly not ideal; better to hide them.
Change-Id: If21d0360e04857752a2c84f5329eadfad7818ac8
diff --git a/sw/source/core/inc/frmtool.hxx b/sw/source/core/inc/frmtool.hxx
index 0ffe4a75c0f6..e692bb900ef6 100644
--- a/sw/source/core/inc/frmtool.hxx
+++ b/sw/source/core/inc/frmtool.hxx
@@ -45,6 +45,8 @@ class GraphicAttr;
class SwPageDesc;
class SwFrameFormats;
class SwRegionRects;
+class SwTextNode;
+namespace sw { struct Extent; }
#define FAR_AWAY (SAL_MAX_INT32 - 20000) // initial position of a Fly
#define BROWSE_HEIGHT (56700L * 10L) // 10 Meters
@@ -55,6 +57,15 @@ class SwRegionRects;
void AppendObjs( const SwFrameFormats *pTable, sal_uLong nIndex,
SwFrame *pFrame, SwPageFrame *pPage, SwDoc* doc );
+void AppendObjsOfNode(SwFrameFormats const* pTable, sal_uLong nIndex,
+ SwFrame * pFrame, SwPageFrame * pPage, SwDoc * pDoc,
+ std::vector<sw::Extent>::const_iterator * pIter,
+ std::vector<sw::Extent>::const_iterator const* pEnd);
+
+void RemoveHiddenObjsOfNode(SwTextNode const& rNode,
+ std::vector<sw::Extent>::const_iterator * pIter,
+ std::vector<sw::Extent>::const_iterator const* pEnd);
+
// draw background with brush or graphics
// The 6th parameter indicates that the method should consider background
// transparency, saved in the color of the brush item.
diff --git a/sw/source/core/layout/frmtool.cxx b/sw/source/core/layout/frmtool.cxx
index 7a0d11e4a5c6..6a7218bfe886 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -1040,32 +1040,63 @@ static bool IsShown(sal_uLong const nIndex,
std::vector<sw::Extent>::const_iterator const*const pEnd)
{
SwPosition const& rAnchor(*rAnch.GetContentAnchor());
+ if (rAnchor.nNode.GetIndex() != nIndex)
+ {
+ return false;
+ }
if (pIter && rAnch.GetAnchorId() != RndStdIds::FLY_AT_PARA)
{
- // TODO are frames sorted by anchor positions perhaps?
+ // note: frames are not sorted by anchor position.
assert(pEnd);
assert(rAnch.GetAnchorId() != RndStdIds::FLY_AT_FLY);
- for ( ; *pIter != *pEnd; ++*pIter)
+ for (auto iter = *pIter; iter != *pEnd; ++iter)
{
- assert((**pIter).pNode->GetIndex() == nIndex);
- if ((**pIter).nStart <= rAnchor.nContent.GetIndex())
+ assert(iter->pNode->GetIndex() == nIndex);
+ if (rAnchor.nContent.GetIndex() < iter->nStart)
{
- // TODO off by one? need < for AS_CHAR but what for AT_CHAR?
- if (rAnchor.nContent.GetIndex() < (**pIter).nEnd)
- {
- return true;
- }
- else
- {
- return false;
- }
+ return false;
+ }
+ // for AS_CHAR obviously must be <
+ // for AT_CHAR it is questionable whether < or <= should be used
+ // and there is the additional corner case of Len() to consider
+ // prefer < for now for symmetry (and inverted usage with
+ // "hidden") and handle special case explicitly
+ if (rAnchor.nContent.GetIndex() < iter->nEnd
+ || iter->nEnd == iter->pNode->Len())
+ {
+ return true;
}
}
return false;
}
else
{
- return rAnch.GetContentAnchor()->nNode.GetIndex() == nIndex;
+ return true;
+ }
+}
+
+void RemoveHiddenObjsOfNode(SwTextNode const& rNode,
+ std::vector<sw::Extent>::const_iterator *const pIter,
+ std::vector<sw::Extent>::const_iterator const*const pEnd)
+{
+ std::vector<SwFrameFormat*> const*const pFlys(rNode.GetAnchoredFlys());
+ if (!pFlys)
+ {
+ return;
+ }
+ for (SwFrameFormat * pFrameFormat : *pFlys)
+ {
+ SwFormatAnchor const& rAnchor = pFrameFormat->GetAnchor();
+ if (rAnchor.GetAnchorId() == RndStdIds::FLY_AT_CHAR
+ || (rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR
+ && RES_DRAWFRMFMT == pFrameFormat->Which()))
+ {
+ assert(rAnchor.GetContentAnchor()->nNode.GetIndex() == rNode.GetIndex());
+ if (!IsShown(rNode.GetIndex(), rAnchor, pIter, pEnd))
+ {
+ pFrameFormat->DelFrames();
+ }
+ }
}
}
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index cfe0d11b56c8..bc5aadf13375 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4182,7 +4182,15 @@ static void UnHideRedlines(SwRootFrame & rLayout,
{
if (pFrame->getRootFrame() == &rLayout)
{
- frames.push_back(pFrame);
+ if (pFrame->IsFollow())
+ {
+ frames.push_back(pFrame);
+ } // when hiding, the loop must remove the anchored flys
+ else // *before* resetting SetMergedPara anywhere - else
+ { // the fly deletion code will access multiple of the
+ // frames with inconsistent MergedPara and assert
+ frames.insert(frames.begin(), pFrame);
+ }
}
}
// this messes with pRegisteredIn so do it outside SwIterator
@@ -4194,29 +4202,111 @@ static void UnHideRedlines(SwRootFrame & rLayout,
rNode.GetRedlineMergeFlag() == SwNode::Merge::NonFirst);
if (rNode.IsCreateFrameWhenHidingRedlines())
{
- pFrame->SetMergedPara(CheckParaRedlineMerge(*pFrame,
- rTextNode, sw::FrameMode::Existing));
- // ??? TODO flys etc.
+ {
+ auto pMerged(CheckParaRedlineMerge(*pFrame,
+ rTextNode, sw::FrameMode::Existing));
+ pFrame->SetMergedPara(std::move(pMerged));
+ }
+ auto const pMerged(pFrame->GetMergedPara());
+ if (pMerged
+ // do this only *once*, for the *last* frame
+ // otherwise AppendObj would create multiple frames for fly-frames!
+ && !pFrame->GetFollow())
+ {
+ // add visible flys in non-first node to merged frame
+ // (hidden flys remain and are deleted via DelFrames())
+ SwFrameFormats& rTable(*rTextNode.GetDoc()->GetSpzFrameFormats());
+ SwPageFrame *const pPage(pFrame->FindPageFrame());
+ std::vector<sw::Extent>::const_iterator iterFirst(pMerged->extents.begin());
+ std::vector<sw::Extent>::const_iterator iter(iterFirst);
+ SwTextNode const* pNode(&rTextNode);
+ for ( ; ; ++iter)
+ {
+ if (iter == pMerged->extents.end()
+ || iter->pNode != pNode)
+ {
+ if (pNode == &rTextNode)
+ { // remove existing hidden at-char anchored flys
+ RemoveHiddenObjsOfNode(
+ rTextNode, &iterFirst, &iter);
+ }
+ else
+ {
+ // pNode's frame has been deleted by CheckParaRedlineMerge()
+ AppendObjsOfNode(&rTable,
+ pNode->GetIndex(), pFrame, pPage,
+ rTextNode.GetDoc(),
+ &iterFirst, &iter);
+ }
+ if (iter == pMerged->extents.end())
+ {
+ break;
+ }
+ pNode = iter->pNode;
+ iterFirst = iter;
+ }
+ }
+ }
}
}
else
{
if (auto const& pMergedPara = pFrame->GetMergedPara())
{
- // the new text frames don't exist yet, so at this point
- // we can only delete the footnote frames so they don't
- // point to the merged SwTextFrame any more...
- SwTextNode const* pNode(&rTextNode);
- for (auto const& rExtent : pMergedPara->extents)
+ // SwFlyAtContentFrame::Modify() always appends to
+ // the master frame, so do the same here.
+ // (RemoveFootnotesForNode must be called at least once)
+ if (!pFrame->IsFollow())
{
- if (rExtent.pNode != pNode)
+ // the new text frames don't exist yet, so at this point
+ // we can only delete the footnote frames so they don't
+ // point to the merged SwTextFrame any more...
+ SwTextNode const* pNode(&rTextNode);
+ for (auto const& rExtent : pMergedPara->extents)
+ {
+ if (rExtent.pNode != pNode)
+ {
+ sw::RemoveFootnotesForNode(*pFrame, *rExtent.pNode, nullptr);
+ // similarly, remove the anchored flys
+ if (auto const pFlys = rExtent.pNode->GetAnchoredFlys())
+ {
+ for (SwFrameFormat * pFormat : *pFlys)
+ {
+ pFormat->DelFrames(/*&rLayout*/);
+ }
+ }
+ pNode = rExtent.pNode;
+ }
+ }
+ // add all flys in first node that are hidden
+ std::vector<sw::Extent> hidden;
+ sal_Int32 nLast(0);
+ for (auto const& rExtent : pMergedPara->extents)
+ {
+ if (rExtent.pNode != &rTextNode)
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list