sw_redlinehide_3: adapt SwDoc::MoveParagraph()
Very tricky...
Change-Id: Ic4157d14c2a3ee7c90f103561a376ac6f753a694
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 1958c34..593428d3 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1117,7 +1117,8 @@ public:
/** Move selected paragraphes (not only numberings)
according to offsets. (if negative: go to doc start). */
bool MoveParagraph( const SwPaM&, long nOffset, bool bIsOutlMv = false );
bool MoveParagraph(SwPaM&, long nOffset, bool bIsOutlMv = false);
bool MoveParagraphImpl(SwPaM&, long nOffset, bool bIsOutlMv, SwRootFrame const*);
bool NumOrNoNum( const SwNodeIndex& rIdx, bool bDel = false);
diff --git a/sw/source/core/doc/docnum.cxx b/sw/source/core/doc/docnum.cxx
index c9e6066..fbcb01f 100644
--- a/sw/source/core/doc/docnum.cxx
+++ b/sw/source/core/doc/docnum.cxx
@@ -29,6 +29,7 @@
#include <IDocumentState.hxx>
#include <IDocumentStylePoolAccess.hxx>
#include <pam.hxx>
#include <unocrsr.hxx>
#include <ndtxt.hxx>
#include <doctxm.hxx>
#include <poolfmt.hxx>
@@ -1781,7 +1782,120 @@ bool SwDoc::NumUpDown(const SwPaM& rPam, bool bDown, SwRootFrame const*const pLa
return bRet;
}
bool SwDoc::MoveParagraph( const SwPaM& rPam, long nOffset, bool bIsOutlMv )
// this function doesn't contain any numbering-related code, but it is
// primarily called to move numbering-relevant paragraphs around, hence
// it will expand its selection to include full SwTextFrames.
bool SwDoc::MoveParagraph(SwPaM& rPam, long nOffset, bool const bIsOutlMv)
{
// sw_redlinehide: as long as a layout with Hide mode exists, only
// move nodes that have merged frames *completely*
SwRootFrame const* pLayout(nullptr);
for (SwRootFrame const*const pLay : GetAllLayouts())
{
if (pLay->IsHideRedlines())
{
pLayout = pLay;
}
}
if (pLayout)
{
std::pair<SwTextNode *, SwTextNode *> nodes(
sw::GetFirstAndLastNode(*pLayout, rPam.Start()->nNode));
if (nodes.first && nodes.first != &rPam.Start()->nNode.GetNode())
{
assert(nodes.second);
if (nOffset < 0)
{
nOffset += rPam.Start()->nNode.GetIndex() - nodes.first->GetIndex();
if (0 <= nOffset) // hack: there are callers that know what
{ // node they want; those should never need
nOffset = -1; // this; other callers just pass in -1
} // and those should still move
}
if (!rPam.HasMark())
{
rPam.SetMark();
}
assert(nodes.first->GetIndex() < rPam.Start()->nNode.GetIndex());
rPam.Start()->nNode = *nodes.first;
rPam.Start()->nContent.Assign(nodes.first, 0);
}
nodes = sw::GetFirstAndLastNode(*pLayout, rPam.End()->nNode);
if (nodes.second && nodes.second != &rPam.End()->nNode.GetNode())
{
assert(nodes.first);
if (0 < nOffset)
{
nOffset -= nodes.second->GetIndex() - rPam.End()->nNode.GetIndex();
if (nOffset <= 0) // hack: there are callers that know what
{ // node they want; those should never need
nOffset = +1; // this; other callers just pass in +1
} // and those should still move
}
if (!rPam.HasMark())
{
rPam.SetMark();
}
assert(rPam.End()->nNode.GetIndex() < nodes.second->GetIndex());
rPam.End()->nNode = *nodes.second;
// until end, otherwise Impl will detect overlapping redline
rPam.End()->nContent.Assign(nodes.second, nodes.second->GetTextNode()->Len());
}
if (nOffset > 0)
{ // sw_redlinehide: avoid moving into delete redline, skip forward
if (GetNodes().GetEndOfContent().GetIndex() <= rPam.End()->nNode.GetIndex() + nOffset)
{
return false; // can't move
}
SwNode const* pNode(GetNodes()[rPam.End()->nNode.GetIndex() + nOffset + 1]);
if ( pNode->GetRedlineMergeFlag() != SwNode::Merge::None
&& pNode->GetRedlineMergeFlag() != SwNode::Merge::First)
{
for ( ; ; ++nOffset)
{
pNode = GetNodes()[rPam.End()->nNode.GetIndex() + nOffset];
if (pNode->IsTextNode())
{
nodes = GetFirstAndLastNode(*pLayout, *pNode->GetTextNode());
assert(nodes.first && nodes.second);
nOffset += nodes.second->GetIndex() - pNode->GetIndex();
// on last; will be incremented below to behind-last
break;
}
}
}
}
else
{ // sw_redlinehide: avoid moving into delete redline, skip backward
if (rPam.Start()->nNode.GetIndex() + nOffset < 1)
{
return false; // can't move
}
SwNode const* pNode(GetNodes()[rPam.Start()->nNode.GetIndex() + nOffset]);
if ( pNode->GetRedlineMergeFlag() != SwNode::Merge::None
&& pNode->GetRedlineMergeFlag() != SwNode::Merge::First)
{
for ( ; ; --nOffset)
{
pNode = GetNodes()[rPam.Start()->nNode.GetIndex() + nOffset];
if (pNode->IsTextNode())
{
nodes = GetFirstAndLastNode(*pLayout, *pNode->GetTextNode());
assert(nodes.first && nodes.second);
nOffset -= pNode->GetIndex() - nodes.first->GetIndex();
// on first
break;
}
}
}
}
}
return MoveParagraphImpl(rPam, nOffset, bIsOutlMv, pLayout);
}
bool SwDoc::MoveParagraphImpl(SwPaM& rPam, long const nOffset,
bool const bIsOutlMv, SwRootFrame const*const pLayout)
{
const SwPosition *pStt = rPam.Start(), *pEnd = rPam.End();
@@ -1983,7 +2097,7 @@ bool SwDoc::MoveParagraph( const SwPaM& rPam, long nOffset, bool bIsOutlMv )
SwPaM aPam( pStt->nNode, 0, aMvRg.aEnd, 0 );
SwPaM& rOrigPam = const_cast<SwPaM&>(rPam);
SwPaM& rOrigPam(rPam);
rOrigPam.DeleteMark();
rOrigPam.GetPoint()->nNode = aIdx.GetIndex() - 1;
rOrigPam.GetPoint()->nContent.Assign( rOrigPam.GetContentNode(), 0 );
@@ -2112,6 +2226,10 @@ bool SwDoc::MoveParagraph( const SwPaM& rPam, long nOffset, bool bIsOutlMv )
nMoved = rPam.End()->nNode.GetIndex() - rPam.Start()->nNode.GetIndex() + 1;
}
(void) pLayout; // note: move will insert between aIdx-1 and aIdx
assert(!pLayout // check not moving *into* delete redline (caller's fault)
|| aIdx.GetNode().GetRedlineMergeFlag() == SwNode::Merge::None
|| aIdx.GetNode().GetRedlineMergeFlag() == SwNode::Merge::First);
getIDocumentContentOperations().MoveNodeRange( aMvRg, aIdx, SwMoveFlags::REDLINES );
if( pUndo )
diff --git a/sw/source/core/edit/ednumber.cxx b/sw/source/core/edit/ednumber.cxx
index 3e417e7..ee35d6e 100644
--- a/sw/source/core/edit/ednumber.cxx
+++ b/sw/source/core/edit/ednumber.cxx
@@ -460,6 +460,13 @@ bool SwEditShell::MoveNumParas( bool bUpperLower, bool bUpperLeft )
else
{
sal_uLong nStt = aPos.nNode.GetIndex(), nIdx = nStt - 1;
if (SwTextNode const*const pStt = aPos.nNode.GetNode().GetTextNode())
{
std::pair<SwTextNode *, SwTextNode *> nodes(
sw::GetFirstAndLastNode(*GetLayout(), *pStt));
nIdx = nodes.first->GetIndex() - 1;
}
while( nIdx && (
( pNd = GetDoc()->GetNodes()[ nIdx ])->IsSectionNode() ||
( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode())))
@@ -477,18 +484,38 @@ bool SwEditShell::MoveNumParas( bool bUpperLower, bool bUpperLeft )
pOrig == aCursor.GetNode().GetTextNode()->GetNumRule() )
{
sal_uLong nStt = aCursor.GetPoint()->nNode.GetIndex(), nIdx = nStt+1;
if (SwTextNode const*const pStt = aCursor.GetPoint()->nNode.GetNode().GetTextNode())
{
std::pair<SwTextNode *, SwTextNode *> nodes(
sw::GetFirstAndLastNode(*GetLayout(), *pStt));
nIdx = nodes.second->GetIndex() + 1;
}
while (nIdx < GetDoc()->GetNodes().Count()-1)
{
pNd = GetDoc()->GetNodes()[ nIdx ];
if (pNd->IsSectionNode() ||
( pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode()) ||
( pNd->IsTextNode() && pOrig == static_cast<const SwTextNode*>(pNd)->GetNumRule() &&
static_cast<const SwTextNode*>(pNd)->GetActualListLevel() > nUpperLevel ))
(pNd->IsEndNode() && pNd->StartOfSectionNode()->IsSectionNode()))
{
++nIdx;
}
else if (pNd->IsTextNode())
{
SwTextNode const*const pTextNode =
sw::GetParaPropsNode(*GetLayout(), SwNodeIndex(*pNd));
if (pOrig == pTextNode->GetNumRule()
&& pTextNode->GetActualListLevel() > nUpperLevel)
{
std::pair<SwTextNode *, SwTextNode *> nodes(
sw::GetFirstAndLastNode(*GetLayout(), *pTextNode));
nIdx = nodes.second->GetIndex() + 1;
}
else
{
break;
}
}
// #i57856#
else
{
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index dfea9d4..5cb4c55 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -103,6 +103,8 @@ bool FrameContainsNode(SwContentFrame const& rFrame, sal_uLong nNodeIndex);
bool IsParaPropsNode(SwRootFrame const& rLayout, SwTextNode const& rNode);
SwTextNode * GetParaPropsNode(SwRootFrame const& rLayout, SwNodeIndex const& rNode);
SwPosition GetParaPropsPos(SwRootFrame const& rLayout, SwPosition const& rPos);
std::pair<SwTextNode *, SwTextNode *>
GetFirstAndLastNode(SwRootFrame const& rLayout, SwNodeIndex const& rPos);
TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged,
bool isRealDelete,
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 8e5d64c..bc5f6e9 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -351,6 +351,23 @@ namespace sw {
return pos;
}
std::pair<SwTextNode *, SwTextNode *>
GetFirstAndLastNode(SwRootFrame const& rLayout, SwNodeIndex const& rPos)
{
SwTextNode *const pTextNode(rPos.GetNode().GetTextNode());
if (pTextNode && rLayout.IsHideRedlines())
{
if (SwTextFrame const*const pFrame = static_cast<SwTextFrame*>(pTextNode->getLayoutFrame(&rLayout)))
{
if (sw::MergedPara const*const pMerged = pFrame->GetMergedPara())
{
return std::make_pair(pMerged->pFirstNode, const_cast<SwTextNode*>(pMerged->pLastNode));
}
}
}
return std::make_pair(pTextNode, pTextNode);
}
} // namespace sw
/// Switches width and height of the text frame