[Libreoffice-commits] core.git: Branch 'private/mst/sw_redlinehide_2' - 748 commits - accessibility/source animations/source avmedia/Module_avmedia.mk avmedia/source basctl/source basegfx/Library_basegfx.mk basegfx/source basegfx/test basic/qa basic/source bin/find-unneeded-includes bin/ios-mapfile-statistics bin/oss-fuzz-build.sh bridges/source canvas/source chart2/inc chart2/IwyuFilter_chart2.yaml chart2/qa chart2/source codemaker/source comphelper/source compilerplugins/clang config_host/config_global.h.in config_host.mk.in configmgr/source configure.ac connectivity/source cppcanvas/source cppuhelper/source cppu/qa cppu/source cpputools/source cui/inc cui/Library_cui.mk cui/source cui/uiconfig cui/UIConfig_cui.mk dbaccess/Executable_odbcconfig.mk dbaccess/qa dbaccess/source dbaccess/win32 desktop/Library_sofficeapp.mk desktop/scripts desktop/source desktop/unx dictionaries distro-configs/LibreOfficeFlatpak.conf download.lst drawinglayer/source dtrans/source dtrans/test editeng/source embeddedo bj/source embedserv/source emfio/source eventattacher/source extensions/source extensions/uiconfig external/boost external/icu external/libcmis external/liborcus external/mariadb-connector-c external/more_fonts external/openssl external/pdfium external/xmlsec extras/source filter/source forms/source formula/source fpicker/Library_fps.mk fpicker/source fpicker/WinResTarget_fps.mk framework/inc framework/source helpcompiler/inc helpcompiler/source helpcontent2 hwpfilter/source i18npool/source i18nutil/source icon-themes/elementary icon-themes/elementary_svg icon-themes/karasa_jaga idlc/inc idlc/source idl/source include/basegfx include/com include/comphelper include/connectivity include/cppuhelper include/editeng include/filter include/ios include/IwyuFilter_include.yaml include/o3tl include/oox include/osl include/rtl include/sal include/salhelper include/sax include/sfx2 include/svl include/svtools include/svx include/test include/toolkit include/tools include/ucbhelper include/unoi dl include/unotools include/vcl include/xmloff ios/CustomTarget_iOS_setup.mk ios/Module_ios.mk io/source ios/source ios/StaticLibrary_ios.mk javaunohelper/source jvmfwk/plugins jvmfwk/source l10ntools/source libreofficekit/qa lingucomponent/source linguistic/source lotuswordpro/inc lotuswordpro/source Makefile.fetch Makefile.in o3tl/qa odk/docs odk/examples odk/source offapi/com officecfg/registry onlineupdate/source oox/inc oox/source oox/util opencl/source package/source postprocess/Rdb_services.mk pyuno/qa pyuno/source qadevOOo/Jar_OOoRunner.mk qadevOOo/objdsc qadevOOo/tests readlicense_oo/license registry/source remotebridges/source reportdesign/source RepositoryExternal.mk Repository.mk salhelper/qa salhelper/source sal/osl sal/qa sal/rtl sal/util sax/source scaddins/source sccomp/source sc/inc sc/IwyuFilter_sc.yaml scp2/source sc/qa scripting/source sc/source sc/uiconfig sc/UIConfig_scalc.mk sdext/Library_PresentationMinimizer.mk sdext/source sd/inc sd/IwyuFilter_sd.yaml sd/Li brary_sdfilt.mk sd/qa sd/source sd/uiconfig setup_native/source sfx2/qa sfx2/source sfx2/uiconfig shell/source slideshow/source smoketest/libtest.cxx solenv/bin solenv/clang-format solenv/CompilerTest_compilerplugins_clang.mk solenv/flatpak-manifest.in solenv/gbuild solenv/sanitizers soltools/cpp soltools/mkdepend sot/source starmath/inc starmath/source starmath/uiconfig stoc/source store/source svgio/inc svgio/source svl/qa svl/source svl/unx svtools/inc svtools/source svtools/uiconfig svtools/UIConfig_svt.mk svx/Executable_pixelctl.mk svx/inc svx/Module_svx.mk svx/source svx/uiconfig svx/workben sw/CppunitTest_sw_ww8export3.mk sw/CppunitTest_sw_xhtmlexport.mk sw/inc sw/Module_sw.mk sw/qa sw/sdi sw/source sw/uiconfig test/Library_subsequenttest.mk test/source testtools/source toolkit/source tools/source ucbhelper/source ucb/source UnoControls/source unodevtools/source unoidl/source unotest/source unotools/source unoxml/source vbahelper/source vcl/backendtest vcl/headless vcl/inc vc l/opengl vcl/osx vcl/qa vcl/qt5 vcl/quartz vcl/source vcl/uiconfig vcl/unx vcl/win vcl/workben wizards/com wizards/source writerfilter/source writerperfect/source xmlhelp/source xmloff/inc xmloff/qa xmloff/source xmlreader/source xmlscript/source xmlsecurity/qa xmlsecurity/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Mon Sep 17 14:30:34 UTC 2018


