[Libreoffice-commits] core.git: Branch 'private/mst/sw_redlinehide_2' - 35 commits - solenv/gbuild sw/inc sw/qa sw/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Fri Sep 14 12:38:12 UTC 2018


Rebased ref, commits from common ancestor:
commit a2476095646cea63f50b58bcb6fa9d332b09ea15
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Sep 14 14:35:00 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: adapt SwEditShell::GetCurWord()
    
    Move SwTextNode::GetCurWord() to SwTextFrame, this was the only caller.
    
    Change-Id: Id26cea92e1ca507fd82c5c75bc5a6eedb531d78d

diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 0f2c5c6347ee..5278b89c17c8 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -404,7 +404,6 @@ public:
         const sal_Int32 nIndex,
         const bool bIncludeInputFieldAtStart = false ) const;
 
-    OUString GetCurWord(sal_Int32) const;
     bool Spell(SwSpellArgs*);
     bool Convert( SwConversionArgs & );
 
diff --git a/sw/source/core/edit/editsh.cxx b/sw/source/core/edit/editsh.cxx
index 04bd08bb8f6f..87efba3c8d18 100644
--- a/sw/source/core/edit/editsh.cxx
+++ b/sw/source/core/edit/editsh.cxx
@@ -415,10 +415,16 @@ OUString SwEditShell::GetCurWord()
 {
     const SwPaM& rPaM = *GetCursor();
     const SwTextNode* pNd = rPaM.GetNode().GetTextNode();
-    OUString aString = pNd ?
-                     pNd->GetCurWord(rPaM.GetPoint()->nContent.GetIndex()) :
-                     OUString();
-    return aString;
+    if (!pNd)
+    {
+        return OUString();
+    }
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(pNd->getLayoutFrame(GetLayout())));
+    if (pFrame)
+    {
+        return pFrame->GetCurWord(*rPaM.GetPoint());
+    }
+    return OUString();
 }
 
 void SwEditShell::UpdateDocStat( )
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index a9d3a6dd1fe5..0933a5e328db 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -742,6 +742,9 @@ public:
 
     void RegisterToNode(SwTextNode &, bool isForceNodeAsFirst = false);
 
+    bool IsSymbolAt(TextFrameIndex) const;
+    OUString GetCurWord(SwPosition const&) const;
+
     virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const override;
 };
 
diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx
index 4134c73f1b90..3d95f5aefc68 100644
--- a/sw/source/core/text/itratr.cxx
+++ b/sw/source/core/text/itratr.cxx
@@ -188,6 +188,13 @@ bool SwAttrIter::IsSymbol(TextFrameIndex const nNewPos)
     return m_pFont->IsSymbol( m_pViewShell );
 }
 
