summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2018-10-30 19:12:39 +0100
committerMichael Stahl <Michael.Stahl@cib.de>2018-11-10 19:47:00 +0100
commit4b7aa86716c12d9ec9310689c73c0862c3fae814 (patch)
treec70117c0e493a1cd6a61b0fd8ba613dc5f8e1199
parent54d27c03e0603d55016678bf94e9191fae0b8c2f (diff)
sw_redlinehide_3: adapt SwDoc::MoveParagraph()
Very tricky... Change-Id: Ic4157d14c2a3ee7c90f103561a376ac6f753a694
-rw-r--r--sw/inc/doc.hxx3
-rw-r--r--sw/source/core/doc/docnum.cxx122
-rw-r--r--sw/source/core/edit/ednumber.cxx33
-rw-r--r--sw/source/core/inc/txtfrm.hxx2
-rw-r--r--sw/source/core/text/txtfrm.cxx17
5 files changed, 171 insertions, 6 deletions
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 1958c34bd1f0..593428d3956a 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 73b8a4dac62f..e1a3844a44ac 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>
@@ -1792,7 +1793,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();
@@ -1994,7 +2108,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 );
@@ -2123,6 +2237,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 3e417e7f9fec..ee35d6e8be8e 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 dfea9d4e2490..5cb4c55facf5 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 8e5d64cbf022..bc5f6e9cfa0f 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