Rebased ref, commits from common ancestor:
commit 78a998e7ba8c464440aa28abf6d9954a7abca7f1
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Sep 17 12:01:46 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Sep 17 15:56:45 2018 +0200

    sw_redlinehide_2: replace SW_REDLINEHIDE with ExperimentalMode config
    
    So we can get more testing & many bug reports.
    
    Change-Id: I34fe456a58670baecf4fdf1a87da77aceab43891

diff --git a/sw/source/filter/xml/swxml.cxx b/sw/source/filter/xml/swxml.cxx
index 08a086621031..cc4fe8616983 100644
--- a/sw/source/filter/xml/swxml.cxx
+++ b/sw/source/filter/xml/swxml.cxx
@@ -35,6 +35,7 @@
 #include <com/sun/star/packages/WrongPasswordException.hpp>
 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
 #include <com/sun/star/xml/sax/XFastParser.hpp>
+#include <officecfg/Office/Common.hxx>
 #include <o3tl/any.hxx>
 #include <vcl/errinf.hxx>
 #include <sfx2/docfile.hxx>
@@ -854,7 +855,8 @@ ErrCode XMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPaM, con
     if( !(IsOrganizerMode() || IsBlockMode() || m_bInsertMode ||
           m_aOption.IsFormatsOnly() ||
             // sw_redlinehide: disable layout cache for now
-          (getenv("SW_REDLINEHIDE") && !*o3tl::doAccess<bool>(xInfoSet->getPropertyValue(sShowChanges)))))
+          (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext) &&
+            !*o3tl::doAccess<bool>(xInfoSet->getPropertyValue(sShowChanges)))))
     {
         try
         {
@@ -902,7 +904,7 @@ ErrCode XMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPaM, con
     // tdf#83260 ensure that the first call of CompressRedlines after loading
     // the document is a no-op by calling it now
     rDoc.getIDocumentRedlineAccess().CompressRedlines();
-    if (getenv("SW_REDLINEHIDE"))
+    if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
     {   // can't set it on the layout or view shell because it doesn't exist yet
         rDoc.GetDocumentRedlineManager().SetHideRedlines(!(nRedlineFlags & RedlineFlags::ShowDelete));
     }
diff --git a/sw/source/filter/xml/wrtxml.cxx b/sw/source/filter/xml/wrtxml.cxx
index 26a16a31ce29..87ecd70566fb 100644
--- a/sw/source/filter/xml/wrtxml.cxx
+++ b/sw/source/filter/xml/wrtxml.cxx
@@ -26,6 +26,8 @@
 #include <com/sun/star/document/XFilter.hpp>
 #include <com/sun/star/frame/XModule.hpp>
 
+#include <officecfg/Office/Common.hxx>
+
 #include <comphelper/fileformat.h>
 #include <comphelper/processfactory.hxx>
 #include <comphelper/genericpropertyset.hxx>
@@ -184,7 +186,7 @@ ErrCode SwXMLWriter::Write_( const uno::Reference < task::XStatusIndicator >& xS
     const OUString sShowChanges("ShowChanges");
     RedlineFlags nRedlineFlags = m_pDoc->getIDocumentRedlineAccess().GetRedlineFlags();
     bool isShowChanges;
-    if (getenv("SW_REDLINEHIDE"))
+    if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
     {   // TODO: ideally this would be stored per-view...
         isShowChanges = !m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->IsHideRedlines();
     }
@@ -414,7 +416,7 @@ ErrCode SwXMLWriter::Write_( const uno::Reference < task::XStatusIndicator >& xS
     nRedlineFlags = m_pDoc->getIDocumentRedlineAccess().GetRedlineFlags();
     nRedlineFlags &= ~RedlineFlags::ShowMask;
     nRedlineFlags |= RedlineFlags::ShowInsert;
-    if (getenv("SW_REDLINEHIDE"))
+    if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
     {
         nRedlineFlags |= RedlineFlags::ShowDelete;
     }
diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx
index 06e3e8cc6bf0..e4b377fbaacb 100644
--- a/sw/source/uibase/uiview/view2.cxx
+++ b/sw/source/uibase/uiview/view2.cxx
@@ -28,6 +28,7 @@
 #include <com/sun/star/ui/dialogs/ListboxControlActions.hpp>
 #include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
 #include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
+#include <officecfg/Office/Common.hxx>
 #include <svl/aeitem.hxx>
 #include <SwStyleNameMapper.hxx>
 #include <docary.hxx>
@@ -637,7 +638,9 @@ void SwView::Execute(SfxRequest &rReq)
                 if( static_cast<const SfxBoolItem*>(pItem)->GetValue() )
                     nMode |= RedlineFlags::ShowDelete;
 
-                if (getenv("SW_REDLINEHIDE")) // TODO...
+                uno::Reference<uno::XComponentContext> const xContext(
+                        comphelper::getProcessComponentContext());
+                if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
                 {
                     m_pWrtShell->GetLayout()->SetHideRedlines(
                         !static_cast<const SfxBoolItem*>(pItem)->GetValue());
diff --git a/sw/source/uibase/uiview/viewstat.cxx b/sw/source/uibase/uiview/viewstat.cxx
index 437fb12b11f0..49020bde88e1 100644
--- a/sw/source/uibase/uiview/viewstat.cxx
+++ b/sw/source/uibase/uiview/viewstat.cxx
@@ -22,6 +22,7 @@
 
 #include <hintids.hxx>
 #include <com/sun/star/linguistic2/XThesaurus.hpp>
+#include <officecfg/Office/Common.hxx>
 #include <svl/aeitem.hxx>
 #include <svl/whiter.hxx>
 #include <svl/cjkoptions.hxx>
@@ -281,7 +282,9 @@ void SwView::GetState(SfxItemSet &rSet)
             break;
             case FN_REDLINE_SHOW:
             {
-                if (getenv("SW_REDLINEHIDE")) // TODO...
+                uno::Reference<uno::XComponentContext> const xContext(
+                        comphelper::getProcessComponentContext());
+                if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
                 {
                     rSet.Put(SfxBoolItem(nWhich, !m_pWrtShell->GetLayout()->IsHideRedlines()));
                 }
commit 0fd3c901843ad1d035af6fb60a5da4c956dd28e8
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Sep 17 11:26:01 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Sep 17 15:56:45 2018 +0200

    sw_redlinehide_2: disable layout-cache for now
    
    Both reading & writing.
    
    Change-Id: I301bc80549e25c21961b8e79db420e81ab40f8f7

diff --git a/sw/source/filter/xml/swxml.cxx b/sw/source/filter/xml/swxml.cxx
index 0dab7e4cedc3..08a086621031 100644
--- a/sw/source/filter/xml/swxml.cxx
+++ b/sw/source/filter/xml/swxml.cxx
@@ -852,7 +852,9 @@ ErrCode XMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPaM, con
            aFilterArgs, rName, true );
 
     if( !(IsOrganizerMode() || IsBlockMode() || m_bInsertMode ||
-          m_aOption.IsFormatsOnly() ) )
+          m_aOption.IsFormatsOnly() ||
+            // sw_redlinehide: disable layout cache for now
+          (getenv("SW_REDLINEHIDE") && !*o3tl::doAccess<bool>(xInfoSet->getPropertyValue(sShowChanges)))))
     {
         try
         {
diff --git a/sw/source/filter/xml/wrtxml.cxx b/sw/source/filter/xml/wrtxml.cxx
index 4f7a8d4dc55c..26a16a31ce29 100644
--- a/sw/source/filter/xml/wrtxml.cxx
+++ b/sw/source/filter/xml/wrtxml.cxx
@@ -377,7 +377,9 @@ ErrCode SwXMLWriter::Write_( const uno::Reference < task::XStatusIndicator >& xS
     }
 
     if( m_pDoc->getIDocumentLayoutAccess().GetCurrentViewShell() && m_pDoc->getIDocumentStatistics().GetDocStat().nPage > 1 &&
-        !(m_bOrganizerMode || m_bBlock || bErr) )
+        !(m_bOrganizerMode || m_bBlock || bErr ||
+            // sw_redlinehide: disable layout cache for now
+            m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->IsHideRedlines()))
     {
         try
         {
commit 6e5b608250851c46e6d266fd11e76657f6f2a9c4
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Sep 14 18:06:12 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Sep 17 15:56:45 2018 +0200

    sw_redlinehide_2: hide redlines in ascii filter too
    
    It's called from SwEditShell::GetSelectedText() :-/
    
    Change-Id: Ie26c7abd1bc0714bb4c1d49eecb7c869d947c276

diff --git a/sw/inc/shellio.hxx b/sw/inc/shellio.hxx
index 0c81a7fd28c4..219975ff7e86 100644
--- a/sw/inc/shellio.hxx
+++ b/sw/inc/shellio.hxx
@@ -410,6 +410,7 @@ public:
 
     bool m_bBlock : 1;
     bool m_bOrganizerMode : 1;
+    bool m_bHideDeleteRedlines : 1;
 
     Writer();
     virtual ~Writer() override;
diff --git a/sw/source/core/edit/edglss.cxx b/sw/source/core/edit/edglss.cxx
index 8dc8d0a2a226..2949a095f592 100644
--- a/sw/source/core/edit/edglss.cxx
+++ b/sw/source/core/edit/edglss.cxx
@@ -28,6 +28,7 @@
 #include <editsh.hxx>
 #include <edimp.hxx>
 #include <frmfmt.hxx>
+#include <rootfrm.hxx>
 #include <swundo.hxx>
 #include <ndtxt.hxx>
 #include <swtable.hxx>
@@ -304,6 +305,7 @@ bool SwEditShell::GetSelectedText( OUString &rBuf, ParaBreakType nHndlParaBrk )
             aAsciiOpt.SetCharSet( RTL_TEXTENCODING_UCS2 );
             xWrt->SetAsciiOptions( aAsciiOpt );
             xWrt->m_bUCS2_WithStartChar = false;
+            xWrt->m_bHideDeleteRedlines = GetLayout()->IsHideRedlines();
 
             if ( ! aWriter.Write(xWrt).IsError() )
             {
diff --git a/sw/source/filter/ascii/ascatr.cxx b/sw/source/filter/ascii/ascatr.cxx
index c0e6eb1c2c62..ae581f0eeb3e 100644
--- a/sw/source/filter/ascii/ascatr.cxx
+++ b/sw/source/filter/ascii/ascatr.cxx
@@ -24,6 +24,8 @@
 #include <pam.hxx>
 #include <doc.hxx>
 #include <ndtxt.hxx>
+#include <IDocumentRedlineAccess.hxx>
+#include <redline.hxx>
 #include "wrtasc.hxx"
 #include <txatbase.hxx>
 #include <fchrfmt.hxx>
@@ -166,6 +168,74 @@ bool SwASC_AttrIter::OutAttr( sal_Int32 nSwPos )
     return bRet;
 }
 
+class SwASC_RedlineIter
+{
+private:
+    SwTextNode const& m_rNode;
+    IDocumentRedlineAccess const& m_rIDRA;
+    SwRedlineTable::size_type m_nextRedline;
+
+public:
+    SwASC_RedlineIter(SwASCWriter const& rWriter, SwTextNode const& rNode)
+        : m_rNode(rNode)
+        , m_rIDRA(rNode.GetDoc()->getIDocumentRedlineAccess())
+        , m_nextRedline(rWriter.m_bHideDeleteRedlines
+            ? m_rIDRA.GetRedlinePos(m_rNode, nsRedlineType_t::REDLINE_DELETE)
+            : SwRedlineTable::npos)
+    {
+    }
+
+    bool CheckNodeDeleted()
+    {
+        if (m_nextRedline == SwRedlineTable::npos)
+        {
+            return false;
+        }
+        SwRangeRedline const*const pRedline(m_rIDRA.GetRedlineTable()[m_nextRedline]);
+        return pRedline->Start()->nNode.GetIndex() < m_rNode.GetIndex()
+            && m_rNode.GetIndex() < pRedline->End()->nNode.GetIndex();
+    }
+
+    std::pair<sal_Int32, sal_Int32> GetNextRedlineSkip()
+    {
+        sal_Int32 nRedlineStart(COMPLETE_STRING);
+        sal_Int32 nRedlineEnd(COMPLETE_STRING);
+        for ( ; m_nextRedline < m_rIDRA.GetRedlineTable().size(); ++m_nextRedline)
+        {
+            SwRangeRedline const*const pRedline(m_rIDRA.GetRedlineTable()[m_nextRedline]);
+            if (pRedline->GetType() != nsRedlineType_t::REDLINE_DELETE)
+            {
+                continue;
+            }
+            SwPosition const*const pStart(pRedline->Start());
+            SwPosition const*const pEnd(pRedline->End());
+            if (m_rNode.GetIndex() < pStart->nNode.GetIndex())
+            {
+                m_nextRedline = SwRedlineTable::npos;
+                break; // done
+            }
+            if (nRedlineStart == COMPLETE_STRING)
+            {
+                nRedlineStart = pStart->nNode.GetIndex() == m_rNode.GetIndex()
+                        ? pStart->nContent.GetIndex()
+                        : 0;
+            }
+            else
+            {
+                if (pStart->nContent.GetIndex() != nRedlineEnd)
+                {
+                    assert(nRedlineEnd < pStart->nContent.GetIndex());
+                    break; // no increment, revisit it next call
+                }
+            }
+            nRedlineEnd = pEnd->nNode.GetIndex() == m_rNode.GetIndex()
+                    ? pEnd->nContent.GetIndex()
+                    : COMPLETE_STRING;
+        }
+        return std::make_pair(nRedlineStart, nRedlineEnd);
+    }
+};
+
 // Output of the node
 
 static Writer& OutASC_SwTextNode( Writer& rWrt, SwContentNode& rNode )
@@ -182,6 +252,12 @@ static Writer& OutASC_SwTextNode( Writer& rWrt, SwContentNode& rNode )
     bool bIsOneParagraph = rWrt.m_pOrigPam->Start()->nNode == rWrt.m_pOrigPam->End()->nNode;
 
     SwASC_AttrIter aAttrIter( static_cast<SwASCWriter&>(rWrt), rNd, nStrPos );
+    SwASC_RedlineIter redlineIter(static_cast<SwASCWriter&>(rWrt), rNd);
+
+    if (redlineIter.CheckNodeDeleted())
+    {
+        return rWrt;
+    }
 
     const SwNumRule* pNumRule = rNd.GetNumRule();
     if (pNumRule && !nStrPos && rWrt.m_bExportPargraphNumbering && !bIsOneParagraph)
@@ -219,12 +295,49 @@ static Writer& OutASC_SwTextNode( Writer& rWrt, SwContentNode& rNode )
     const bool bExportSoftHyphens = RTL_TEXTENCODING_UCS2 == rWrt.GetAsciiOptions().GetCharSet() ||
                                     RTL_TEXTENCODING_UTF8 == rWrt.GetAsciiOptions().GetCharSet();
 
+    std::pair<sal_Int32, sal_Int32> curRedline(redlineIter.GetNextRedlineSkip());
     for (;;) {
         const sal_Int32 nNextAttr = std::min(aAttrIter.WhereNext(), nEnd);
 
-        if( !aAttrIter.OutAttr( nStrPos ))
+        bool isOutAttr(false);
+        if (nStrPos < curRedline.first || curRedline.second <= nStrPos)
         {
-            OUString aOutStr( aStr.copy( nStrPos, nNextAttr - nStrPos ) );
+            isOutAttr = aAttrIter.OutAttr(nStrPos);
+        }
+
+        if (!isOutAttr)
+        {
+            OUStringBuffer buf;
+            while (true)
+            {
+                if (nNextAttr <= curRedline.first)
+                {
+                    buf.append(aStr.copy(nStrPos, nNextAttr - nStrPos));
+                    break;
+                }
+                else if (nStrPos < curRedline.second)
+                {
+                    if (nStrPos < curRedline.first)
+                    {
+                        buf.append(aStr.copy(nStrPos, curRedline.first - nStrPos));
+                    }
+                    if (curRedline.second <= nNextAttr)
+                    {
+                        nStrPos = curRedline.second;
+                        curRedline = redlineIter.GetNextRedlineSkip();
+                    }
+                    else
+                    {
+                        nStrPos = nNextAttr;
+                        break;
+                    }
+                }
+                else
+                {
+                    curRedline = redlineIter.GetNextRedlineSkip();
+                }
+            }
+            OUString aOutStr(buf.makeStringAndClear());
             if ( !bExportSoftHyphens )
                 aOutStr = aOutStr.replaceAll(OUStringLiteral1(CHAR_SOFTHYPHEN), "");
 
diff --git a/sw/source/filter/writer/writer.cxx b/sw/source/filter/writer/writer.cxx
index cd8450fbe033..e86a01d70f3b 100644
--- a/sw/source/filter/writer/writer.cxx
+++ b/sw/source/filter/writer/writer.cxx
@@ -120,6 +120,7 @@ void Writer_Impl::InsertBkmk(const ::sw::mark::IMark& rBkmk)
 Writer::Writer()
     : m_pImpl(o3tl::make_unique<Writer_Impl>())
     , m_pOrigFileName(nullptr), m_pDoc(nullptr), m_pOrigPam(nullptr), m_pCurrentPam(nullptr)
+    , m_bHideDeleteRedlines(false)
 {
     m_bWriteAll = m_bShowProgress = m_bUCS2_WithStartChar = true;
     m_bASCII_NoLastLineEnd = m_bASCII_ParaAsBlank = m_bASCII_ParaAsCR =
commit 392b37083c3c738d2244867960b6ba462577c42d
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: Mon Sep 17 15:56:45 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 64bdaa3a5cc1..dde56486e0a7 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 1b4c46b4eb80..0533fae9be27 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 ff2d645c83da..bbd4ccc268fd 100644
--- a/sw/source/core/txtnode/txtedt.cxx
+++ b/sw/source/core/txtnode/txtedt.cxx
@@ -695,36 +695,43 @@ static 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 83b5c005b1559d49ca90718e8daa316010b1b5ad
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: Mon Sep 17 15:56:45 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 5a2cfe23278d..18eab64c3468 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 9be4243977430a97c055529985a3a5aeb4589edf
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: Mon Sep 17 15:56:45 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 c818a9400c3f..90348e42189d 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -2387,6 +2387,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 39117e5e1856b6b2188c179f0726562ff7d1994d
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: Mon Sep 17 15:56:45 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 68a8a499b119..64bdaa3a5cc1 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 30cfed591c78..14f87719a334 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -3392,12 +3392,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 36bc43b3a33fec3ecbbac13350200117e20e9c04
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: Mon Sep 17 15:56:45 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 c4861ed75fe5..c818a9400c3f 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -1045,11 +1045,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->GetMark()->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 e4e1a4aa5ba8e71d1b3ea575963ad27a57eb5e43
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: Mon Sep 17 15:56:45 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 32aab859b611..c4861ed75fe5 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -2350,21 +2350,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 9d5007bbb288..ecb0150f25a4 100644
--- a/sw/source/ui/dbui/mmlayoutpage.cxx
+++ b/sw/source/ui/dbui/mmlayoutpage.cxx
@@ -453,7 +453,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 35859296016e49515bcc6fa10a5aaa50bf8c6adc
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: Mon Sep 17 15:56:45 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 1c26480bd000..32aab859b611 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -2351,7 +2351,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 a67325a730ec..9d5007bbb288 100644
--- a/sw/source/ui/dbui/mmlayoutpage.cxx
+++ b/sw/source/ui/dbui/mmlayoutpage.cxx
@@ -453,7 +453,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 239a1256c6b9b158f8ea2987be460a0c79df1c7a
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: Mon Sep 17 15:56:45 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 bc053b947a74..1c26480bd000 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -644,6 +644,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
@@ -656,7 +682,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 2173efff673a9bc7c0473936821258c2a94f6ca0
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: Mon Sep 17 15:56:45 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 ac0e0e812004..6578d9e2b1ca 100644
--- a/sw/source/core/crsr/swcrsr.cxx
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -1115,70 +1115,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 );
 
@@ -1186,64 +1216,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;
         }
@@ -1251,24 +1292,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;
         }
@@ -1276,23 +1322,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;
         }
@@ -1300,26 +1350,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;
         }
@@ -1341,7 +1399,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?
@@ -1369,30 +1427,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
@@ -1453,61 +1527,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;
         }
@@ -1515,11 +1598,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())
@@ -1532,24 +1615,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 b488f6b426d3..1c579e2b3569 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 fdd42ce4c99f..d16972e71e3c 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 60ac385659099249422e0e7aa8b239eb4fdb16e9
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: Mon Sep 17 15:56:45 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 25118e6f9aa9..ac0e0e812004 100644
--- a/sw/source/core/crsr/swcrsr.cxx
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -1825,7 +1825,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;
@@ -1844,7 +1845,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 )
     {
@@ -1880,7 +1881,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());
             }
         }
 