+bool SwTextFrame::IsSymbolAt(TextFrameIndex const nPos) const
+{
+    SwTextInfo info(const_cast<SwTextFrame*>(this));
+    SwTextIter iter(const_cast<SwTextFrame*>(this), &info);
+    return iter.IsSymbol(nPos);
+}
+
 bool SwAttrIter::SeekStartAndChgAttrIter( OutputDevice* pOut, const bool bParaFont )
 {
     SwTextNode const*const pFirstTextNode(m_pMergedPara ? m_pMergedPara->pFirstNode : m_pTextNode);
diff --git a/sw/source/core/txtnode/txtedt.cxx b/sw/source/core/txtnode/txtedt.cxx
index 19a239c7cca8..5cc101729bcc 100644
--- a/sw/source/core/txtnode/txtedt.cxx
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -695,36 +695,43 @@ sal_Int32 clipIndexBounds(const OUString &rStr, sal_Int32 nPos)
 // Search from left to right, so find the word before nPos.
 // Except if at the start of the paragraph, then return the first word.
 // If the first word consists only of whitespace, return an empty string.
-OUString SwTextNode::GetCurWord( sal_Int32 nPos ) const
+OUString SwTextFrame::GetCurWord(SwPosition const& rPos) const
 {
-    assert(nPos <= m_Text.getLength()); // invalid index
+    TextFrameIndex const nPos(MapModelToViewPos(rPos));
+    SwTextNode *const pTextNode(rPos.nNode.GetNode().GetTextNode());
+    assert(pTextNode);
+    OUString const& rText(GetText());
+    assert(sal_Int32(nPos) <= rText.getLength()); // invalid index
 
-    if (m_Text.isEmpty())
-        return m_Text;
+    if (rText.isEmpty())
+        return OUString();
 
     assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
     const uno::Reference< XBreakIterator > &rxBreak = g_pBreakIt->GetBreakIter();
     sal_Int16 nWordType = WordType::DICTIONARY_WORD;
-    lang::Locale aLocale( g_pBreakIt->GetLocale( GetLang( nPos ) ) );
+    lang::Locale aLocale( g_pBreakIt->GetLocale(pTextNode->GetLang(rPos.nContent.GetIndex())) );
     Boundary aBndry =
-        rxBreak->getWordBoundary( m_Text, nPos, aLocale, nWordType, true );
+        rxBreak->getWordBoundary(rText, sal_Int32(nPos), aLocale, nWordType, true);
 
     // if no word was found use previous word (if any)
     if (aBndry.startPos == aBndry.endPos)
     {
-        aBndry = rxBreak->previousWord( m_Text, nPos, aLocale, nWordType );
+        aBndry = rxBreak->previousWord(rText, sal_Int32(nPos), aLocale, nWordType);
     }
 
     // check if word was found and if it uses a symbol font, if so
     // enforce returning an empty string
-    if (aBndry.endPos != aBndry.startPos && IsSymbolAt(aBndry.startPos))
+    if (aBndry.endPos != aBndry.startPos
+        && IsSymbolAt(TextFrameIndex(aBndry.startPos)))
+    {
         aBndry.endPos = aBndry.startPos;
+    }
 
     // can have -1 as start/end of bounds not found
-    aBndry.startPos = clipIndexBounds(m_Text, aBndry.startPos);
-    aBndry.endPos = clipIndexBounds(m_Text, aBndry.endPos);
+    aBndry.startPos = clipIndexBounds(rText, aBndry.startPos);
+    aBndry.endPos = clipIndexBounds(rText, aBndry.endPos);
 
-    return m_Text.copy(aBndry.startPos,
+    return  rText.copy(aBndry.startPos,
                        aBndry.endPos - aBndry.startPos);
 }
 
commit 513b7a07552af3b318aa426745b046448a7ea768
Author:     Michael Stahl <mstahl at redhat.com>
AuthorDate: Wed May 20 13:18:42 2015 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    gbuild: allow recording of CppunitTests and PythonTests too
    
    Since these don't use soffice they need to be tweaked to use RR varaiable.
    
    Unfortunately rr crashes in some CppunitTest so don't enable that now.
    Unfortunately rr crashes in PythonTest.
    
    Change-Id: I2143618fa2181e36b6aaeded43637cb3481f5e47

diff --git a/solenv/gbuild/CppunitTest.mk b/solenv/gbuild/CppunitTest.mk
index 1ac3b210e149..8e130d481802 100644
--- a/solenv/gbuild/CppunitTest.mk
+++ b/solenv/gbuild/CppunitTest.mk
@@ -63,6 +63,10 @@ gb_CppunitTest_VALGRINDTOOL += --vgdb=yes --vgdb-error=0
 endif
 endif
 
+ifneq ($(strip $(RR)),)
+gb_CppunitTest_RR := rr record
+endif
+
 # defined by platform
 #  gb_CppunitTest_get_filename
 gb_CppunitTest_RUNTIMEDEPS := $(call gb_Executable_get_runtime_dependencies,cppunittester)
@@ -134,7 +138,8 @@ else
 		$(gb_CppunitTest_malloc_check) \
 		$(if $(strip $(PYTHON_URE)),\
 			PYTHONDONTWRITEBYTECODE=1) \
-		$(ICECREAM_RUN) $(gb_CppunitTest_GDBTRACE) $(gb_CppunitTest_VALGRINDTOOL) $(gb_CppunitTest_CPPTESTCOMMAND) \
+		$(ICECREAM_RUN) $(gb_CppunitTest_GDBTRACE) $(gb_CppunitTest_VALGRINDTOOL) $(gb_CppunitTest_RR) \
+			$(gb_CppunitTest_CPPTESTCOMMAND) \
 		$(call gb_LinkTarget_get_target,$(call gb_CppunitTest_get_linktarget,$*)) \
 		$(call gb_CppunitTest__make_args) "-env:CPPUNITTESTTARGET=$@" \
 		$(if $(gb_CppunitTest_POSTGDBTRACE), \
diff --git a/solenv/gbuild/PythonTest.mk b/solenv/gbuild/PythonTest.mk
index c579a34ea6d5..a2bac3819e02 100644
--- a/solenv/gbuild/PythonTest.mk
+++ b/solenv/gbuild/PythonTest.mk
@@ -55,7 +55,7 @@ else
 		$(if $(filter-out MACOSX WNT,$(OS_FOR_BUILD)),$(if $(DISABLE_GUI),, \
 			SAL_USE_VCLPLUGIN=svp \
 		)) \
-		$(gb_CppunitTest_GDBTRACE) $(gb_CppunitTest_VALGRINDTOOL) \
+		$(gb_CppunitTest_GDBTRACE) $(gb_CppunitTest_VALGRINDTOOL) $(gb_CppunitTest_RR) \
 			$(gb_PythonTest_COMMAND) \
 			$(if $(PYTHON_TEST_NAME),$(PYTHON_TEST_NAME),$(MODULES)) \
 		$(if $(gb_CppunitTest__interactive),, \
commit 82c22d0329228d216414b978424faff9e11bb3bc
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Sep 13 20:42:03 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: fix FrameContainsNode() to use pLastNode
    
    Change-Id: Iaa67b9a0134971917c18c9d6f678f6d2913db666

diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 56bbc10111f2..b61c1341d222 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -291,12 +291,7 @@ namespace sw {
             if (sw::MergedPara const*const pMerged = rTextFrame.GetMergedPara())
             {
                 sal_uLong const nFirst(pMerged->pFirstNode->GetIndex());
-                sal_uLong nLast(nFirst);
-                // FIXME is this actually the last one? what about delete RL that dels last node until end, what happens to its anchored objs?
-                if (!pMerged->extents.empty())
-                {
-                    nLast = pMerged->extents.back().pNode->GetIndex();
-                }
+                sal_uLong const nLast(pMerged->pLastNode->GetIndex());
                 return (nFirst <= nNodeIndex && nNodeIndex <= nLast);
             }
             else
commit b9a46bce2f4549c4ce8a7b7fc55308b720974478
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Sep 13 20:40:24 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: view cursor: adapt SwCursorShell::GetSelText()
    
    Pass in ExpandMode::HideDeletions to get the same effect (hopefully)
    from the model code as from the merged text frame.
    
    Change-Id: I546f51388bc7bd0d1740167062ef9171a37d1797

diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 07e298842e25..b6d662b372db 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -2394,6 +2394,40 @@ void SwCursorShell::CallChgLnk()
 OUString SwCursorShell::GetSelText() const
 {
     OUString aText;
+    if (GetLayout()->IsHideRedlines())
+    {
+        SwContentFrame const*const pFrame(GetCurrFrame(false));
+        if (FrameContainsNode(*pFrame, m_pCurrentCursor->GetMark()->nNode.GetIndex()))
+        {
+            OUStringBuffer buf;
+            SwPosition const*const pStart(m_pCurrentCursor->Start());
+            SwPosition const*const pEnd(m_pCurrentCursor->End());
+            for (sal_uLong i = pStart->nNode.GetIndex(); i <= pEnd->nNode.GetIndex(); ++i)
+            {
+                SwNode const& rNode(*pStart->nNode.GetNodes()[i]);
+                assert(!rNode.IsEndNode());
+                if (rNode.IsStartNode())
+                {
+                    i = rNode.EndOfSectionIndex();
+                }
+                else if (rNode.IsTextNode())
+                {
+                    sal_Int32 const nStart(i == pStart->nNode.GetIndex()
+                            ? pStart->nContent.GetIndex()
+                            : 0);
+                    sal_Int32 const nEnd(i == pEnd->nNode.GetIndex()
+                            ? pEnd->nContent.GetIndex()
+                            : pEnd->nNode.GetNode().GetTextNode()->Len());
+                    buf.append(rNode.GetTextNode()->GetExpandText(
+                                nStart, nEnd - nStart, false, false, false,
+                                ExpandMode::HideDeletions));
+
+                }
+            }
+            aText = buf.makeStringAndClear();
+        }
+    }
+    else
     if( m_pCurrentCursor->GetPoint()->nNode.GetIndex() ==
         m_pCurrentCursor->GetMark()->nNode.GetIndex() )
     {
commit bfe3992a561054252ddb803902cdedd9e28a8ff2
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Sep 13 20:38:36 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: remove one bool from SwTextNode::ExpandText()
    
    ... to make call sites both more readable and more flexible.
    
    Change-Id: I28932290799cb3c354cdcaad8e426050bcfede50

diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index 2a5e48145cd8..0f2c5c6347ee 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -61,6 +61,7 @@ class SwWrongList;
 class SwGrammarMarkUp;
 struct SwDocStat;
 struct SwParaIdleData_Impl;
+enum class ExpandMode;
 
 namespace sw { namespace mark { enum class RestoreMode; } }
 
@@ -686,7 +687,7 @@ public:
                             const bool bWithNum = false,
                             const bool bAddSpaceAfterListLabelStr = false,
                             const bool bWithSpacesForLevel = false,
-                            const bool bWithFootnote = true ) const;
+                            const ExpandMode eAdditionalMode = ExpandMode(0)) const;
     bool GetExpandText( SwTextNode& rDestNd, const SwIndex* pDestIdx,
                            sal_Int32 nIdx, sal_Int32 nLen,
                            bool bWithNum = false, bool bWithFootnote = true,
diff --git a/sw/source/core/doc/DocumentOutlineNodesManager.cxx b/sw/source/core/doc/DocumentOutlineNodesManager.cxx
index c129887b7f68..db448ec4f609 100644
--- a/sw/source/core/doc/DocumentOutlineNodesManager.cxx
+++ b/sw/source/core/doc/DocumentOutlineNodesManager.cxx
@@ -19,6 +19,7 @@
 #include <DocumentOutlineNodesManager.hxx>
 #include <doc.hxx>
 #include <ndtxt.hxx>
+#include <modeltoviewhelper.hxx>
 
 namespace sw
 {
@@ -45,7 +46,8 @@ OUString DocumentOutlineNodesManager::getOutlineText( const tSortedOutlineNodeLi
 {
     return m_rDoc.GetNodes().GetOutLineNds()[ nIdx ]->
                 GetTextNode()->GetExpandText( 0, -1, bWithNumber,
-                                            bWithNumber, bWithSpacesForLevel, bWithFootnote );
+                    bWithNumber, bWithSpacesForLevel,
+                    bWithFootnote ? ExpandMode::ExpandFootnote : ExpandMode(0));
 }
 
 SwTextNode* DocumentOutlineNodesManager::getOutlineNode( const tSortedOutlineNodeList::size_type nIdx ) const
diff --git a/sw/source/core/fields/chpfld.cxx b/sw/source/core/fields/chpfld.cxx
index 68b2749cedc6..7093e940764a 100644
--- a/sw/source/core/fields/chpfld.cxx
+++ b/sw/source/core/fields/chpfld.cxx
@@ -187,7 +187,7 @@ void SwChapterField::ChangeExpansion(const SwTextNode &rTextNd, bool bSrchNum)
             sNumber = "??";
         }
 
-        sTitle = removeControlChars(pTextNd->GetExpandText(0, -1, false, false, false, false));
+        sTitle = removeControlChars(pTextNd->GetExpandText(0, -1, false, false, false));
 
     }
 }
diff --git a/sw/source/core/fields/reffld.cxx b/sw/source/core/fields/reffld.cxx
index b7ad1cb81f33..e1ca14410486 100644
--- a/sw/source/core/fields/reffld.cxx
+++ b/sw/source/core/fields/reffld.cxx
@@ -396,7 +396,7 @@ OUString SwGetRefField::GetExpandedTextOfReferencedTextNode() const
 {
     const SwTextNode* pReferencedTextNode( GetReferencedTextNode() );
     return pReferencedTextNode
-           ? pReferencedTextNode->GetExpandText( 0, -1, true, true, false, false )
+           ? pReferencedTextNode->GetExpandText(0, -1, true, true, false)
            : OUString();
 }
 
@@ -538,7 +538,7 @@ void SwGetRefField::UpdateField( const SwTextField* pFieldTextAttr )
 
             if( nStart != nEnd ) // a section?
             {
-                m_sText = pTextNd->GetExpandText( nStart, nEnd - nStart, false, false, false, false );
+                m_sText = pTextNd->GetExpandText(nStart, nEnd - nStart, false, false, false);
 
                 // remove all special characters (replace them with blanks)
                 if( !m_sText.isEmpty() )
diff --git a/sw/source/core/tox/txmsrt.cxx b/sw/source/core/tox/txmsrt.cxx
index a5dbd956b0c5..801c7679d26d 100644
--- a/sw/source/core/tox/txmsrt.cxx
+++ b/sw/source/core/tox/txmsrt.cxx
@@ -502,7 +502,7 @@ TextAndReading SwTOXPara::GetText_Impl() const
             return TextAndReading(static_cast<const SwTextNode*>(pNd)->GetExpandText(
                     nStartIndex,
                     nEndIndex == -1 ? -1 : nEndIndex - nStartIndex,
-                    false, false, false, false),
+                    false, false, false),
                     OUString());
         }
         break;
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index 7302a168c840..6414f900887b 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -3396,12 +3396,10 @@ OUString SwTextNode::GetExpandText(  const sal_Int32 nIdx,
                                    const bool bWithNum,
                                    const bool bAddSpaceAfterListLabelStr,
                                    const bool bWithSpacesForLevel,
-                                   const bool bWithFootnote ) const
+                                   const ExpandMode eAdditionalMode) const
 
 {
-    ExpandMode eMode = ExpandMode::ExpandFields;
-    if (bWithFootnote)
-        eMode |= ExpandMode::ExpandFootnote;
+    ExpandMode eMode = ExpandMode::ExpandFields | eAdditionalMode;
 
     ModelToViewHelper aConversionMap(*this, eMode);
     const OUString aExpandText = aConversionMap.getViewText();
commit 46c388988d9ec9d79d8b3413a667a996fcf88ca9
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Sep 13 20:30:06 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: view cursor: IsSelOnePara(),IsStartPara(),IsEndPara()
    
    Change-Id: Idb7bdc139e501dfbd7e7d3b2d4598d211fa11591

diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 12337a2da62c..327674e3c547 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -502,7 +502,7 @@ public:
     bool ShouldWait() const;
 
     // Check if selection is within one paragraph.
-    inline bool IsSelOnePara() const;
+    bool IsSelOnePara() const;
 
     /*
      * Returns SRectangle, at which the cursor is located.
@@ -870,12 +870,6 @@ inline bool SwCursorShell::IsMultiSelection() const
     return m_pCurrentCursor->GetNext() != m_pCurrentCursor;
 }
 
-inline bool SwCursorShell::IsSelOnePara() const
-{
-    return !m_pCurrentCursor->IsMultiSelection() &&
-           m_pCurrentCursor->GetPoint()->nNode == m_pCurrentCursor->GetMark()->nNode;
-}
-
 inline const SwTableNode* SwCursorShell::IsCursorInTable() const
 {
     return m_pCurrentCursor->GetNode().FindTableNode();
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 25d7be2305fb..07e298842e25 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -1052,11 +1052,62 @@ int SwCursorShell::CompareCursorStackMkCurrPt() const
     return nRet;
 }
 
+bool SwCursorShell::IsSelOnePara() const
+{
+    if (m_pCurrentCursor->IsMultiSelection())
+    {
+        return false;
+    }
+    if (m_pCurrentCursor->GetPoint()->nNode == m_pCurrentCursor->GetMark()->nNode)
+    {
+        return true;
+    }
+    if (GetLayout()->IsHideRedlines())
+    {
+        SwContentFrame const*const pFrame(GetCurrFrame(false));
+        auto const n(m_pCurrentCursor->GetPoint()->nNode.GetIndex());
+        return FrameContainsNode(*pFrame, n);
+    }
+    return false;
+}
+
 bool SwCursorShell::IsSttPara() const
-{   return m_pCurrentCursor->GetPoint()->nContent == 0; }
+{
+    if (GetLayout()->IsHideRedlines())
+    {
+        SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->nNode.GetNode().GetTextNode());
+        if (pNode)
+        {
+            SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(
+                        pNode->getLayoutFrame(GetLayout())));
+            if (pFrame)
+            {
+                return pFrame->MapModelToViewPos(*m_pCurrentCursor->GetPoint())
+                    == TextFrameIndex(0);
+            }
+        }
+    }
+    return m_pCurrentCursor->GetPoint()->nContent == 0;
+}
 
 bool SwCursorShell::IsEndPara() const
-{   return m_pCurrentCursor->GetPoint()->nContent == m_pCurrentCursor->GetContentNode()->Len(); }
+{
+    if (GetLayout()->IsHideRedlines())
+    {
+        SwTextNode const*const pNode(m_pCurrentCursor->GetPoint()->nNode.GetNode().GetTextNode());
+        if (pNode)
+        {
+            SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(
+                        pNode->getLayoutFrame(GetLayout())));
+            if (pFrame)
+            {
+                return pFrame->MapModelToViewPos(*m_pCurrentCursor->GetPoint())
+                    == TextFrameIndex(pFrame->GetText().getLength());
+            }
+        }
+    }
+    return m_pCurrentCursor->GetPoint()->nContent == m_pCurrentCursor->GetContentNode()->Len();
+}
 
 bool SwCursorShell::IsEndOfTable() const
 {
commit e707c7f28b103efb10151b4511b4f12422d4bbfb
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Sep 13 20:09:49 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: remove GetTextUntilEndOfNode()
    
    This is pretty silly, the only caller is actually interested in the
    position of the cursor, not any text at all.
    
    Change-Id: Ibf016d5526e18775c0e6e365b9823723267e76d5

diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index ca221d5b6b35..12337a2da62c 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -566,9 +566,6 @@ public:
     // get the selected text at the current cursor. it will be filled with
     // fields etc.
     OUString GetSelText() const;
-    // return only the text starting from the current cursor position (to the
-    // end of the node)
-    OUString GetTextUntilEndOfNode() const;
 
     // Check of SPoint or Mark of current cursor are placed within a table.
     inline const SwTableNode* IsCursorInTable() const;
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 68e83859adab..25d7be2305fb 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -2357,21 +2357,6 @@ OUString SwCursorShell::GetSelText() const
     return aText;
 }
 
-/// get text only from current cursor position (until end of node)
-OUString SwCursorShell::GetTextUntilEndOfNode() const
-{
-    OUString aText;
-    if( m_pCurrentCursor->GetPoint()->nNode.GetIndex() ==
-        m_pCurrentCursor->GetMark()->nNode.GetIndex() )
-    {
-        SwTextNode* pTextNd = m_pCurrentCursor->GetNode().GetTextNode();
-        if( pTextNd )
-            aText = pTextNd->GetText().copy(
-                    m_pCurrentCursor->GetPoint()->nContent.GetIndex() );
-    }
-    return aText;
-}
-
 /** get the nth character of the current SSelection
 
     @param bEnd    Start counting from the end? From start otherwise.
diff --git a/sw/source/ui/dbui/mmlayoutpage.cxx b/sw/source/ui/dbui/mmlayoutpage.cxx
index 1a6e8ba28547..fecbff79b026 100644
--- a/sw/source/ui/dbui/mmlayoutpage.cxx
+++ b/sw/source/ui/dbui/mmlayoutpage.cxx
@@ -454,7 +454,7 @@ void SwMailMergeLayoutPage::InsertGreeting(SwWrtShell& rShell, SwMailMergeConfig
         //we may end up inside of a paragraph if the left margin is not at DEFAULT_LEFT_DISTANCE
         rShell.MovePara(GoCurrPara, fnParaStart);
     }
-    bool bSplitNode = !rShell.GetTextUntilEndOfNode().isEmpty();
+    bool bSplitNode = !rShell.IsEndPara();
     sal_Int32 nMoves = rConfigItem.GetGreetingMoves();
     if( !bExample && 0 != nMoves )
     {
commit ef0b8d675e9ce997ab5aae511673f5186544cc93
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Sep 13 19:21:46 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: rename SwCursorShell::GetText()
    
    It's really not obvious *what* you can get here.
    
    Change-Id: I1f14b851a127847206f8eb5fd2da778d0acece9b

diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index 8b736656dec9..ca221d5b6b35 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -568,7 +568,7 @@ public:
     OUString GetSelText() const;
     // return only the text starting from the current cursor position (to the
     // end of the node)
-    OUString GetText() const;
+    OUString GetTextUntilEndOfNode() const;
 
     // Check of SPoint or Mark of current cursor are placed within a table.
     inline const SwTableNode* IsCursorInTable() const;
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 1cbcd78e7297..68e83859adab 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -2358,7 +2358,7 @@ OUString SwCursorShell::GetSelText() const
 }
 
 /// get text only from current cursor position (until end of node)
-OUString SwCursorShell::GetText() const
+OUString SwCursorShell::GetTextUntilEndOfNode() const
 {
     OUString aText;
     if( m_pCurrentCursor->GetPoint()->nNode.GetIndex() ==
diff --git a/sw/source/ui/dbui/mmlayoutpage.cxx b/sw/source/ui/dbui/mmlayoutpage.cxx
index 23e6d7b845a2..1a6e8ba28547 100644
--- a/sw/source/ui/dbui/mmlayoutpage.cxx
+++ b/sw/source/ui/dbui/mmlayoutpage.cxx
@@ -454,7 +454,7 @@ void SwMailMergeLayoutPage::InsertGreeting(SwWrtShell& rShell, SwMailMergeConfig
         //we may end up inside of a paragraph if the left margin is not at DEFAULT_LEFT_DISTANCE
         rShell.MovePara(GoCurrPara, fnParaStart);
     }
-    bool bSplitNode = !rShell.GetText().isEmpty();
+    bool bSplitNode = !rShell.GetTextUntilEndOfNode().isEmpty();
     sal_Int32 nMoves = rConfigItem.GetGreetingMoves();
     if( !bExample && 0 != nMoves )
     {
commit bb4ded91c123d07b775101f151851c3bd61f89ed
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Sep 13 12:18:48 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: view cursor movement, prev/next/start/end paragraph
    
    This is used by Ctrl+Up/Down.
    
    Just iterate movement in SwCursorShell::MovePara() until the point
    is at the start (or end) of a frame.
    
    Change-Id: I8abab57f1b549a3d585a385181cf734d73a0286a

diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index f29462b9b268..1cbcd78e7297 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -651,6 +651,32 @@ bool SwCursorShell::isInHiddenTextFrame(SwShellCursor* pShellCursor)
     return !pFrame || (pFrame->IsTextFrame() && static_cast<SwTextFrame*>(pFrame)->IsHiddenNow());
 }
 
+// sw_redlinehide: this should work for all cases: GoCurrPara, GoNextPara, GoPrevPara
+static bool IsAtStartOrEndOfFrame(SwCursorShell const*const pShell,
+    SwShellCursor const*const pShellCursor, SwMoveFnCollection const& fnPosPara)
+{
+    SwContentNode *const pCNode = pShellCursor->GetContentNode();
+    assert(pCNode); // surely can't have moved otherwise?
+    SwContentFrame const*const pFrame = pCNode->getLayoutFrame(
+            pShell->GetLayout(), &pShellCursor->GetPtPos(),
+            pShellCursor->GetPoint(), false);
+    if (!pFrame || !pFrame->IsTextFrame())
+    {
+        return false;
+    }
+    SwTextFrame const& rTextFrame(static_cast<SwTextFrame const&>(*pFrame));
+    TextFrameIndex const ix(rTextFrame.MapModelToViewPos(*pShellCursor->GetPoint()));
+    if (&fnParaStart == &fnPosPara)
+    {
+        return ix == TextFrameIndex(0);
+    }
+    else
+    {
+        assert(&fnParaEnd == &fnPosPara);
+        return ix == TextFrameIndex(rTextFrame.GetText().getLength());
+    }
+}
+
 bool SwCursorShell::MovePara(SwWhichPara fnWhichPara, SwMoveFnCollection const & fnPosPara )
 {
     SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
@@ -663,7 +689,8 @@ bool SwCursorShell::MovePara(SwWhichPara fnWhichPara, SwMoveFnCollection const &
         //which is what SwCursorShell::UpdateCursorPos will reset
         //the position to if we pass it a position in an
         //invisible hidden paragraph field
-        while (isInHiddenTextFrame(pTmpCursor))
+        while (isInHiddenTextFrame(pTmpCursor)
+                || !IsAtStartOrEndOfFrame(this, pTmpCursor, fnPosPara))
         {
             if (!pTmpCursor->MovePara(fnWhichPara, fnPosPara))
                 break;
commit ebe7b8cedda202b89c537fedff720886989f0160
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Sep 12 17:52:36 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: view cursor movement, Word/Sentence functions
    
    E.g. Ctrl+Left/Right, Ctrl+Shift+Del/Backspace, double-click to select
    word...
    
    These are all implemented in SwCursor, so they need a layout passed to
    them from the SwViewShell.
    
    There was a bug in the while loop in SwCursor::GoSentence() case
    NEXT_SENT that triggered assert in the mapping code when the
    endOfSentence() returned the length of the SwTextNode but then it was
    incremented once more.
    
    Change-Id: Ic3866860a8c07774dce35952271c207eb6e7d182

diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index f975533ac6e9..8b736656dec9 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -250,8 +250,18 @@ private:
 
     SAL_DLLPRIVATE bool isInHiddenTextFrame(SwShellCursor* pShellCursor);
 
-typedef bool (SwCursor:: *FNCursor)();
+    SAL_DLLPRIVATE bool GoStartWordImpl();
+    SAL_DLLPRIVATE bool GoEndWordImpl();
+    SAL_DLLPRIVATE bool GoNextWordImpl();
+    SAL_DLLPRIVATE bool GoPrevWordImpl();
+    SAL_DLLPRIVATE bool GoNextSentenceImpl();
+    SAL_DLLPRIVATE bool GoEndSentenceImpl();
+    SAL_DLLPRIVATE bool GoStartSentenceImpl();
+
+    typedef bool (SwCursor::*FNCursor)();
+    typedef bool (SwCursorShell::*FNCursorShell)();
     SAL_DLLPRIVATE bool CallCursorFN( FNCursor );
+    SAL_DLLPRIVATE bool CallCursorShellFN( FNCursorShell );
 
     SAL_DLLPRIVATE const SwRangeRedline* GotoRedline_( SwRedlineTable::size_type nArrPos, bool bSelect );
 
diff --git a/sw/inc/swcrsr.hxx b/sw/inc/swcrsr.hxx
index 9ec86d6f5f77..6eccacf8f1e3 100644
--- a/sw/inc/swcrsr.hxx
+++ b/sw/inc/swcrsr.hxx
@@ -131,25 +131,18 @@ public:
                 const SfxItemSet* rReplSet = nullptr );
 
     // UI versions
-    bool IsStartWord( sal_Int16 nWordType ) const;
-    bool IsEndWord( sal_Int16 nWordType  ) const;
-    bool IsInWord( sal_Int16 nWordType ) const;
-    bool IsStartEndSentence( bool bEnd ) const;
-    bool GoStartWord();
-    bool GoEndWord();
-    bool GoNextWord();
-    bool GoPrevWord();
+    bool IsStartEndSentence(bool bEnd, SwRootFrame const* pLayout) const;
     bool SelectWord( SwViewShell const * pViewShell, const Point* pPt );
 
     // API versions of above functions (will be used with a different
     // WordType for the break iterator)
-    bool IsStartWordWT( sal_Int16 nWordType ) const;
-    bool IsEndWordWT( sal_Int16 nWordType ) const;
-    bool IsInWordWT( sal_Int16 nWordType ) const;
-    bool GoStartWordWT( sal_Int16 nWordType );
-    bool GoEndWordWT( sal_Int16 nWordType );
-    bool GoNextWordWT( sal_Int16 nWordType );
-    bool GoPrevWordWT( sal_Int16 nWordType );
+    bool IsStartWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr) const;
+    bool IsEndWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr) const;
+    bool IsInWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr) const;
+    bool GoStartWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr);
+    bool GoEndWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr);
+    bool GoNextWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr);
+    bool GoPrevWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr);
     bool SelectWordWT( SwViewShell const * pViewShell, sal_Int16 nWordType, const Point* pPt );
 
     enum SentenceMoveType
@@ -159,11 +152,8 @@ public:
         START_SENT,
         END_SENT
     };
-    bool GoSentence(SentenceMoveType eMoveType);
-    bool GoNextSentence(){return GoSentence(NEXT_SENT);}
-    bool GoEndSentence(){return GoSentence(END_SENT);}
-    bool GoStartSentence(){return GoSentence(START_SENT);}
-    bool ExpandToSentenceBorders();
+    bool GoSentence(SentenceMoveType eMoveType, SwRootFrame const*pLayout = nullptr);
+    bool ExpandToSentenceBorders(SwRootFrame const* pLayout);
 
     virtual bool LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
         bool bAllowVisual, bool bSkipHidden, bool bInsertCursor,
diff --git a/sw/source/core/crsr/crstrvl1.cxx b/sw/source/core/crsr/crstrvl1.cxx
index 8c69bb97b288..5654566769c8 100644
--- a/sw/source/core/crsr/crstrvl1.cxx
+++ b/sw/source/core/crsr/crstrvl1.cxx
@@ -20,59 +20,64 @@
 #include <crsrsh.hxx>
 #include <viscrs.hxx>
 
+#include <com/sun/star/i18n/WordType.hpp>
+
+using namespace ::com::sun::star::i18n;
+
 bool SwCursorShell::IsStartWord( sal_Int16 nWordType ) const
 {
-    return m_pCurrentCursor->IsStartWord( nWordType );
+    return m_pCurrentCursor->IsStartWordWT(nWordType, GetLayout());
 }
 bool SwCursorShell::IsEndWord( sal_Int16 nWordType ) const
 {
-    return m_pCurrentCursor->IsEndWord( nWordType );
+    return m_pCurrentCursor->IsEndWordWT(nWordType, GetLayout());
 }
 
 bool SwCursorShell::IsInWord( sal_Int16 nWordType ) const
 {
-    return m_pCurrentCursor->IsInWord( nWordType );
+    return m_pCurrentCursor->IsInWordWT(nWordType, GetLayout());
 }
 
 bool SwCursorShell::IsStartSentence() const
 {
-    return m_pCurrentCursor->IsStartEndSentence( false );
+    return m_pCurrentCursor->IsStartEndSentence(false, GetLayout());
 }
 bool SwCursorShell::IsEndSentence() const
 {
-    return m_pCurrentCursor->IsStartEndSentence( true );
+    return m_pCurrentCursor->IsStartEndSentence(true, GetLayout());
 }
 
 bool SwCursorShell::GoStartWord()
 {
-    return CallCursorFN( &SwCursor::GoStartWord );
+    return CallCursorShellFN( &SwCursorShell::GoStartWordImpl );
 }
 bool SwCursorShell::GoEndWord()
 {
-    return CallCursorFN( &SwCursor::GoEndWord );
+    return CallCursorShellFN( &SwCursorShell::GoEndWordImpl );
 }
 
 bool SwCursorShell::GoNextWord()
 {
-    return CallCursorFN( &SwCursor::GoNextWord );
+    return CallCursorShellFN( &SwCursorShell::GoNextWordImpl );
 }
 bool SwCursorShell::GoPrevWord()
 {
-    return CallCursorFN( &SwCursor::GoPrevWord );
+    return CallCursorShellFN( &SwCursorShell::GoPrevWordImpl );
 }
 
 bool SwCursorShell::GoNextSentence()
 {
-    return CallCursorFN( &SwCursor::GoNextSentence );
+    return CallCursorShellFN( &SwCursorShell::GoNextSentenceImpl );
 }
 
 bool SwCursorShell::GoEndSentence()
 {
-    return CallCursorFN( &SwCursor::GoEndSentence );
+    return CallCursorShellFN( &SwCursorShell::GoEndSentenceImpl );
 }
+
 bool SwCursorShell::GoStartSentence()
 {
-    return CallCursorFN( &SwCursor::GoStartSentence );
+    return CallCursorShellFN( &SwCursorShell::GoStartSentenceImpl );
 }
 
 bool SwCursorShell::SelectWord( const Point* pPt )
@@ -82,7 +87,40 @@ bool SwCursorShell::SelectWord( const Point* pPt )
 
 void SwCursorShell::ExpandToSentenceBorders()
 {
-    m_pCurrentCursor->ExpandToSentenceBorders();
+    m_pCurrentCursor->ExpandToSentenceBorders(GetLayout());
+}
+
+bool SwCursorShell::GoStartWordImpl()
+{
+    return getShellCursor(true)->GoStartWordWT(WordType::ANYWORD_IGNOREWHITESPACES, GetLayout());
+}
+
+bool SwCursorShell::GoEndWordImpl()
+{
+    return getShellCursor(true)->GoEndWordWT(WordType::ANYWORD_IGNOREWHITESPACES, GetLayout());
+}
+
+bool SwCursorShell::GoNextWordImpl()
+{
+    return getShellCursor(true)->GoNextWordWT(WordType::ANYWORD_IGNOREWHITESPACES, GetLayout());
+}
+
+bool SwCursorShell::GoPrevWordImpl()
+{
+    return getShellCursor(true)->GoPrevWordWT(WordType::ANYWORD_IGNOREWHITESPACES, GetLayout());
+}
+
+bool SwCursorShell::GoNextSentenceImpl()
+{
+    return getShellCursor(true)->GoSentence(SwCursor::NEXT_SENT, GetLayout());
+}
+bool SwCursorShell::GoEndSentenceImpl()
+{
+    return getShellCursor(true)->GoSentence(SwCursor::END_SENT, GetLayout());
+}
+bool SwCursorShell::GoStartSentenceImpl()
+{
+    return getShellCursor(true)->GoSentence(SwCursor::START_SENT, GetLayout());
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx
index 9f1679254c55..d90ce94d9590 100644
--- a/sw/source/core/crsr/swcrsr.cxx
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -1117,70 +1117,100 @@ short SwCursor::MaxReplaceArived()
     return RET_YES;
 }
 
-bool SwCursor::IsStartWord( sal_Int16 nWordType ) const
-{
-    return IsStartWordWT( nWordType );
-}
-
-bool SwCursor::IsEndWord( sal_Int16 nWordType ) const
-{
-    return IsEndWordWT( nWordType );
-}
-
-bool SwCursor::IsInWord( sal_Int16 nWordType ) const
-{
-    return IsInWordWT( nWordType );
-}
-
-bool SwCursor::GoStartWord()
-{
-    return GoStartWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
-}
-
-bool SwCursor::GoEndWord()
-{
-    return GoEndWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
-}
-
-bool SwCursor::GoNextWord()
-{
-    return GoNextWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
-}
+namespace {
+
+struct HideWrapper
+{
+    // either the frame's text or the node's text (possibly pre-filtered)
+    OUString const* m_pText;
+    // this is actually a TextFrameIndex but all of the i18n code uses sal_Int32
+    sal_Int32 m_nPtIndex;
+    // if mapping is needed, use this frame
+    SwTextFrame * m_pFrame;
+    // input in the constructor, output (via mapping) in the destructor
+    SwTextNode *& m_rpTextNode;
+    sal_Int32 & m_rPtPos;
+
+    HideWrapper(SwRootFrame const*const pLayout,
+            SwTextNode *& rpTextNode, sal_Int32 & rPtPos,
+            OUString const*const pFilteredNodeText = nullptr)
+        : m_pText(pFilteredNodeText)
+        , m_pFrame(nullptr)
+        , m_rpTextNode(rpTextNode)
+        , m_rPtPos(rPtPos)
+    {
+        if (pLayout && pLayout->IsHideRedlines())
+        {
+            m_pFrame = static_cast<SwTextFrame*>(rpTextNode->getLayoutFrame(pLayout));
+            m_pText = &m_pFrame->GetText();
+            m_nPtIndex = sal_Int32(m_pFrame->MapModelToView(rpTextNode, rPtPos));
+        }
+        else
+        {
+            if (!m_pText)
+            {
+                m_pText = &rpTextNode->GetText();
+            }
+            m_nPtIndex = rPtPos;
+        }
+    }
+    ~HideWrapper()
+    {
+        AssignBack(m_rpTextNode, m_rPtPos);
+    }
+    void AssignBack(SwTextNode *& rpTextNode, sal_Int32 & rPtPos)
+    {
+        if (0 <= m_nPtIndex && m_pFrame)
+        {
+            std::pair<SwTextNode*, sal_Int32> const pos(
+                    m_pFrame->MapViewToModel(TextFrameIndex(m_nPtIndex)));
+            rpTextNode = pos.first;
+            rPtPos = pos.second;
+        }
+        else
+        {
+            rPtPos = m_nPtIndex;
+        }
+    }
+};
 
-bool SwCursor::GoPrevWord()
-{
-    return GoPrevWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
-}
+} // namespace
 
 bool SwCursor::SelectWord( SwViewShell const * pViewShell, const Point* pPt )
 {
     return SelectWordWT( pViewShell, WordType::ANYWORD_IGNOREWHITESPACES, pPt );
 }
 
-bool SwCursor::IsStartWordWT( sal_Int16 nWordType ) const
+bool SwCursor::IsStartWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) const
 {
     bool bRet = false;
-    const SwTextNode* pTextNd = GetNode().GetTextNode();
+    SwTextNode* pTextNd = GetNode().GetTextNode();
     if (pTextNd)
     {
-        const sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
+        sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
+
+        HideWrapper w(pLayout, pTextNd, nPtPos);
+
         bRet = g_pBreakIt->GetBreakIter()->isBeginWord(
-                            pTextNd->GetText(), nPtPos,
+                            *w.m_pText, w.m_nPtIndex,
                             g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos )),
                             nWordType );
     }
     return bRet;
 }
 
-bool SwCursor::IsEndWordWT( sal_Int16 nWordType ) const
+bool SwCursor::IsEndWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) const
 {
     bool bRet = false;
-    const SwTextNode* pTextNd = GetNode().GetTextNode();
+    SwTextNode* pTextNd = GetNode().GetTextNode();
     if (pTextNd)
     {
-        const sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
+        sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
+
+        HideWrapper w(pLayout, pTextNd, nPtPos);
+
         bRet = g_pBreakIt->GetBreakIter()->isEndWord(
-                            pTextNd->GetText(), nPtPos,
+                            *w.m_pText, w.m_nPtIndex,
                             g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
                             nWordType );
 
@@ -1188,64 +1218,75 @@ bool SwCursor::IsEndWordWT( sal_Int16 nWordType ) const
     return bRet;
 }
 
-bool SwCursor::IsInWordWT( sal_Int16 nWordType ) const
+bool SwCursor::IsInWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout) const
 {
     bool bRet = false;
-    const SwTextNode* pTextNd = GetNode().GetTextNode();
+    SwTextNode* pTextNd = GetNode().GetTextNode();
     if (pTextNd)
     {
-        const sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
-        Boundary aBoundary = g_pBreakIt->GetBreakIter()->getWordBoundary(
-                            pTextNd->GetText(), nPtPos,
-                            g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
-                            nWordType,
-                            true );
+        sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
 
-        bRet = aBoundary.startPos != aBoundary.endPos &&
-                aBoundary.startPos <= nPtPos &&
-                    nPtPos <= aBoundary.endPos;
+        {
+            HideWrapper w(pLayout, pTextNd, nPtPos);
+
+            Boundary aBoundary = g_pBreakIt->GetBreakIter()->getWordBoundary(
+                                *w.m_pText, w.m_nPtIndex,
+                                g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
+                                nWordType,
+                                true );
+
+            bRet = aBoundary.startPos != aBoundary.endPos &&
+                    aBoundary.startPos <= w.m_nPtIndex &&
+                        w.m_nPtIndex <= aBoundary.endPos;
+            w.m_nPtIndex = aBoundary.startPos; // hack: convert startPos back...
+        }
         if(bRet)
         {
             const CharClass& rCC = GetAppCharClass();
-            bRet = rCC.isLetterNumeric( pTextNd->GetText(), aBoundary.startPos );
+            bRet = rCC.isLetterNumeric(pTextNd->GetText(), nPtPos);
         }
     }
     return bRet;
 }
 
-bool SwCursor::IsStartEndSentence( bool bEnd ) const
+bool SwCursor::IsStartEndSentence(bool bEnd, SwRootFrame const*const pLayout) const
 {
     bool bRet = bEnd ?
                     GetContentNode() && GetPoint()->nContent == GetContentNode()->Len() :
                     GetPoint()->nContent.GetIndex() == 0;
 
-    if( !bRet )
+    if ((pLayout != nullptr && pLayout->IsHideRedlines()) || !bRet)
     {
         SwCursor aCursor(*GetPoint(), nullptr);
         SwPosition aOrigPos = *aCursor.GetPoint();
-        aCursor.GoSentence( bEnd ? SwCursor::END_SENT : SwCursor::START_SENT );
+        aCursor.GoSentence(bEnd ? SwCursor::END_SENT : SwCursor::START_SENT, pLayout);
         bRet = aOrigPos == *aCursor.GetPoint();
     }
     return bRet;
 }
 
-bool SwCursor::GoStartWordWT( sal_Int16 nWordType )
+bool SwCursor::GoStartWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout)
 {
     bool bRet = false;
-    const SwTextNode* pTextNd = GetNode().GetTextNode();
+    SwTextNode* pTextNd = GetNode().GetTextNode();
     if (pTextNd)
     {
         SwCursorSaveState aSave( *this );
         sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
-        nPtPos = g_pBreakIt->GetBreakIter()->getWordBoundary(
-                            pTextNd->GetText(), nPtPos,
+
+        {
+            HideWrapper w(pLayout, pTextNd, nPtPos);
+
+            w.m_nPtIndex = g_pBreakIt->GetBreakIter()->getWordBoundary(
+                            *w.m_pText, w.m_nPtIndex,
                             g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
                             nWordType,
                             false ).startPos;
+        }
 
         if (nPtPos < pTextNd->GetText().getLength() && nPtPos >= 0)
         {
-            GetPoint()->nContent = nPtPos;
+            *GetPoint() = SwPosition(*pTextNd, nPtPos);
             if( !IsSelOvr() )
                 bRet = true;
         }
@@ -1253,24 +1294,29 @@ bool SwCursor::GoStartWordWT( sal_Int16 nWordType )
     return bRet;
 }
 
-bool SwCursor::GoEndWordWT( sal_Int16 nWordType )
+bool SwCursor::GoEndWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout)
 {
     bool bRet = false;
-    const SwTextNode* pTextNd = GetNode().GetTextNode();
+    SwTextNode* pTextNd = GetNode().GetTextNode();
     if (pTextNd)
     {
         SwCursorSaveState aSave( *this );
         sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
-        nPtPos = g_pBreakIt->GetBreakIter()->getWordBoundary(
-                            pTextNd->GetText(), nPtPos,
+
+        {
+            HideWrapper w(pLayout, pTextNd, nPtPos);
+
+            w.m_nPtIndex = g_pBreakIt->GetBreakIter()->getWordBoundary(
+                            *w.m_pText, w.m_nPtIndex,
                             g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
                             nWordType,
                             true ).endPos;
+        }
 
         if (nPtPos <= pTextNd->GetText().getLength() && nPtPos >= 0 &&
             GetPoint()->nContent.GetIndex() != nPtPos )
         {
-            GetPoint()->nContent = nPtPos;
+            *GetPoint() = SwPosition(*pTextNd, nPtPos);
             if( !IsSelOvr() )
                 bRet = true;
         }
@@ -1278,23 +1324,27 @@ bool SwCursor::GoEndWordWT( sal_Int16 nWordType )
     return bRet;
 }
 
-bool SwCursor::GoNextWordWT( sal_Int16 nWordType )
+bool SwCursor::GoNextWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout)
 {
     bool bRet = false;
-    const SwTextNode* pTextNd = GetNode().GetTextNode();
+    SwTextNode* pTextNd = GetNode().GetTextNode();
     if (pTextNd)
     {
         SwCursorSaveState aSave( *this );
         sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
 
-        nPtPos = g_pBreakIt->GetBreakIter()->nextWord(
-                                pTextNd->GetText(), nPtPos,
-            g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos, 1 ) ),
-                    nWordType ).startPos;
+        {
+            HideWrapper w(pLayout, pTextNd, nPtPos);
+
+            w.m_nPtIndex = g_pBreakIt->GetBreakIter()->nextWord(
+                        *w.m_pText, w.m_nPtIndex,
+                        g_pBreakIt->GetLocale( pTextNd->GetLang(nPtPos, 1) ),
+                        nWordType ).startPos;
+        }
 
         if (nPtPos <= pTextNd->GetText().getLength() && nPtPos >= 0)
         {
-            GetPoint()->nContent = nPtPos;
+            *GetPoint() = SwPosition(*pTextNd, nPtPos);
             if( !IsSelOvr() )
                 bRet = true;
         }
@@ -1302,26 +1352,34 @@ bool SwCursor::GoNextWordWT( sal_Int16 nWordType )
     return bRet;
 }
 
-bool SwCursor::GoPrevWordWT( sal_Int16 nWordType )
+bool SwCursor::GoPrevWordWT(sal_Int16 nWordType, SwRootFrame const*const pLayout)
 {
     bool bRet = false;
-    const SwTextNode* pTextNd = GetNode().GetTextNode();
+    SwTextNode* pTextNd = GetNode().GetTextNode();
     if (pTextNd)
     {
         SwCursorSaveState aSave( *this );
         sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
-        const sal_Int32 nPtStart = nPtPos;
 
-        if( nPtPos )
-            --nPtPos;
-        nPtPos = g_pBreakIt->GetBreakIter()->previousWord(
-                                pTextNd->GetText(), nPtStart,
-            g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos, 1 ) ),
-                    nWordType ).startPos;
+        {
+            HideWrapper w(pLayout, pTextNd, nPtPos);
+
+            const sal_Int32 nPtStart = w.m_nPtIndex;
+            if (w.m_nPtIndex)
+            {
+                --w.m_nPtIndex;
+                w.AssignBack(pTextNd, nPtPos);
+            }
+
+            w.m_nPtIndex = g_pBreakIt->GetBreakIter()->previousWord(
+                        *w.m_pText, nPtStart,
+                        g_pBreakIt->GetLocale( pTextNd->GetLang(nPtPos, 1) ),
+                                nWordType ).startPos;
+        }
 
         if (nPtPos < pTextNd->GetText().getLength() && nPtPos >= 0)
         {
-            GetPoint()->nContent = nPtPos;
+            *GetPoint() = SwPosition(*pTextNd, nPtPos);
             if( !IsSelOvr() )
                 bRet = true;
         }
@@ -1343,7 +1401,7 @@ bool SwCursor::SelectWordWT( SwViewShell const * pViewShell, sal_Int16 nWordType
         pLayout->GetCursorOfst( GetPoint(), aPt );
     }
 
-    const SwTextNode* pTextNd = GetNode().GetTextNode();
+    SwTextNode* pTextNd = GetNode().GetTextNode();
     if (pTextNd)
     {
         // Should we select the whole fieldmark?
@@ -1371,30 +1429,46 @@ bool SwCursor::SelectWordWT( SwViewShell const * pViewShell, sal_Int16 nWordType
         {
             bool bForward = true;
             sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
+
+            HideWrapper w(pViewShell->GetLayout(), pTextNd, nPtPos);
+
             Boundary aBndry( g_pBreakIt->GetBreakIter()->getWordBoundary(
-                                pTextNd->GetText(), nPtPos,
+                                *w.m_pText, w.m_nPtIndex,
                                 g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
                                 nWordType,
                                 bForward ));
 
-            if (comphelper::LibreOfficeKit::isActive() && aBndry.startPos == aBndry.endPos && nPtPos > 0)
+            if (comphelper::LibreOfficeKit::isActive() && aBndry.startPos == aBndry.endPos && w.m_nPtIndex > 0)
             {
                 // nPtPos is the end of the paragraph, select the last word then.
-                --nPtPos;
+                --w.m_nPtIndex;
+                w.AssignBack(pTextNd, nPtPos);
+
                 aBndry = Boundary( g_pBreakIt->GetBreakIter()->getWordBoundary(
-                                    pTextNd->GetText(), nPtPos,
+                                    *w.m_pText, w.m_nPtIndex,
                                     g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
                                     nWordType,
                                     bForward ));
+
             }
 
+            SwTextNode * pStartNode(pTextNd);
+            sal_Int32 nStartIndex;
+            w.m_nPtIndex = aBndry.startPos;
+            w.AssignBack(pStartNode, nStartIndex);
+
+            SwTextNode * pEndNode(pTextNd);
+            sal_Int32 nEndIndex;
+            w.m_nPtIndex = aBndry.endPos;
+            w.AssignBack(pEndNode, nEndIndex);
+
             if( aBndry.startPos != aBndry.endPos )
             {
-                GetPoint()->nContent = aBndry.endPos;
+                *GetPoint() = SwPosition(*pEndNode, nEndIndex);
                 if( !IsSelOvr() )
                 {
                     SetMark();
-                    GetMark()->nContent = aBndry.startPos;
+                    *GetMark() = SwPosition(*pStartNode, nStartIndex);
                     if (sw::mark::IMark* pAnnotationMark = pMarksAccess->getAnnotationMarkFor(*GetPoint()))
                     {
                         // An annotation mark covers the selected word. Check
@@ -1455,61 +1529,70 @@ static OUString lcl_MaskDeletedRedlines( const SwTextNode* pTextNd )
     return aRes;
 }
 
-bool SwCursor::GoSentence( SentenceMoveType eMoveType )
+bool SwCursor::GoSentence(SentenceMoveType eMoveType, SwRootFrame const*const pLayout)
 {
     bool bRet = false;
-    const SwTextNode* pTextNd = GetNode().GetTextNode();
+    SwTextNode* pTextNd = GetNode().GetTextNode();
     if (pTextNd)
     {
-        OUString sNodeText( lcl_MaskDeletedRedlines( pTextNd ) );
+        OUString const sNodeText(lcl_MaskDeletedRedlines(pTextNd));
 
         SwCursorSaveState aSave( *this );
         sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
-        switch ( eMoveType )
+
         {
-        case START_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
-            nPtPos = g_pBreakIt->GetBreakIter()->beginOfSentence(
-                                    sNodeText,
-                                    nPtPos, g_pBreakIt->GetLocale(
-                                            pTextNd->GetLang( nPtPos ) ));
-            break;
-        case END_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
-            nPtPos = g_pBreakIt->GetBreakIter()->endOfSentence(
-                                    sNodeText,
-                                    nPtPos, g_pBreakIt->GetLocale(
-                                                pTextNd->GetLang( nPtPos ) ));
-            break;
-        case NEXT_SENT:
+            HideWrapper w(pLayout, pTextNd, nPtPos, &sNodeText);
+
+            switch ( eMoveType )
             {
-                nPtPos = g_pBreakIt->GetBreakIter()->endOfSentence(
-                                        sNodeText,
-                                        nPtPos, g_pBreakIt->GetLocale(
-                                                    pTextNd->GetLang( nPtPos ) ));
-                while (nPtPos>=0 && ++nPtPos < sNodeText.getLength()
-                       && sNodeText[nPtPos] == ' ' /*isWhiteSpace( aText.GetChar(nPtPos)*/ )
-                    ;
+            case START_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
+                w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence(
+                            *w.m_pText, w.m_nPtIndex,
+                            g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos)));
+                break;
+            case END_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
+                w.m_nPtIndex = g_pBreakIt->GetBreakIter()->endOfSentence(
+                            *w.m_pText, w.m_nPtIndex,
+                            g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos)));
+                break;
+            case NEXT_SENT:
+                {
+                    w.m_nPtIndex = g_pBreakIt->GetBreakIter()->endOfSentence(
+                            *w.m_pText, w.m_nPtIndex,
+                            g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos)));
+                    if (w.m_nPtIndex >= 0 && w.m_nPtIndex < w.m_pText->getLength())
+                    {
+                        do
+                        {
+                            ++w.m_nPtIndex;
+                        }
+                        while (w.m_nPtIndex < w.m_pText->getLength()
+                               && (*w.m_pText)[w.m_nPtIndex] == ' ');
+                    }
+                    break;
+                }
+            case PREV_SENT:
+                w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence(
+                            *w.m_pText, w.m_nPtIndex,
+                            g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos)));
+
+                if (w.m_nPtIndex == 0)
+                    return false;   // the previous sentence is not in this paragraph
+                if (w.m_nPtIndex > 0)
+                {
+                    w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence(
+                            *w.m_pText, w.m_nPtIndex - 1,
+                            g_pBreakIt->GetLocale(pTextNd->GetLang(nPtPos)));
+                }
                 break;
             }
-        case PREV_SENT:
-            nPtPos = g_pBreakIt->GetBreakIter()->beginOfSentence(
-                                    sNodeText,
-                                    nPtPos, g_pBreakIt->GetLocale(
-                                                pTextNd->GetLang( nPtPos ) ));
-            if (nPtPos == 0)
-                return false;   // the previous sentence is not in this paragraph
-            if (nPtPos > 0)
-                nPtPos = g_pBreakIt->GetBreakIter()->beginOfSentence(
-                                    sNodeText,
-                                    nPtPos - 1, g_pBreakIt->GetLocale(
-                                                pTextNd->GetLang( nPtPos ) ));
-            break;
         }
 
         // it is allowed to place the PaM just behind the last
         // character in the text thus <= ...Len
         if (nPtPos <= pTextNd->GetText().getLength() && nPtPos >= 0)
         {
-            GetPoint()->nContent = nPtPos;
+            *GetPoint() = SwPosition(*pTextNd, nPtPos);
             if( !IsSelOvr() )
                 bRet = true;
         }
@@ -1517,11 +1600,11 @@ bool SwCursor::GoSentence( SentenceMoveType eMoveType )
     return bRet;
 }
 
-bool SwCursor::ExpandToSentenceBorders()
+bool SwCursor::ExpandToSentenceBorders(SwRootFrame const*const pLayout)
 {
     bool bRes = false;
-    const SwTextNode* pStartNd = Start()->nNode.GetNode().GetTextNode();
-    const SwTextNode* pEndNd   = End()->nNode.GetNode().GetTextNode();
+    SwTextNode* pStartNd = Start()->nNode.GetNode().GetTextNode();
+    SwTextNode* pEndNd   = End()->nNode.GetNode().GetTextNode();
     if (pStartNd && pEndNd)
     {
         if (!HasMark())
@@ -1534,24 +1617,32 @@ bool SwCursor::ExpandToSentenceBorders()
         sal_Int32 nStartPos = Start()->nContent.GetIndex();
         sal_Int32 nEndPos   = End()->nContent.GetIndex();
 
-        nStartPos = g_pBreakIt->GetBreakIter()->beginOfSentence(
-                                sStartText, nStartPos,
+        {
+            HideWrapper w(pLayout, pStartNd, nStartPos, &sStartText);
+
+            w.m_nPtIndex = g_pBreakIt->GetBreakIter()->beginOfSentence(
+                                *w.m_pText, w.m_nPtIndex,
                                 g_pBreakIt->GetLocale( pStartNd->GetLang( nStartPos ) ) );
-        nEndPos   = g_pBreakIt->GetBreakIter()->endOfSentence(
-                                sEndText, nEndPos,
+        }
+        {
+            HideWrapper w(pLayout, pEndNd, nEndPos, &sEndText);
+
+            w.m_nPtIndex = g_pBreakIt->GetBreakIter()->endOfSentence(
+                                *w.m_pText, w.m_nPtIndex,
                                 g_pBreakIt->GetLocale( pEndNd->GetLang( nEndPos ) ) );
+        }
 
         // it is allowed to place the PaM just behind the last
         // character in the text thus <= ...Len
         bool bChanged = false;
         if (nStartPos <= pStartNd->GetText().getLength() && nStartPos >= 0)
         {
-            GetMark()->nContent = nStartPos;
+            *GetMark() = SwPosition(*pStartNd, nStartPos);
             bChanged = true;
         }
         if (nEndPos <= pEndNd->GetText().getLength() && nEndPos >= 0)
         {
-            GetPoint()->nContent = nEndPos;
+            *GetPoint() = SwPosition(*pEndNd, nEndPos);
             bChanged = true;
         }
         if (bChanged && !IsSelOvr())
diff --git a/sw/source/core/crsr/trvlfnfl.cxx b/sw/source/core/crsr/trvlfnfl.cxx
index c0fa6a288320..e327e73e3ab3 100644
--- a/sw/source/core/crsr/trvlfnfl.cxx
+++ b/sw/source/core/crsr/trvlfnfl.cxx
@@ -36,6 +36,16 @@
 #include "callnk.hxx"
 #include <svx/srchdlg.hxx>
 
+bool SwCursorShell::CallCursorShellFN( FNCursorShell fnCursor )
+{
+    SwCallLink aLk( *this ); // watch Cursor-Moves
+    bool bRet = (this->*fnCursor)();
+    if( bRet )
+        UpdateCursor( SwCursorShell::SCROLLWIN | SwCursorShell::CHKRANGE |
+                    SwCursorShell::READONLY );
+    return bRet;
+}
+
 bool SwCursorShell::CallCursorFN( FNCursor fnCursor )
 {
     SwCallLink aLk( *this ); // watch Cursor-Moves
diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx
index c1c91b365bf0..680a336bb9d9 100644
--- a/sw/source/core/unocore/unoobj.cxx
+++ b/sw/source/core/unocore/unoobj.cxx
@@ -1434,9 +1434,9 @@ SwXTextCursor::gotoNextSentence(sal_Bool Expand)
     // if at the end of the sentence (i.e. at the space after the '.')
     // advance to next word in order for GoSentence to work properly
     // next time and have isStartOfSentence return true after this call
-    if (!rUnoCursor.IsStartWord(css::i18n::WordType::ANYWORD_IGNOREWHITESPACES))
+    if (!rUnoCursor.IsStartWordWT(css::i18n::WordType::ANYWORD_IGNOREWHITESPACES))
     {
-        const bool bNextWord = rUnoCursor.GoNextWord();
+        const bool bNextWord = rUnoCursor.GoNextWordWT(i18n::WordType::ANYWORD_IGNOREWHITESPACES);
         if (bWasEOS && !bNextWord)
         {
             bRet = false;
commit 8e550d9db349f303ef4108bf94d1f8d570b70506
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Sep 12 11:28:06 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: adapt SwCursor::UpDown()
    
    Actually it already works, this is just a clean up to pass in the
    SwCursorShell's layout...
    
    Change-Id: I1a90bbe9966c7f4d5b5e959122ca1f995df93a45

diff --git a/sw/inc/swcrsr.hxx b/sw/inc/swcrsr.hxx
index 41aba80df7e5..9ec86d6f5f77 100644
--- a/sw/inc/swcrsr.hxx
+++ b/sw/inc/swcrsr.hxx
@@ -168,7 +168,7 @@ public:
     virtual bool LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
         bool bAllowVisual, bool bSkipHidden, bool bInsertCursor,
         SwRootFrame const* pLayout);
-    bool UpDown( bool bUp, sal_uInt16 nCnt, Point const * pPt, long nUpDownX );
+    bool UpDown(bool bUp, sal_uInt16 nCnt, Point const * pPt, long nUpDownX, SwRootFrame & rLayout);
     bool LeftRightMargin( bool bLeftMargin, bool bAPI );
     bool IsAtLeftRightMargin( bool bLeftMargin, bool bAPI ) const;
     bool SttEndDoc( bool bSttDoc );
diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx
index a5ab87c2293f..9f1679254c55 100644
--- a/sw/source/core/crsr/swcrsr.cxx
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -1827,7 +1827,8 @@ void SwCursor::DoSetBidiLevelUpDown()
 }
 
 bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt,
-                       Point const * pPt, long nUpDownX )
+                       Point const * pPt, long nUpDownX,
+                       SwRootFrame & rLayout)
 {
     SwTableCursor* pTableCursor = dynamic_cast<SwTableCursor*>(this);
     bool bAdjustTableCursor = false;
@@ -1846,7 +1847,7 @@ bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt,
     Point aPt;
     if( pPt )
         aPt = *pPt;
-    SwContentFrame* pFrame = GetContentNode()->getLayoutFrame( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, GetPoint() );
+    SwContentFrame* pFrame = GetContentNode()->getLayoutFrame(&rLayout, &aPt, GetPoint());
 
     if( pFrame )
     {
@@ -1882,7 +1883,7 @@ bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt,
                 const SwNode* pEndNd = pTableNd->EndOfSectionNode();
                 GetPoint()->nNode = *pEndNd;
                 pTableCursor->Move( fnMoveBackward, GoInNode );
-                   pFrame = GetContentNode()->getLayoutFrame( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, GetPoint() );
+               pFrame = GetContentNode()->getLayoutFrame(&rLayout, &aPt, GetPoint());
             }
         }
 
@@ -1891,7 +1892,7 @@ bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt,
                     : pFrame->UnitDown( this, nUpDownX, bInReadOnly ) ) &&
                 CheckNodesRange( aOldPos.nNode, GetPoint()->nNode, bChkRange ))
         {
-               pFrame = GetContentNode()->getLayoutFrame( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, GetPoint() );
+               pFrame = GetContentNode()->getLayoutFrame(&rLayout, &aPt, GetPoint());
             --nCnt;
         }
 
@@ -1902,8 +1903,8 @@ bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt,
             if( !pTableCursor )
             {
                 // try to position the cursor at half of the char-rect's height
-                DisableCallbackAction a(*GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout());
-                pFrame = GetContentNode()->getLayoutFrame( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, GetPoint() );
+                DisableCallbackAction a(rLayout);
+                pFrame = GetContentNode()->getLayoutFrame(&rLayout, &aPt, GetPoint());
                 SwCursorMoveState eTmpState( MV_UPDOWN );
                 eTmpState.m_bSetInReadOnly = bInReadOnly;
                 SwRect aTmpRect;
@@ -1911,13 +1912,13 @@ bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt,
                 if ( pFrame->IsVertical() )
                 {
                     aPt.setX(aTmpRect.Center().getX());
-                    pFrame->Calc(pFrame->getRootFrame()->GetCurrShell()->GetOut());
+                    pFrame->Calc(rLayout.GetCurrShell()->GetOut());
                     aPt.setY(pFrame->getFrameArea().Top() + nUpDownX);
                 }
                 else
                 {
                     aPt.setY(aTmpRect.Center().getY());
-                    pFrame->Calc(pFrame->getRootFrame()->GetCurrShell()->GetOut());
+                    pFrame->Calc(rLayout.GetCurrShell()->GetOut());
                     aPt.setX(pFrame->getFrameArea().Left() + nUpDownX);
                 }
                 pFrame->GetCursorOfst( GetPoint(), aPt, &eTmpState );
diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx
index 6e588b0dfd14..a27189ac1520 100644
--- a/sw/source/core/crsr/viscrs.cxx
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -700,7 +700,8 @@ void SwShellCursor::SaveTableBoxContent( const SwPosition* pPos )
 bool SwShellCursor::UpDown( bool bUp, sal_uInt16 nCnt )
 {
     return SwCursor::UpDown( bUp, nCnt,
-                            &GetPtPos(), GetShell()->GetUpDownX() );
+                            &GetPtPos(), GetShell()->GetUpDownX(),
+                            *GetShell()->GetLayout());
 }
 
 // if <true> than the cursor can be set to the position.
diff --git a/sw/source/core/edit/eddel.cxx b/sw/source/core/edit/eddel.cxx
index 658a650c8048..126b5000a923 100644
--- a/sw/source/core/edit/eddel.cxx
+++ b/sw/source/core/edit/eddel.cxx
@@ -185,7 +185,7 @@ bool SwEditShell::Copy( SwEditShell* pDestShell )
                 if( nMove )
                 {
                     SwCursor aCursor( *pPos, nullptr);
-                    if( aCursor.UpDown( false, nMove, nullptr, 0 ) )
+                    if (aCursor.UpDown(false, nMove, nullptr, 0, *GetLayout()))
                     {
                         pInsertPos.reset( new SwPosition( *aCursor.GetPoint() ) );
                         aInsertList.push_back( pInsertPos );
diff --git a/sw/source/core/frmedt/fecopy.cxx b/sw/source/core/frmedt/fecopy.cxx
index b30bd26fffa6..d0f69864d9e0 100644
--- a/sw/source/core/frmedt/fecopy.cxx
+++ b/sw/source/core/frmedt/fecopy.cxx
@@ -761,7 +761,7 @@ bool SwFEShell::Paste( SwDoc* pClpDoc )
                     SwCursor aCursor( aStartPos, nullptr);
                     // Check if we find another insert position by moving
                     // down the last given position
-                    if( aCursor.UpDown( false, ++nMove, nullptr, 0 ) )
+                    if (aCursor.UpDown(false, ++nMove, nullptr, 0, *GetLayout()))
                         aInsertPos = *aCursor.GetPoint();
                     else // if there is no paragraph we have to create it
                         bCompletePara = nCount > 0;
diff --git a/sw/source/core/unocore/unotbl.cxx b/sw/source/core/unocore/unotbl.cxx
index 7f832ac8e0d4..e58b04a3a112 100644
--- a/sw/source/core/unocore/unotbl.cxx
+++ b/sw/source/core/unocore/unotbl.cxx
@@ -42,6 +42,7 @@
 #include <IDocumentContentOperations.hxx>
 #include <IDocumentFieldsAccess.hxx>
 #include <IDocumentState.hxx>
+#include <IDocumentLayoutAccess.hxx>
 #include <shellres.hxx>
 #include <docary.hxx>
 #include <ndole.hxx>
@@ -1602,7 +1603,8 @@ sal_Bool SwXTextTableCursor::goUp(sal_Int16 Count, sal_Bool bExpand)
     SwUnoCursor& rUnoCursor = GetCursor();
     SwUnoTableCursor& rTableCursor = dynamic_cast<SwUnoTableCursor&>(rUnoCursor);
     lcl_CursorSelect(rTableCursor, bExpand);
-    return rTableCursor.UpDown(true, Count, nullptr, 0);
+    return rTableCursor.UpDown(true, Count, nullptr, 0,
+        *rUnoCursor.GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout());
 }
 
 sal_Bool SwXTextTableCursor::goDown(sal_Int16 Count, sal_Bool bExpand)
@@ -1611,7 +1613,8 @@ sal_Bool SwXTextTableCursor::goDown(sal_Int16 Count, sal_Bool bExpand)
     SwUnoCursor& rUnoCursor = GetCursor();
     SwUnoTableCursor& rTableCursor = dynamic_cast<SwUnoTableCursor&>(rUnoCursor);
     lcl_CursorSelect(rTableCursor, bExpand);
-    return rTableCursor.UpDown(false, Count, nullptr, 0);
+    return rTableCursor.UpDown(false, Count, nullptr, 0,
+        *rUnoCursor.GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout());
 }
 
 void SwXTextTableCursor::gotoStart(sal_Bool bExpand)
commit 9151eaf2603b73bcb74f208b40eef4b1bf5c90bc
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Sep 12 10:44:38 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: view cursor movement, SwCursorShell::LeftRight()
    
    Just put a loop in SwCursor::LeftRight() to repeat a movement if
    it didn't actually advance the text frame index; the
    SwContentNode::GoPrevious()/GoNext() take into account hidden text
    attributes from SwScriptInfo, so this ought to result in end
    positions that are neither hidden by attributes nor by redlines.
    
    This requires passing the layout to SwCursor.
    
    Change-Id: Ieb623840f6390fa6f1c78b7458ad8dc6523a2744

diff --git a/sw/inc/swcrsr.hxx b/sw/inc/swcrsr.hxx
index ca6b18b325e9..41aba80df7e5 100644
--- a/sw/inc/swcrsr.hxx
+++ b/sw/inc/swcrsr.hxx
@@ -166,15 +166,16 @@ public:
     bool ExpandToSentenceBorders();
 
     virtual bool LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
-        bool bAllowVisual, bool bSkipHidden, bool bInsertCursor );
+        bool bAllowVisual, bool bSkipHidden, bool bInsertCursor,
+        SwRootFrame const* pLayout);
     bool UpDown( bool bUp, sal_uInt16 nCnt, Point const * pPt, long nUpDownX );
     bool LeftRightMargin( bool bLeftMargin, bool bAPI );
     bool IsAtLeftRightMargin( bool bLeftMargin, bool bAPI ) const;
     bool SttEndDoc( bool bSttDoc );
     bool GoPrevNextCell( bool bNext, sal_uInt16 nCnt );
 