@@ -1889,7 +1890,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;
         }
 
@@ -1900,8 +1901,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;
@@ -1909,13 +1910,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 be6be7f0d868..4a2b73d5a194 100644
--- a/sw/source/core/crsr/viscrs.cxx
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -698,7 +698,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 9725815c5ed0..95a52d7b0ed1 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 678cb0c07eb1d3d1fe4f2268be74da4244c5f39d
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: Mon Sep 17 15:56:45 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 6dc236921d9b..bc053b947a74 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -350,7 +350,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 1b74af2faa58..25118e6f9aa9 100644
--- a/sw/source/core/crsr/swcrsr.cxx
+++ b/sw/source/core/crsr/swcrsr.cxx
@@ -1559,7 +1559,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 );
@@ -1621,7 +1622,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();
@@ -1638,13 +1640,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(-1);
+        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 a4a9a1effe60bb8f7787b9fb6f7c57eac8a297c6
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: Mon Sep 17 15:56:45 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 65acbbc63bbe..3f27ada19883 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!
@@ -176,6 +254,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 );
@@ -960,7 +1042,45 @@ 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
+                (void) bNonMerged;
+                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
@@ -997,7 +1117,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);
     }
 
@@ -1072,6 +1192,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;
@@ -1127,6 +1252,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 ad6543ca416dafd5fabcbe8b2b93192efca225dd
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: Mon Sep 17 15:56:45 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 0a01b1f4beeb..74de269c36fb 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 04ebd2bd4b27..30cfed591c78 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -873,21 +873,42 @@ void MoveDeletedPrevFrames(SwTextNode & rDeletedPrev, SwTextNode & rNode)
 
 /// if first node is First, its frames may need to be moved, never deleted.
 /// if first node is NonFirst, second node's own frames (First/None) must be deleted
-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);

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list