-    bool Left( sal_uInt16 nCnt )   { return LeftRight( true, nCnt, CRSR_SKIP_CHARS, false/*bAllowVisual*/, false/*bSkipHidden*/, false ); }
-    bool Right( sal_uInt16 nCnt )  { return LeftRight( false, nCnt, CRSR_SKIP_CHARS, false/*bAllowVisual*/, false/*bSkipHidden*/, false ); }
+    bool Left( sal_uInt16 nCnt )   { return LeftRight( true, nCnt, CRSR_SKIP_CHARS, false/*bAllowVisual*/, false/*bSkipHidden*/, false, nullptr ); }
+    bool Right( sal_uInt16 nCnt )  { return LeftRight( false, nCnt, CRSR_SKIP_CHARS, false/*bAllowVisual*/, false/*bSkipHidden*/, false, nullptr ); }
     bool GoNextCell( sal_uInt16 nCnt = 1 )  { return GoPrevNextCell( true, nCnt ); }
     bool GoPrevCell( sal_uInt16 nCnt = 1 )  { return GoPrevNextCell( false, nCnt ); }
     virtual bool GotoTable( const OUString& rName );
@@ -274,7 +275,8 @@ public:
     virtual ~SwTableCursor() override;
 
     virtual bool LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
-        bool bAllowVisual, bool bSkipHidden, bool bInsertCursor ) override;
+        bool bAllowVisual, bool bSkipHidden, bool bInsertCursor,
+        SwRootFrame const*) override;
     virtual bool GotoTable( const OUString& rName ) override;
 
     void InsertBox( const SwTableBox& rTableBox );
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 2afbfdadbd08..f29462b9b268 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -357,7 +357,8 @@ bool SwCursorShell::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
         // reflected in the return value <bRet>.
         const bool bResetOfInFrontOfLabel = SetInFrontOfLabel( false );
         bRet = pShellCursor->LeftRight( bLeft, nCnt, nMode, bVisualAllowed,
-                                      bSkipHidden, !IsOverwriteCursor() );
+                                      bSkipHidden, !IsOverwriteCursor(),
+                                      GetLayout());
         if ( !bRet && bLeft && bResetOfInFrontOfLabel )
         {
             // undo reset of <bInFrontOfLabel> flag
diff --git a/sw/source/core/crsr/swcrsr.cxx b/sw/source/core/crsr/swcrsr.cxx
index 2b934cb6c576..a5ab87c2293f 100644
--- a/sw/source/core/crsr/swcrsr.cxx
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -1561,7 +1561,8 @@ bool SwCursor::ExpandToSentenceBorders()
 }
 
 bool SwTableCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 /*nMode*/,
-    bool /*bVisualAllowed*/, bool /*bSkipHidden*/, bool /*bInsertCursor*/ )
+    bool /*bVisualAllowed*/, bool /*bSkipHidden*/, bool /*bInsertCursor*/,
+    SwRootFrame const*)
 {
     return bLeft ? GoPrevCell( nCnt )
                  : GoNextCell( nCnt );
@@ -1623,7 +1624,8 @@ SwCursor::DoSetBidiLevelLeftRight(
 }
 
 bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
-                          bool bVisualAllowed,bool bSkipHidden, bool bInsertCursor )
+                          bool bVisualAllowed,bool bSkipHidden, bool bInsertCursor,
+                          SwRootFrame const*const pLayout)
 {
     // calculate cursor bidi level
     SwNode& rNode = GetPoint()->nNode.GetNode();
@@ -1640,13 +1642,59 @@ bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
     else
         fnGo = CRSR_SKIP_CELLS == nMode ? GoInContentCells : GoInContent;
 
+    SwTextFrame const* pFrame(nullptr);
+    if (pLayout)
+    {
+        pFrame = static_cast<SwTextFrame*>(rNode.GetContentNode()->getLayoutFrame(pLayout));
+        if (pFrame)
+        {
+            while (pFrame->GetPrecede())
+            {
+                pFrame = static_cast<SwTextFrame const*>(pFrame->GetPrecede());
+            }
+        }
+    }
+
     while( nCnt )
     {
         SwNodeIndex aOldNodeIdx( GetPoint()->nNode );
 
+        TextFrameIndex beforeIndex;
+        if (pFrame)
+        {
+            beforeIndex = pFrame->MapModelToViewPos(*GetPoint());
+        }
+
         if ( !Move( fnMove, fnGo ) )
             break;
 
+        if (pFrame)
+        {
+            SwTextFrame const* pNewFrame(static_cast<SwTextFrame const*>(
+                GetPoint()->nNode.GetNode().GetContentNode()->getLayoutFrame(pLayout)));
+            if (pNewFrame)
+            {
+                while (pNewFrame->GetPrecede())
+                {
+                    pNewFrame = static_cast<SwTextFrame const*>(pNewFrame->GetPrecede());
+                }
+            }
+            // sw_redlinehide: fully redline-deleted nodes don't have frames...
+            if (pFrame == pNewFrame || !pNewFrame)
+            {
+                if (!pNewFrame || beforeIndex == pFrame->MapModelToViewPos(*GetPoint()))
+                {
+                    continue; // moving inside delete redline, doesn't count...
+                }
+            }
+            else
+            {
+                // assume iteration is stable & returns the same frame
+                assert(!pFrame->IsAnFollow(pNewFrame) && !pNewFrame->IsAnFollow(pFrame));
+                pFrame = pNewFrame;
+            }
+        }
+
         // If we were located inside a covered cell but our position has been
         // corrected, we check if the last move has moved the cursor to a
         // different table cell. In this case we set the cursor to the stored
commit 81347a760ed4172decdec72a3085eb3972a02820
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Sep 10 17:02:28 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: adapt the SwUndoDelete DelFullPara path...
    
    This never splits or joins nodes, so it needs yet another different code
    to keep the merged text frames up to date.
    
    Change-Id: I151edcec9db34c64bf3a29ecad4396d95669d1c9

diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx
index f4f6c5559d85..dbe885665edd 100644
--- a/sw/source/core/undo/undel.cxx
+++ b/sw/source/core/undo/undel.cxx
@@ -70,6 +70,84 @@ static void lcl_MakeAutoFrames( const SwFrameFormats& rSpzArr, sal_uLong nMovedI
     }
 }
 
+static SwTextNode * FindFirstAndNextNode(SwDoc & rDoc, SwUndRng const& rRange,
+        SwRedlineSaveDatas const& rRedlineSaveData,
+        SwTextNode *& o_rpFirstMergedDeletedTextNode)
+{
+    // redlines are corrected now to exclude the deleted node
+    assert(rRange.nEndContent == 0);
+    sal_uLong nEndOfRedline = 0;
+    for (size_t i = 0; i < rRedlineSaveData.size(); ++i)
+    {
+        auto const& rRedline(rRedlineSaveData[i]);
+        if (rRedline.nSttNode <= rRange.nSttNode
+            && rRedline.nSttNode < rRange.nEndNode
+            && rRange.nEndNode <= rRedline.nEndNode
+            && rRedline.GetType() == nsRedlineType_t::REDLINE_DELETE)
+        {
+            nEndOfRedline = rRedline.nEndNode;
+            o_rpFirstMergedDeletedTextNode = rDoc.GetNodes()[rRedline.nSttNode]->GetTextNode();
+            assert(rRange.nSttNode == rRange.nEndNode - 1); // otherwise this needs to iterate more RL to find the first node?
+            break;
+        }
+    }
+    if (nEndOfRedline)
+    {
+        assert(o_rpFirstMergedDeletedTextNode);
+        SwTextNode * pNextNode(nullptr);
+        for (sal_uLong i = rRange.nEndNode; /* i <= nEndOfRedline */; ++i)
+        {
+            SwNode *const pNode(rDoc.GetNodes()[i]);
+            assert(!pNode->IsEndNode()); // cannot be both leaving section here *and* overlapping redline
+            if (pNode->IsStartNode())
+            {
+                i = pNode->EndOfSectionIndex(); // will be incremented again
+            }
+            else if (pNode->IsTextNode())
+            {
+                pNextNode = pNode->GetTextNode();
+                break;
+            }
+        }
+        assert(pNextNode);
+        return pNextNode;
+    }
+    else
+    {
+        return nullptr;
+    }
+}
+
+static void DelFullParaMoveFrames(SwDoc & rDoc, SwUndRng const& rRange,
+        SwRedlineSaveDatas const& rRedlineSaveData)
+{
+    SwTextNode * pFirstMergedDeletedTextNode(nullptr);
+    SwTextNode *const pNextNode = FindFirstAndNextNode(rDoc, rRange,
+            rRedlineSaveData, pFirstMergedDeletedTextNode);
+    if (pNextNode)
+    {
+        std::vector<SwTextFrame*> frames;
+        SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pFirstMergedDeletedTextNode);
+        for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+        {
+            if (pFrame->getRootFrame()->IsHideRedlines())
+            {
+                assert(pFrame->GetMergedPara());
+                assert(pFrame->GetMergedPara()->pFirstNode == pFirstMergedDeletedTextNode);
+                assert(pNextNode->GetIndex() <= pFrame->GetMergedPara()->pLastNode->GetIndex());
+                frames.push_back(pFrame);
+            }
+        }
+        for (SwTextFrame *const pFrame : frames)
+        {
+            // sw_redlinehide: don't need FrameMode::Existing here
+            // because everything from pNextNode onwards is already
+            // correctly hidden
+            pFrame->RegisterToNode(*pNextNode, true);
+        }
+    }
+}
+
 // SwUndoDelete has to perform a deletion and to record anything that is needed
 // to restore the situation before the deletion. Unfortunately a part of the
 // deletion will be done after calling this Ctor, this has to be kept in mind!
@@ -178,6 +256,10 @@ SwUndoDelete::SwUndoDelete(
                     ? pSttTextNd
                     : pEnd->nNode.GetNode().GetTextNode();
     }
+    else if (m_pRedlSaveData)
+    {
+        DelFullParaMoveFrames(*pDoc, *this, *m_pRedlSaveData);
+    }
 
     bool bMoveNds = *pStt != *pEnd      // any area still existent?
                 && ( SaveContent( pStt, pEnd, pSttTextNd, pEndTextNd ) || m_bFromTableCopy );
@@ -962,7 +1044,44 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
     if( m_pRedlSaveData )
         SetSaveData(rDoc, *m_pRedlSaveData);
 
-    if (m_aSttStr && (!m_bFromTableCopy || 0 != m_nNode))
+    sal_uLong delFullParaEndNode(nEndNode);
+    if (m_bDelFullPara && m_pRedlSaveData)
+    {
+        SwTextNode * pFirstMergedDeletedTextNode(nullptr);
+        SwTextNode *const pNextNode = FindFirstAndNextNode(rDoc, *this,
+                *m_pRedlSaveData, pFirstMergedDeletedTextNode);
+        if (pNextNode)
+        {
+            bool bNonMerged(false);
+            std::vector<SwTextFrame*> frames;
+            SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pNextNode);
+            for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+            {
+                if (pFrame->getRootFrame()->IsHideRedlines())
+                {
+                    frames.push_back(pFrame);
+                }
+                else
+                {
+                    bNonMerged = true;
+                }
+            }
+            for (SwTextFrame *const pFrame : frames)
+            {
+                // could either destroy the text frames, or move them...
+                // destroying them would have the advantage that we don't
+                // need special code to *exclude* pFirstMergedDeletedTextNode
+                // from MakeFrames  for the layouts in Hide mode but not
+                // layouts in Show mode ...
+                // ... except that MakeFrames won't create them then :(
+                pFrame->RegisterToNode(*pFirstMergedDeletedTextNode);
+                assert(pFrame->GetMergedPara());
+                assert(!bNonMerged); // delFullParaEndNode is such an awful hack
+                delFullParaEndNode = pFirstMergedDeletedTextNode->GetIndex();
+            }
+        }
+    }
+    else if (m_aSttStr && (!m_bFromTableCopy || 0 != m_nNode))
     {
         // only now do we have redlines in the document again; fix up the split
         // frames
@@ -999,7 +1118,7 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
         // by the start node, or it may be merged by one of the moved nodes,
         // but if it isn't merged, its current frame(s) should be good...
         SwNodeIndex const start(rDoc.GetNodes(), nSttNode + (m_bDelFullPara ? 0 : 1));
-        SwNodeIndex const end(rDoc.GetNodes(), nEndNode);
+        SwNodeIndex const end(rDoc.GetNodes(), m_bDelFullPara ? delFullParaEndNode : nEndNode);
         ::MakeFrames(&rDoc, start, end);
     }
 
@@ -1074,6 +1193,11 @@ void SwUndoDelete::RedoImpl(::sw::UndoRedoContext & rContext)
 
     if( !m_aSttStr && !m_aEndStr )
     {
+        if (m_bDelFullPara && m_pRedlSaveData)
+        {
+            DelFullParaMoveFrames(rDoc, *this, *m_pRedlSaveData);
+        }
+
         SwNodeIndex aSttIdx = ( m_bDelFullPara || m_bJoinNext )
                                     ? rPam.GetMark()->nNode
                                     : rPam.GetPoint()->nNode;
@@ -1129,6 +1253,7 @@ void SwUndoDelete::RedoImpl(::sw::UndoRedoContext & rContext)
     }
     else if( m_bDelFullPara )
     {
+        assert(!"dead code");
         // The Pam was incremented by one at Point (== end) to provide space
         // for UNDO. This now needs to be reverted!
         --rPam.End()->nNode;
commit a11cbc241bc109e352d15dced9eac008c95ab85f
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Sep 10 14:38:13 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: JoinPrev with NonFirst node
    
    This needs to recreate the frames on the node preceding the deleted one,
    in case the second node of the join wasn't merged like the first was,
    but is merged afterwards...
    
    Change-Id: I001ba3af118614c1cce891cf6faec7e829576d21

diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx
index 54c6a1c56e74..5a1d2b7ab814 100644
--- a/sw/source/core/doc/docedt.cxx
+++ b/sw/source/core/doc/docedt.cxx
@@ -418,7 +418,10 @@ bool sw_JoinText( SwPaM& rPam, bool bJoinPrev )
                 sw::MoveDeletedPrevFrames(*pOldTextNd, *pTextNd);
             }
             pDoc->GetNodes().Delete( aOldIdx );
-            sw::CheckResetRedlineMergeFlag(*pTextNd, eOldMergeFlag == SwNode::Merge::NonFirst);
+            sw::CheckResetRedlineMergeFlag(*pTextNd,
+                    eOldMergeFlag == SwNode::Merge::NonFirst
+                        ? sw::Recreate::Predecessor
+                        : sw::Recreate::No);
         }
         else
         {
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 0b19178734d2..a9d3a6dd1fe5 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -109,7 +109,8 @@ void MoveMergedFlysAndFootnotes(std::vector<SwTextFrame*> const& rFrames,
         SwTextNode const& rFirstNode, SwTextNode & rSecondNode, bool);
 
 void MoveDeletedPrevFrames(SwTextNode & rDeletedPrev, SwTextNode & rNode);
-void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool bRecreateMerged);
+enum class Recreate { No, ThisNode, Predecessor };
+void CheckResetRedlineMergeFlag(SwTextNode & rNode, Recreate eRecreateMerged);
 
 void UpdateFramesForAddDeleteRedline(SwPaM const& rPam);
 void UpdateFramesForRemoveDeleteRedline(SwDoc & rDoc, SwPaM const& rPam);
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index da5e65037763..7302a168c840 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -877,21 +877,42 @@ void MoveDeletedPrevFrames(SwTextNode & rDeletedPrev, SwTextNode & rNode)
     /// not only fix the flag; if prev is First the frame is actually deleted!!!
     // if prev is First : must not delete frame but move it
     // if prev is NonFirst : must delete frame (if this is First/None) & merge into prev
-void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool const bRecreateMerged)
+void CheckResetRedlineMergeFlag(SwTextNode & rNode, Recreate const eRecreateMerged)
 {
-    if (bRecreateMerged)
+    if (eRecreateMerged != sw::Recreate::No)
     {
+        SwTextNode * pMergeNode(&rNode);
+        if (eRecreateMerged == sw::Recreate::Predecessor)
+        {
+            for (sal_uLong i = rNode.GetIndex() - 1; ; --i)
+            {
+                SwNode *const pNode(rNode.GetNodes()[i]);
+                assert(!pNode->IsStartNode());
+                if (pNode->IsEndNode())
+                {
+                    i = pNode->StartOfSectionIndex();
+                }
+                else if (pNode->IsTextNode())
+                {
+                    pMergeNode = pNode->GetTextNode(); // use predecessor to merge
+                    break;
+                }
+            }
+        }
         std::vector<SwTextFrame*> frames;
-        SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rNode);
+        SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pMergeNode);
         for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
         {
-            frames.push_back(pFrame);
+            if (pFrame->getRootFrame()->IsHideRedlines())
+            {
+                frames.push_back(pFrame);
+            }
         }
         for (SwTextFrame * pFrame : frames)
         {
             SwTextNode & rFirstNode(pFrame->GetMergedPara()
                 ? *pFrame->GetMergedPara()->pFirstNode
-                : rNode);
+                : *pMergeNode);
             assert(rFirstNode.GetIndex() <= rNode.GetIndex());
             pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
                         *pFrame, rFirstNode, sw::FrameMode::Existing));
@@ -1012,7 +1033,9 @@ SwContentNode *SwTextNode::JoinNext()
         SetGrammarCheck( pList3, false );
         SetSmartTags( pList2, false );
         InvalidateNumRule();
-        CheckResetRedlineMergeFlag(*this, eOldMergeFlag == SwNode::Merge::First);
+        CheckResetRedlineMergeFlag(*this, eOldMergeFlag == SwNode::Merge::First
+                                            ? sw::Recreate::ThisNode
+                                            : sw::Recreate::No);
     }
     else {
         OSL_FAIL( "No TextNode." );
@@ -1112,7 +1135,10 @@ void SwTextNode::JoinPrev()
         SetGrammarCheck( pList3, false );
         SetSmartTags( pList2, false );
         InvalidateNumRule();
-        CheckResetRedlineMergeFlag(*this, eOldMergeFlag == SwNode::Merge::NonFirst);
+        sw::CheckResetRedlineMergeFlag(*this,
+                eOldMergeFlag == SwNode::Merge::NonFirst
+                    ? sw::Recreate::Predecessor
+                    : sw::Recreate::No);
     }
     else {
         OSL_FAIL( "No TextNode." );
commit 2dc1e4ea48ae0ea8db708891042986f3bd0088b6
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Sep 7 14:27:46 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw: fix usage of wrong string in SwUndoOverwrite::RedoImpl()
    
    At this point the "aDelStr" is in the document, don't use invalid index.
    
    Change-Id: I0aae8839e9669e3a474266a345b54a1e7e6db38f

diff --git a/sw/source/core/undo/unovwr.cxx b/sw/source/core/undo/unovwr.cxx
index 359010418053..b6f1721a0524 100644
--- a/sw/source/core/undo/unovwr.cxx
+++ b/sw/source/core/undo/unovwr.cxx
@@ -272,7 +272,7 @@ void SwUndoOverwrite::RedoImpl(::sw::UndoRedoContext & rContext)
     {
         rIdx.Assign( pTextNd, nSttContent );
         pCurrentPam->SetMark();
-        pCurrentPam->GetMark()->nContent += aInsStr.getLength();
+        pCurrentPam->GetMark()->nContent += aDelStr.getLength();
         pDoc->getIDocumentRedlineAccess().DeleteRedline( *pCurrentPam, false, USHRT_MAX );
         pCurrentPam->DeleteMark();
     }
commit 575b02af31d49042d31d5d1e19e260784b6900a2
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Sep 7 14:27:30 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw: convert to assert in SwUndoOverwrite
    
    Change-Id: Iafad5a72922db35d94c836cefc53fb6be50eaaad

diff --git a/sw/source/core/undo/unovwr.cxx b/sw/source/core/undo/unovwr.cxx
index d5652ce85e6e..359010418053 100644
--- a/sw/source/core/undo/unovwr.cxx
+++ b/sw/source/core/undo/unovwr.cxx
@@ -183,7 +183,7 @@ void SwUndoOverwrite::UndoImpl(::sw::UndoRedoContext & rContext)
     pCurrentPam->DeleteMark();
     pCurrentPam->GetPoint()->nNode = nSttNode;
     SwTextNode* pTextNd = pCurrentPam->GetNode().GetTextNode();
-    OSL_ENSURE( pTextNd, "Overwrite not in a TextNode?" );
+    assert(pTextNd);
     SwIndex& rIdx = pCurrentPam->GetPoint()->nContent;
     rIdx.Assign( pTextNd, nSttContent );
 
@@ -265,7 +265,7 @@ void SwUndoOverwrite::RedoImpl(::sw::UndoRedoContext & rContext)
     pCurrentPam->DeleteMark();
     pCurrentPam->GetPoint()->nNode = nSttNode;
     SwTextNode* pTextNd = pCurrentPam->GetNode().GetTextNode();
-    OSL_ENSURE( pTextNd, "Overwrite not in TextNode?" );
+    assert(pTextNd);
     SwIndex& rIdx = pCurrentPam->GetPoint()->nContent;
 
     if( pRedlSaveData )
commit 2fd99f04dce0fba3c33eab4c0fcb2fe74764d759
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Sep 7 13:36:02 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw: add some asserts in CheckPosition()
    
    This checks stuff but doesn't complain in any way if it fails, so try to
    make it useful.
    
    Change-Id: I5d52ea020226f1ffc4fda6533761930ac0d7051d

diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
index 716cdfc6c2d7..7d1903a72df4 100644
--- a/sw/source/core/doc/docredln.cxx
+++ b/sw/source/core/doc/docredln.cxx
@@ -122,8 +122,10 @@ bool CheckPosition( const SwPosition* pStt, const SwPosition* pEnd )
     while( pEndStart && (!pEndStart->IsStartNode() || pEndStart->IsSectionNode() ||
         pEndStart->IsTableNode() ) )
         pEndStart = pEndStart->StartOfSectionNode();
+    assert(pSttTab == pEndTab);
     if( pSttTab != pEndTab )
         nError = 1;
+    assert(pSttTab || pSttStart == pEndStart);
     if( !pSttTab && pSttStart != pEndStart )
         nError |= 2;
     if( nError )
commit ae98e1da13ffa8cb10bcb128d623369ac4917628
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Sep 7 12:35:54 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Fri Sep 14 14:36:51 2018 +0200

    sw_redlinehide_2: fix frame updates for SwUndoRedlineDelete
    
    There is a special case where the redline that is inserted doesn't have
    a valid range and then it's split up inside AppendRedline(), in
    SwRedlineTable::InsertWithValidRanges().  This happens for example
    with a selection that includes a section start node but not its end node
    (or vice versa).
    
    This breaks the UpdateFramesForRemoveDeleteRedline() /
    UpdateFramesForAddDeleteRedline() because they assume that the given
    range is one SwRangeRedline; the result is duplicate text frames.
    
    This could be worked around by iterating the SwRangeRedline in the given
    PaM, but for the Remove case there is the additional complication that
    the redlines are actually removed by the time the function is called.
    
    So rework the implementation of DeleteAndJoinWithRedlineImpl()
    to call the part of InsertWithValidRanges() that does the splitting
    into multiple redlines (extracted into new sw::GetAllValidRanges())
    and create multiple SwUndoRedlineDelete actions, each of which now
    updates the frames properly.
    
    Also clean up the horrible group-undo code to group before inserting,
    instead of after-the-fact cleanup.
    
    Change-Id: Ia279910e0c74edabe56b0c4cf87dbbad688179da

diff --git a/sw/inc/redline.hxx b/sw/inc/redline.hxx
index 40d8377fcb54..d66d8b4a8ec6 100644
--- a/sw/inc/redline.hxx
+++ b/sw/inc/redline.hxx
@@ -340,6 +340,13 @@ class SW_DLLPUBLIC SwRedlineHint : public SfxHint
 {
 };
 
+
+namespace sw {
+
+std::vector<SwRangeRedline*> GetAllValidRanges(std::unique_ptr<SwRangeRedline> p);
+
+} // namespace sw
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index dc45775cbf25..46ee7b26f894 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -3571,10 +3571,32 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa
 {
     assert(m_rDoc.getIDocumentRedlineAccess().IsRedlineOn());
 
-    SwUndoRedlineDelete* pUndo = nullptr;
     RedlineFlags eOld = m_rDoc.getIDocumentRedlineAccess().GetRedlineFlags();
     m_rDoc.GetDocumentRedlineManager().checkRedlining( eOld );
 
+    if (*rPam.GetPoint() == *rPam.GetMark())
+    {
+        return false; // do not add empty redlines
+    }
+
+    std::vector<SwRangeRedline*> redlines;
+    {
+        auto pRedline(o3tl::make_unique<SwRangeRedline>(nsRedlineType_t::REDLINE_DELETE, rPam));
+        if (pRedline->HasValidRange())
+        {
+            redlines.push_back(pRedline.release());
+        }
+        else // sigh ... why is such a selection even possible...
+        {    // split it up so we get one SwUndoRedlineDelete per inserted RL
+            redlines = GetAllValidRanges(std::move(pRedline));
+        }
+    }
+
+    if (redlines.empty())
+    {
+        return false;
+    }
+
     auto & rDMA(*m_rDoc.getIDocumentMarkAccess());
     std::vector<std::unique_ptr<SwUndo>> MarkUndos;
     for (auto iter = rDMA.getAnnotationMarksBegin();
@@ -3604,6 +3626,7 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa
         }
     }
 
+    std::vector<std::unique_ptr<SwUndoRedlineDelete>> undos;
     if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
     {
         /* please don't translate -- for cultural reasons this comment is protected
@@ -3611,47 +3634,61 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa
         //JP 06.01.98: MUSS noch optimiert werden!!!
         m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags(
             RedlineFlags::On | RedlineFlags::ShowInsert | RedlineFlags::ShowDelete);
-        pUndo = new SwUndoRedlineDelete( rPam, SwUndoId::DELETE );
-        const SwRewriter aRewriter = pUndo->GetRewriter();
-        m_rDoc.GetIDocumentUndoRedo().StartUndo( SwUndoId::DELETE, &aRewriter );
-        for (auto& it : MarkUndos)
+        for (SwRangeRedline * pRedline : redlines)
+        {
+            assert(pRedline->HasValidRange());
+            undos.emplace_back(o3tl::make_unique<SwUndoRedlineDelete>(
+                        *pRedline, SwUndoId::DELETE));
+        }
+        const SwRewriter aRewriter = undos.front()->GetRewriter();
+        // can only group a single undo action
+        if (MarkUndos.empty() && undos.size() == 1
+            && m_rDoc.GetIDocumentUndoRedo().DoesGroupUndo())
+        {
+            SwUndo * const pLastUndo( m_rDoc.GetUndoManager().GetLastUndo() );
+            SwUndoRedlineDelete *const pUndoRedlineDel(dynamic_cast<SwUndoRedlineDelete*>(pLastUndo));
+            bool const bMerged = pUndoRedlineDel
+                && pUndoRedlineDel->CanGrouping(*undos.front());
+            if (!bMerged)
+            {
+                m_rDoc.GetIDocumentUndoRedo().AppendUndo(undos.front().release());
+            }
+            undos.clear(); // prevent unmatched EndUndo
+        }
+        else
         {
-            m_rDoc.GetIDocumentUndoRedo().AppendUndo(it.release());
+            m_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::DELETE, &aRewriter);
+            for (auto& it : MarkUndos)
+            {
+                m_rDoc.GetIDocumentUndoRedo().AppendUndo(it.release());
+            }
+            for (auto & it : undos)
+            {
+                m_rDoc.GetIDocumentUndoRedo().AppendUndo(it.release());
+            }
         }
-        m_rDoc.GetIDocumentUndoRedo().AppendUndo( pUndo );
     }
 
-    if (*rPam.GetPoint() != *rPam.GetMark())
-        m_rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( nsRedlineType_t::REDLINE_DELETE, rPam ), true );
+    for (SwRangeRedline *const pRedline : redlines)
+    {
+        // note: 1. the pRedline can still be merged & deleted
+        //       2. the impl. can even DeleteAndJoin the range => no plain PaM
+        std::shared_ptr<SwUnoCursor> const pCursor(m_rDoc.CreateUnoCursor(*pRedline->GetMark()));
+        pCursor->SetMark();
+        *pCursor->GetPoint() = *pRedline->GetPoint();
+        m_rDoc.getIDocumentRedlineAccess().AppendRedline(pRedline, true);
+        // sw_redlinehide: 2 reasons why this is needed:
+        // 1. it's the first redline in node => RedlineDelText was sent but ignored
+        // 2. redline spans multiple nodes => must merge text frames
+        sw::UpdateFramesForAddDeleteRedline(*pCursor);
+    }
     m_rDoc.getIDocumentState().SetModified();
 
-    // sw_redlinehide: 2 reasons why this is needed:
-    // 1. it's the first redline in node => RedlineDelText was sent but ignored
-    // 2. redline spans multiple nodes => must merge text frames
-    sw::UpdateFramesForAddDeleteRedline(rPam);
-
-    if (pUndo)
+    if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
     {
-        m_rDoc.GetIDocumentUndoRedo().EndUndo( SwUndoId::EMPTY, nullptr );
-        // ??? why the hell is the AppendUndo not below the
-        // CanGrouping, so this hideous cleanup wouldn't be necessary?
-        // bah, this is redlining, probably changing this would break it...
-        if (m_rDoc.GetIDocumentUndoRedo().DoesGroupUndo())
+        if (!undos.empty())
         {
-            SwUndo * const pLastUndo( m_rDoc.GetUndoManager().GetLastUndo() );
-            SwUndoRedlineDelete *const pUndoRedlineDel( dynamic_cast<SwUndoRedlineDelete*>(pLastUndo) );
-            if (pUndoRedlineDel)

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list