[Libreoffice-commits] core.git: Branch 'private/mst/sw_redlinehide_2' - 804 commits - accessibility/source android/source autogen.sh avmedia/Library_avmedia.mk avmedia/source basctl/source basegfx/source basic/source binaryurp/source bin/check-elf-dynamic-objects bin/gbuild-to-ide bin/oss-fuzz-build.sh bridges/source chart2/IwyuFilter_chart2.yaml chart2/Library_chartcore.mk chart2/qa chart2/source cli_ure/source comphelper/source compilerplugins/clang config_host/config_global.h.in config_host.mk.in configmgr/qa configmgr/source configure.ac connectivity/Configuration_mysql.mk connectivity/inc connectivity/Library_mysqlc.mk connectivity/Library_mysql.mk connectivity/Module_connectivity.mk connectivity/registry connectivity/source cppcanvas/source cppuhelper/source cppu/source cui/Library_cui.mk cui/source cui/uiconfig dbaccess/qa dbaccess/source desktop/Executable_oosplash.mk desktop/inc desktop/Library_sofficeapp.mk desktop/Module_desktop.mk desktop/source dictionaries distro-configs/Jenkins dis tro-configs/LibreOfficeHaiku.conf distro-configs/LibreOfficeOssFuzz.conf download.lst drawinglayer/source editeng/inc editeng/qa editeng/source emfio/CppunitTest_emfio_wmf_test.mk emfio/source extensions/inc extensions/source external/breakpad external/cairo external/epoxy external/firebird external/harfbuzz external/mariadb-connector-c external/mdds external/Module_external.mk external/mysql-connector-cpp external/pdfium external/python3 external/twain_dsm external/xmlsec extras/CustomTarget_tplofficorr.mk extras/CustomTarget_tploffimisc.mk extras/CustomTarget_tplpersonal.mk extras/CustomTarget_tpl_styles.mk extras/Module_extras.mk extras/Package_tplofficorr.mk extras/Package_tploffimisc.mk extras/Package_tplpersonal.mk extras/Package_tpl_styles.mk extras/README extras/source filter/source forms/source formula/source fpicker/source framework/inc framework/source helpcontent2 hwpfilter/source i18nlangtag/qa i18nlangtag/source i18npool/inc i18npool/source icon-themes/breeze icon-them es/breeze_dark icon-themes/breeze_svg icon-themes/colibre icon-themes/colibre_svg icon-themes/elementary icon-themes/elementary_svg icon-themes/karasa_jaga idlc/inc idlc/source include/android include/basegfx include/comphelper include/connectivity include/drawinglayer include/editeng include/filter include/formula include/i18nlangtag include/IwyuFilter_include.yaml include/LibreOfficeKit include/o3tl include/oox include/package include/rtl include/sal include/sfx2 include/store include/svl include/svtools include/svx include/test include/tools include/unotools include/vbahelper include/vcl include/xmloff include/xmlreader instsetoo_native/CustomTarget_setup.mk instsetoo_native/inc_ooohelppack instsetoo_native/inc_openoffice instsetoo_native/inc_sdkoo ios/LibreOfficeLight ios/Module_ios.mk io/source javaunohelper/com javaunohelper/source jurt/com jvmfwk/plugins jvmfwk/source libreofficekit/README linguistic/source lotuswordpro/source Makefile.fetch Makefile.in mysqlc/Configuration_m ysql.mk mysqlc/Extension_mysql-connector-ooo.mk mysqlc/Library_mysqlc.mk mysqlc/Makefile mysqlc/Module_mysqlc.mk mysqlc/Rdb_mysqlc.mk mysqlc/README mysqlc/source odk/examples offapi/com officecfg/registry officecfg/util oox/source opencl/source package/inc package/qa package/source postprocess/CustomTarget_registry.mk postprocess/Module_postprocess.mk postprocess/Rdb_services.mk qadevOOo/Jar_OOoRunner.mk qadevOOo/objdsc qadevOOo/tests registry/source registry/test reportbuilder/java reportdesign/inc reportdesign/qa reportdesign/source RepositoryExternal.mk Repository.mk RepositoryModule_host.mk sal/cppunittester sal/CppunitTest_sal_rtl.mk sal/Library_sal.mk sal/osl sal/qa sal/rtl sal/textenc sax/source sc/inc sc/IwyuFilter_sc.yaml sc/Module_sc.mk scp2/source sc/qa scripting/source sc/sdi sc/source sc/uiconfig sc/UITest_textCase.mk sd/CppunitTest_sd_uimpress.mk sdext/source sd/inc sd/IwyuFilter_sd.yaml sd/Library_sdfilt.mk sd/Module_sd.mk sd/qa sd/sdi sd/source sd/uiconfig setup_nati ve/source sfx2/inc sfx2/qa sfx2/sdi sfx2/source shell/source slideshow/Library_slideshow.mk slideshow/source solenv/bin solenv/clang-format solenv/CompilerTest_compilerplugins_clang.mk solenv/flatpak-manifest.in solenv/gbuild solenv/qa sot/source starmath/inc starmath/source stoc/source store/source svgio/source svl/qa svl/source svtools/inc svtools/qa svtools/source svx/Executable_gengal.mk svx/inc svx/Library_svxcore.mk svx/sdi svx/source svx/uiconfig sw/CppunitTest_sw_mailmerge.mk sw/CppunitTest_sw_odfimport.mk sw/inc sw/Module_sw.mk sw/qa sw/sdi sw/source sw/uiconfig sysui/desktop test/Library_subsequenttest.mk test/source toolkit/Library_tk.mk toolkit/source toolkit/test tools/Library_tl.mk tools/qa tools/source ucb/source udkapi/com uitest/loginterpreter.py UnoControls/source unoidl/source unotools/source unoxml/inc unoxml/source uui/source vbahelper/source vcl/android vcl/CppunitTest_vcl_bitmap_test.mk vcl/CustomTarget_qt5_moc.mk vcl/Executable_icontest.mk vcl/Executable_mmlf uzzer.mk vcl/Executable_scrtffuzzer.mk vcl/Executable_vcldemo.mk vcl/headless vcl/inc vcl/ios vcl/Library_vcl.mk vcl/Library_vclplug_qt5.mk vcl/Module_vcl.mk vcl/opengl vcl/osx vcl/qa vcl/qt5 vcl/quartz vcl/README vcl/source vcl/uiconfig vcl/unx vcl/win vcl/workben winaccessibility/inc winaccessibility/source wizards/source writerfilter/source xmlhelp/source xmloff/inc xmloff/source xmlscript/source xmlsecurity/qa xmlsecurity/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Fri Aug 31 09:53:18 UTC 2018


Rebased ref, commits from common ancestor:
commit ddb2cae9e0cf7eada18219997e6fd6cfa42ff293
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 22 17:09:02 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2: SwUndoDelete
    
    This is problematic because of the calls to SplitNode.
    Ideally we'd want the SplitNode to create merged frames already, but
    that doesn't seem to be easy to achieve; several problems with this are:
    
    1. the redlines are only restored at the end of UndoImpl
    2. even if we store another set of SwRedlineSaveDatas right before the
       Join (while preventing the first SwRedlineSaveDatas from deleting
       them), and restore them by passing a closure to SplitNode, there
       are complaints about empty redlines, and also this case isn't
       handled properly:
    
         f<delete start>o<redline start>o
         b<redline end>a<redline start>r
         b<redline end>a<delete end>z
    
    So instead, let SplitNode create whatever frames it does, and fix it up
    at the end manually on the start node's frames.
    
    This necessitates delaying the creation of the frames on the moved nodes
    until the end too.
    
    Change-Id: I8ba2967659cc2ddbe6f7c40e0447d79601498ed6

diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx
index 7e942b427ecb..f4f6c5559d85 100644
--- a/sw/source/core/undo/undel.cxx
+++ b/sw/source/core/undo/undel.cxx
@@ -41,6 +41,9 @@
 #include <sfx2/app.hxx>
 #include <fldbas.hxx>
 #include <fmtfld.hxx>
+#include <frmtool.hxx>
+#include <txtfrm.hxx>
+#include <rootfrm.hxx>
 #include <strings.hrc>
 #include <vector>
 
@@ -763,6 +766,7 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
 
     SwNodeIndex aIdx(rDoc.GetNodes(), nCalcStt);
     SwNode* pInsNd = &aIdx.GetNode();
+    SwNode* pMovedNode = nullptr;
 
     {   // code block so that SwPosition is detached when deleting a Node
         SwPosition aPos( aIdx );
@@ -838,7 +842,6 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
                     ++aPos.nNode;
             }
         }
-        SwNode* pMovedNode = nullptr;
         if( m_nSectDiff )
         {
             sal_uLong nMoveIndex = aPos.nNode.GetIndex();
@@ -866,7 +869,11 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
         {
             SwNodeRange aRange( *m_pMvStt, 0, *m_pMvStt, m_nNode );
             SwNodeIndex aCopyIndex( aPos.nNode, -1 );
-            rDoc.GetUndoManager().GetUndoNodes().Copy_( aRange, aPos.nNode );
+            rDoc.GetUndoManager().GetUndoNodes().Copy_(aRange, aPos.nNode,
+                    // sw_redlinehide: delay creating frames: the flags on the
+                    // nodes aren't necessarily up-to-date, and the redlines
+                    // from m_pRedlSaveData aren't applied yet...
+                    false);
 
             if( m_nReplaceDummy )
             {
@@ -889,9 +896,6 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
             }
         }
 
-        if( pMovedNode )
-            lcl_MakeAutoFrames(*rDoc.GetSpzFrameFormats(), pMovedNode->GetIndex());
-
         if( m_aSttStr )
         {
             aPos.nNode = nSttNode - m_nNdDiff + ( m_bJoinNext ? 0 : m_nReplaceDummy );
@@ -958,6 +962,52 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
     if( m_pRedlSaveData )
         SetSaveData(rDoc, *m_pRedlSaveData);
 
+    if (m_aSttStr && (!m_bFromTableCopy || 0 != m_nNode))
+    {
+        // only now do we have redlines in the document again; fix up the split
+        // frames
+        SwTextNode *const pStartNode(aIdx.GetNodes()[nSttNode]->GetTextNode());
+        assert(pStartNode);
+        std::vector<SwTextFrame*> frames;
+        SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pStartNode);
+        for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+        {
+            if (pFrame->getRootFrame()->IsHideRedlines())
+            {
+                frames.push_back(pFrame);
+            }
+        }
+        for (SwTextFrame * pFrame : frames)
+        {
+            // SplitNode could have moved the original frame to the start node
+            // & created a new one on end, or could have created new frame on
+            // start node... grab start node's frame and recreate MergedPara.
+            SwTextNode & rFirstNode(pFrame->GetMergedPara()
+                ? *pFrame->GetMergedPara()->pFirstNode
+                : *pStartNode);
+            assert(rFirstNode.GetIndex() <= pStartNode->GetIndex());
+            pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
+                        *pFrame, rFirstNode, sw::FrameMode::Existing));
+            // note: this may or may not delete frames on the end node
+        }
+    }
+
+    // create frames after SetSaveData has recreated redlines
+    if (0 != m_nNode)
+    {
+        // don't include end node in the range: it may have been merged already
+        // 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);
+        ::MakeFrames(&rDoc, start, end);
+    }
+
+    if (pMovedNode)
+    {   // probably better do this after creating all frames
+        lcl_MakeAutoFrames(*rDoc.GetSpzFrameFormats(), pMovedNode->GetIndex());
+    }
+
     AddUndoRedoPaM(rContext, true);
 }
 
commit 2a9aefb8581f91d93874ff80068467e514a4d288
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 22 15:09:59 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2: something about Join
    
    Change-Id: I047b6008c5f0bb6e79c63421a4dba09ba8cf3320
    Todo: remember what i was thinking when i wrote this

diff --git a/sw/source/core/doc/docedt.cxx b/sw/source/core/doc/docedt.cxx
index 89454ea879ae..54c6a1c56e74 100644
--- a/sw/source/core/doc/docedt.cxx
+++ b/sw/source/core/doc/docedt.cxx
@@ -412,7 +412,13 @@ bool sw_JoinText( SwPaM& rPam, bool bJoinPrev )
                     rPam.GetBound( false ) = aAlphaPos;
             }
             // delete the Node, at last!
+            SwNode::Merge const eOldMergeFlag(pOldTextNd->GetRedlineMergeFlag());
+            if (eOldMergeFlag == SwNode::Merge::First)
+            {
+                sw::MoveDeletedPrevFrames(*pOldTextNd, *pTextNd);
+            }
             pDoc->GetNodes().Delete( aOldIdx );
+            sw::CheckResetRedlineMergeFlag(*pTextNd, eOldMergeFlag == SwNode::Merge::NonFirst);
         }
         else
         {
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 028c3605aa50..10bde328c903 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -105,6 +105,9 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged,
         bool isRealDelete,
         SwTextNode const& rNode, sal_Int32 nIndex, sal_Int32 nLen);
 
+void MoveDeletedPrevFrames(SwTextNode & rDeletedPrev, SwTextNode & rNode);
+void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool bRecreateMerged);
+
 } // namespace sw
 
 /// Represents the visualization of a paragraph. Typical upper is an
@@ -726,7 +729,7 @@ public:
 
     static void repaintTextFrames( const SwTextNode& rNode );
 
-    void RegisterToNode( SwTextNode& );
+    void RegisterToNode(SwTextNode &, bool isForceNodeAsFirst = false);
 
     virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const override;
 };
diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx
index 3a37ae92bc7f..8b8e7bd22610 100644
--- a/sw/source/core/layout/ssfrm.cxx
+++ b/sw/source/core/layout/ssfrm.cxx
@@ -440,14 +440,19 @@ SwContentFrame::~SwContentFrame()
 {
 }
 
-void SwTextFrame::RegisterToNode(SwTextNode & rNode)
+void SwTextFrame::RegisterToNode(SwTextNode & rNode, bool const isForceNodeAsFirst)
 {
+    if (isForceNodeAsFirst && m_pMergedPara)
+    {   // nothing registered here, in particular no redlines
+        assert(m_pMergedPara->pFirstNode->GetIndex() + 1 == rNode.GetIndex());
+        assert(!m_pMergedPara->pFirstNode->HasAnyIndex());
+    }
     assert(&rNode != GetDep());
     assert(!m_pMergedPara
         || (m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex())
         || (rNode.GetIndex() + 1 == m_pMergedPara->pFirstNode->GetIndex()));
     SwTextNode & rFirstNode(
-        (m_pMergedPara && m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex())
+        (!isForceNodeAsFirst && m_pMergedPara && m_pMergedPara->pFirstNode->GetIndex() < rNode.GetIndex())
             ? *m_pMergedPara->pFirstNode
             : rNode);
     // sw_redlinehide: use New here, because the only caller also calls lcl_ChangeFootnoteRef
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index defd89105380..b9e44c32cbc6 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -823,8 +823,51 @@ void SwTextNode::MoveTextAttr_To_AttrSet()
 
 }
 
-namespace {
+namespace sw {
+
+    // None,Node->None
+    // None,First->First
+    // First,NonFirst->First
+    // NonFirst,First->NonFirst
+    // NonFirst,None->NonFirst
+
 
+void MoveDeletedPrevFrames(SwTextNode & rDeletedPrev, SwTextNode & rNode)
+{
+    std::vector<SwTextFrame*> frames;
+    SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(rDeletedPrev);
+    for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+    {
+        frames.push_back(pFrame);
+    }
+    {
+        auto frames2(frames);
+        SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIt(rNode);
+        for (SwTextFrame* pFrame = aIt.First(); pFrame; pFrame = aIt.Next())
+        {
+            auto const it(std::find(frames2.begin(), frames2.end(), pFrame));
+            assert(it != frames2.end());
+            frames2.erase(it);
+        }
+        assert(frames2.empty());
+    }
+    for (SwTextFrame * pFrame : frames)
+    {
+        pFrame->RegisterToNode(rNode, true);
+#if 0
+        if (pFrame->m_pMergedPara && pFrame->m_pMergedPara->pFirstNode == &rDeletedPrev && GetIndex() <= pFrame->m_pMergedPara->pLastNode->GetIndex())
+        {
+            pFrame->listeners.StopListening(&rDeletedPrev);
+            pFrame->m_pMergedPara->pFirstNode = &rNode;
+            &rNode.SetRedlineMergeFlag(SwNodes::Merge::First);
+        }
+#endif
+    }
+}
+
+    /// not only fix the flag; if prev is First the frame is actually deleted!!!
+    // if prev is First : must not delete frame but move it
+    // if prev is NonFirst : must delete frame (if this is First/None) & merge into prev
 void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool const bRecreateMerged)
 {
     if (bRecreateMerged)
@@ -843,6 +886,9 @@ void CheckResetRedlineMergeFlag(SwTextNode & rNode, bool const bRecreateMerged)
             assert(rFirstNode.GetIndex() <= rNode.GetIndex());
             pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
                         *pFrame, rFirstNode, sw::FrameMode::Existing));
+            assert(pFrame->GetMergedPara());
+            assert(pFrame->GetMergedPara()->listener.IsListeningTo(&rNode));
+            assert(rNode.GetIndex() <= pFrame->GetMergedPara()->pLastNode->GetIndex());
         }
     }
     else if (rNode.GetRedlineMergeFlag() != SwNode::Merge::None)
@@ -1048,6 +1094,10 @@ void SwTextNode::JoinPrev()
             pDoc->CorrAbs( aIdx, SwPosition( *this ), nLen, true );
         }
         SwNode::Merge const eOldMergeFlag(pTextNode->GetRedlineMergeFlag());
+        if (eOldMergeFlag == SwNode::Merge::First)
+        {
+            sw::MoveDeletedPrevFrames(*pTextNode, *this);
+        }
         rNds.Delete(aIdx);
         SetWrong( pList, false );
         SetGrammarCheck( pList3, false );
commit e89efdd75365a8c9d2e754cea9c82ae873c4cc0e
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 22 15:04:18 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2: DelFrames is called for hidden nodes too now
    
    Change-Id: I9933d8b8ee29bb4da74819d7d2350a5b2b04aa09

diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index 8d8a4072bcdd..3e6ff2d4f565 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4348,8 +4348,9 @@ static void UnHideRedlines(SwRootFrame & rLayout,
             {
                 if (rNode.IsContentNode())
                 {
-                    // note: no-op for NonFirst nodes, only Hidden will delete
-                    static_cast<SwContentNode&>(rNode).DelFrames(&rLayout);
+                    // note: nothing to do here, already done
+                    auto const pFrame(static_cast<SwContentNode&>(rNode).getLayoutFrame(&rLayout));
+                    assert(!pFrame || static_cast<SwTextFrame*>(pFrame)->GetMergedPara()->pFirstNode != &rNode);
                 }
                 else if (rNode.IsTableNode())
                 {
commit dc2a5eed4430bcc62ab594a6fee85e659e76b9d4
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 22 15:03:42 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2: another assert (merge this?)
    
    Change-Id: Ica141176e0accd07f9b4246a71df5e660119078e

diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index bcea7f789905..8d8a4072bcdd 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4172,6 +4172,7 @@ static void UnHideRedlines(SwRootFrame & rLayout,
         std::set<sal_uLong> *const pSkipped)
 {
     assert(rEndOfSectionNode.IsEndNode());
+    assert(rNodes[rEndOfSectionNode.StartOfSectionNode()->GetIndex() + 1]->IsCreateFrameWhenHidingRedlines()); // first node is never hidden
     for (sal_uLong i = rEndOfSectionNode.StartOfSectionNode()->GetIndex() + 1;
          i < rEndOfSectionNode.GetIndex(); ++i)
     {
commit 7f92bec824fece514b48f4f273a3c7a308e88310
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 22 13:26:18 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    Revert "this looks like a wrong path..."
    
    This reverts commit 391b6325117483c73f6fd0fb2286b37aaeeb46e4.

diff --git a/sw/inc/IDocumentContentOperations.hxx b/sw/inc/IDocumentContentOperations.hxx
index b3204109a8a0..fb4006334a15 100644
--- a/sw/inc/IDocumentContentOperations.hxx
+++ b/sw/inc/IDocumentContentOperations.hxx
@@ -22,7 +22,6 @@
 
 #include <sal/types.h>
 #include <rtl/ustring.hxx>
-#include <functional>
 #include "swtypes.hxx"
 
 class SwPaM;
@@ -38,9 +37,6 @@ class SwFrameFormat;
 class SwDrawFrameFormat;
 class SwFlyFrameFormat;
 class SwNodeIndex;
-class SwTextNode;
-
-namespace sw { namespace mark { enum class RestoreMode; } }
 
 namespace utl { class TransliterationWrapper; }
 namespace svt { class EmbeddedObjectRef; }
@@ -190,8 +186,7 @@ public:
 
     /** Split a node at rPos (implemented only for TextNode).
     */
-    virtual bool SplitNode(const SwPosition &rPos, bool bChkTableStart,
-        std::function<void ()> const* pRedlineRestore = nullptr) = 0;
+    virtual bool SplitNode(const SwPosition &rPos, bool bChkTableStart) = 0;
 
     virtual bool AppendTextNode(SwPosition& rPos) = 0;
 
diff --git a/sw/inc/IDocumentRedlineAccess.hxx b/sw/inc/IDocumentRedlineAccess.hxx
index d6c44b24e680..a68af07fb707 100644
--- a/sw/inc/IDocumentRedlineAccess.hxx
+++ b/sw/inc/IDocumentRedlineAccess.hxx
@@ -180,7 +180,7 @@ public:
     virtual bool DeleteRedline(
         /*[in]*/const SwPaM& rPam,
         /*[in]*/bool bSaveInUndo,
-        /*[in]*/sal_uInt16 nDelType, bool bIgnoreJoining = false) = 0;
+        /*[in]*/sal_uInt16 nDelType) = 0;
 
     virtual bool DeleteRedline(
         /*[in]*/const SwStartNode& rSection,
diff --git a/sw/inc/undobj.hxx b/sw/inc/undobj.hxx
index afb4ecee7184..2e84ff9c1d6e 100644
--- a/sw/inc/undobj.hxx
+++ b/sw/inc/undobj.hxx
@@ -119,11 +119,9 @@ public:
 
     bool IsDelBox() const;
 
-    enum class DelRange { Ignore, Delete, DeleteNonJoining };
     // Save and set Redline data.
     static bool FillSaveData( const SwPaM& rRange, SwRedlineSaveDatas& rSData,
-                              DelRange eDelRange = DelRange::Delete,
-                              bool bCopyNext = true );
+                              bool bDelRange = true, bool bCopyNext = true );
     static bool FillSaveDataForFormat( const SwPaM& , SwRedlineSaveDatas& );
     static void SetSaveData( SwDoc& rDoc, SwRedlineSaveDatas& rSData );
     static bool HasHiddenRedlines( const SwRedlineSaveDatas& rSData );
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 688318420c85..f6a2562983cd 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -2831,8 +2831,7 @@ SwDrawFrameFormat* DocumentContentOperationsManager::InsertDrawObj(
     return pFormat;
 }
 
-bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool bChkTableStart,
-        std::function<void ()> const*const pRedlineRestore)
+bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool bChkTableStart )
 {
     SwContentNode *pNode = rPos.nNode.GetNode().GetContentNode();
     if(nullptr == pNode)
@@ -2966,10 +2965,6 @@ bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool b
                         m_rDoc.getIDocumentRedlineAccess().SplitRedline(aPam);
                     }
                 }
-                if (pRedlineRestore)
-                {
-                    (*pRedlineRestore)();
-                }
             }
         });
     pNode->GetTextNode()->SplitContentNode(rPos, &restoreFunc);
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx
index beb8728b0c9a..ad9c292810a1 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -1923,7 +1923,7 @@ bool DocumentRedlineManager::SplitRedline( const SwPaM& rRange )
 }
 
 bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUndo,
-        sal_uInt16 const nDelType, bool const bIgnoreJoining)
+                            sal_uInt16 nDelType )
 {
     if( RedlineFlags::IgnoreDeleteRedlines & meRedlineFlags ||
         !rRange.HasMark() || *rRange.GetMark() == *rRange.GetPoint() )
@@ -1956,13 +1956,6 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd
         SwPosition* pRStt = pRedl->Start(),
                   * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
                                                        : pRedl->GetPoint();
-        if (bIgnoreJoining && pRStt->nNode != pREnd->nNode
-            && pRStt->nNode.GetIndex() <= pStt->nNode.GetIndex()
-            && pEnd->nNode.GetIndex() <= pREnd->nNode.GetIndex())
-        {
-            continue; // ignore node-joining redline
-        }
-
         switch( ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ) )
         {
         case SwComparePosition::Equal:
diff --git a/sw/source/core/inc/DocumentContentOperationsManager.hxx b/sw/source/core/inc/DocumentContentOperationsManager.hxx
index 55f15ad3b79e..c60676617b78 100644
--- a/sw/source/core/inc/DocumentContentOperationsManager.hxx
+++ b/sw/source/core/inc/DocumentContentOperationsManager.hxx
@@ -78,8 +78,7 @@ public:
     SwFlyFrameFormat* InsertOLE(const SwPaM &rRg, const OUString& rObjName, sal_Int64 nAspect, const SfxItemSet* pFlyAttrSet,
                            const SfxItemSet* pGrfAttrSet) override;
 
-    bool SplitNode(const SwPosition &rPos, bool bChkTableStart,
-        std::function<void ()> const* pRedlineRestore = nullptr) override;
+    bool SplitNode(const SwPosition &rPos, bool bChkTableStart) override;
 
     bool AppendTextNode(SwPosition& rPos) override;
 
diff --git a/sw/source/core/inc/DocumentRedlineManager.hxx b/sw/source/core/inc/DocumentRedlineManager.hxx
index d9cdf7ca3e59..f534cccea3fd 100644
--- a/sw/source/core/inc/DocumentRedlineManager.hxx
+++ b/sw/source/core/inc/DocumentRedlineManager.hxx
@@ -61,7 +61,7 @@ public:
     virtual bool DeleteRedline(
         /*[in]*/const SwPaM& rPam,
         /*[in]*/bool bSaveInUndo,
-        /*[in]*/sal_uInt16 nDelType, bool bIgnoreJoining = false) override;
+        /*[in]*/sal_uInt16 nDelType) override;
 
     virtual bool DeleteRedline(
         /*[in]*/const SwStartNode& rSection,
diff --git a/sw/source/core/inc/UndoDelete.hxx b/sw/source/core/inc/UndoDelete.hxx
index 699bc09c21b1..f22832b18d54 100644
--- a/sw/source/core/inc/UndoDelete.hxx
+++ b/sw/source/core/inc/UndoDelete.hxx
@@ -40,7 +40,6 @@ class SwUndoDelete
     std::unique_ptr<SwNodeIndex> m_pMvStt;            // Position of Nodes in UndoNodes-Array
     boost::optional<OUString> m_aSttStr, m_aEndStr;
     std::unique_ptr<SwRedlineSaveDatas> m_pRedlSaveData;
-    std::unique_ptr<SwRedlineSaveDatas> m_pRedlSaveDataAtEnd;
     std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
     std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;
 
diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx
index 0b7e93979016..7e942b427ecb 100644
--- a/sw/source/core/undo/undel.cxx
+++ b/sw/source/core/undo/undel.cxx
@@ -32,8 +32,6 @@
 #include <swundo.hxx>
 #include <pam.hxx>
 #include <ndtxt.hxx>
-#include <txtfrm.hxx>
-#include <rootfrm.hxx>
 #include <UndoCore.hxx>
 #include <rolbck.hxx>
 #include <poolfmt.hxx>
@@ -121,15 +119,11 @@ SwUndoDelete::SwUndoDelete(
     bCacheComment = false;
 
     SwDoc * pDoc = rPam.GetDoc();
-    bool bMustDelete(false);
 
     if( !pDoc->getIDocumentRedlineAccess().IsIgnoreRedline() && !pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty() )
     {
         m_pRedlSaveData.reset(new SwRedlineSaveDatas);
-//        if (!FillSaveData(rPam, *m_pRedlSaveData, false /*true in 2nd call*/))
-        bMustDelete = rPam.GetPoint()->nNode != rPam.GetMark()->nNode;
-//        if (!FillSaveData(rPam, *m_pRedlSaveData, rPam.GetPoint()->nNode == rPam.GetMark()->nNode))
-        if (!FillSaveData(rPam, *m_pRedlSaveData, SwUndo::DelRange::DeleteNonJoining))
+        if( !FillSaveData( rPam, *m_pRedlSaveData ))
         {
             m_pRedlSaveData.reset();
         }
@@ -216,7 +210,7 @@ SwUndoDelete::SwUndoDelete(
 
     if( !pSttTextNd && !pEndTextNd )
         --rPam.GetPoint()->nNode;
-//    rPam.DeleteMark();          // the SPoint is in the selection
+    rPam.DeleteMark();          // the SPoint is in the selection
 
     if( !pEndTextNd )
         nEndContent = 0;
@@ -360,22 +354,6 @@ SwUndoDelete::SwUndoDelete(
     // is a history necessary here at all?
     if( pHistory && !pHistory->Count() )
         pHistory.reset();
-
-    assert(pDoc->getIDocumentRedlineAccess().IsIgnoreRedline()
-        || pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty()
-        || (pStt->nNode != pEnd->nNode) == bMustDelete);
-    if (pStt->nNode != pEnd->nNode
-        && !pDoc->getIDocumentRedlineAccess().IsIgnoreRedline()
-        && !pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty())
-    {   // horrible duplication that SplitNode can undo
-        m_pRedlSaveDataAtEnd.reset(new SwRedlineSaveDatas);
-        if (!FillSaveData(rPam, *m_pRedlSaveDataAtEnd))
-        {
-            m_pRedlSaveDataAtEnd.reset();
-        }
-    }
-
-    rPam.DeleteMark(); // now it is no longer a range...
 }
 
 bool SwUndoDelete::SaveContent( const SwPosition* pStt, const SwPosition* pEnd,
@@ -506,7 +484,7 @@ bool SwUndoDelete::CanGrouping( SwDoc* pDoc, const SwPaM& rDelPam )
 
     {
         SwRedlineSaveDatas aTmpSav;
-        const bool bSaved = FillSaveData(rDelPam, aTmpSav, SwUndo::DelRange::Ignore);
+        const bool bSaved = FillSaveData( rDelPam, aTmpSav, false );
 
         bool bOk = ( !m_pRedlSaveData && !bSaved ) ||
                    ( m_pRedlSaveData && bSaved &&
@@ -810,7 +788,6 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
             pInsNd = nullptr;         // do not delete Node!
 
         bool bNodeMove = 0 != m_nNode;
-        bool bRedlAtEndRestored(false);
 
         if( m_aEndStr )
         {
@@ -826,17 +803,7 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
             if( m_aSttStr && !m_bFromTableCopy )
             {
                 sal_uLong nOldIdx = aPos.nNode.GetIndex();
-                // call this before messing with frames in SplitNode
-                std::function<void ()> restoreFunc(
-                    [&]()
-                    {
-                        if (m_pRedlSaveDataAtEnd)
-                        {
-                            SetSaveData(rDoc, *m_pRedlSaveDataAtEnd);
-                        }
-                    });
-                rDoc.getIDocumentContentOperations().SplitNode(aPos, false, &restoreFunc);
-                bRedlAtEndRestored = true;
+                rDoc.getIDocumentContentOperations().SplitNode( aPos, false );
                 // After the split all objects are anchored at the first
                 // paragraph, but the pHistory of the fly frame formats relies
                 // on anchoring at the start of the selection
@@ -845,11 +812,6 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
                     lcl_ReAnchorAtContentFlyFrames(*rDoc.GetSpzFrameFormats(), aPos, nOldIdx);
                 pTextNd = aPos.nNode.GetNode().GetTextNode();
             }
-            else if (m_pRedlSaveDataAtEnd)
-            {
-                SetSaveData(rDoc, *m_pRedlSaveDataAtEnd);
-                bRedlAtEndRestored = true;
-            }
             if( pTextNd )
             {
                 OUString const ins( pTextNd->InsertText(*m_aEndStr, aPos.nContent,
@@ -868,30 +830,14 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
                 if (nSttContent < pNd->GetText().getLength())
                 {
                     sal_uLong nOldIdx = aPos.nNode.GetIndex();
-                    // call this before messing with frames in SplitNode
-                    std::function<void ()> restoreFunc(
-                        [&]()
-                        {
-                            if (m_pRedlSaveDataAtEnd)
-                            {
-                                SetSaveData(rDoc, *m_pRedlSaveDataAtEnd);
-                            }
-                        });
-                    rDoc.getIDocumentContentOperations().SplitNode(aPos, false, &restoreFunc);
-                    bRedlAtEndRestored = true;
+                    rDoc.getIDocumentContentOperations().SplitNode( aPos, false );
                     if( m_bBackSp )
                         lcl_ReAnchorAtContentFlyFrames(*rDoc.GetSpzFrameFormats(), aPos, nOldIdx);
                 }
                 else
-                {
                     ++aPos.nNode;
-                }
             }
         }
-        if (!bRedlAtEndRestored && m_pRedlSaveDataAtEnd)
-        {
-            SetSaveData(rDoc, *m_pRedlSaveDataAtEnd);
-        }
         SwNode* pMovedNode = nullptr;
         if( m_nSectDiff )
         {
@@ -920,23 +866,7 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
         {
             SwNodeRange aRange( *m_pMvStt, 0, *m_pMvStt, m_nNode );
             SwNodeIndex aCopyIndex( aPos.nNode, -1 );
-            rDoc.GetUndoManager().GetUndoNodes().Copy_(aRange, aPos.nNode,
-                    // SplitNode would have inited this flag; at this point,
-                    // either all these nodes are Hidden or all are None
-                    // (it might be that in the None case, the 2nd SetSaveData
-                    //  below will introduce new redlines...)
-                    false);
-#if 0
-                    aPos.nNode.GetRedlineMergeFlag() == SwNode::Merge::None);
-#endif
-            if (aPos.nNode.GetNode().GetRedlineMergeFlag() != SwNode::Merge::None)
-            {
-                for (sal_uLong i = aCopyIndex.GetIndex() + m_nNode; aCopyIndex.GetIndex() < i; --i)
-                {
-                    rDoc.GetNodes()[i]->SetRedlineMergeFlag(SwNode::Merge::Hidden);
-                }
-            }
-            // TODO after the SetSaveData we need to check again ???
+            rDoc.GetUndoManager().GetUndoNodes().Copy_( aRange, aPos.nNode );
 
             if( m_nReplaceDummy )
             {
@@ -1026,62 +956,8 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
     if( pInsNd )
         rDoc.GetNodes().Delete( aIdx );
     if( m_pRedlSaveData )
-    {
         SetSaveData(rDoc, *m_pRedlSaveData);
 
-#if 0
-        if (m_aSttStr && (!m_bFromTableCopy || 0 != m_nNode))
-        {
-            // only now do we have redlines in the document again; fix up the frame
-            SwTextNode *const pStartNode(aIdx.GetNodes()[nSttNode]->GetTextNode());
-            SwTextNode *const pEndNode(aIdx.GetNodes()[nEndNode]->GetTextNode());
-            // FIXME we need to fetch frame of end node????
-            // the MakeCopy already creates frames of intermediate nodes depending on their flag... problem: deletion was with redlines shown, restore with hidden
-            assert(pNode);
-            std::vector<SwTextFrame*> frames;
-            SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pEndNode);
-            for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
-            {
-                if (pFrame->getRootFrame()->IsHideRedlines())
-                {
-                    frames.push_back(pFrame);
-                }
-            }
-            for (SwTextFrame * pFrame : frames)
-            {
-// this is not going to work if there are intermediate nodes with frames                pFrame->RegisterToNode(*pStartNode);
-#if 0
-                SwTextNode & rFirstNode(pFrame->GetMergedPara()
-                    ? *pFrame->GetMergedPara()->pFirstNode
-                    : *pStartNode);
-                assert(rFirstNode.GetIndex() <= pNode->GetIndex());
-                pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
-                            *pFrame, rFirstNode, sw::FrameMode::Existing));
-#endif
-            }
-        }
-#endif
-    }
-
-    // create frames after SetSaveData has recreated redlines
-    if (0 != m_nNode)
-    {
-        SwNodeIndex const start(rDoc.GetNodes(), nSttNode + 1);
-        SwNodeIndex const end(rDoc.GetNodes(), nEndNode);
-        ::MakeFrames(&rDoc, start, end);
-    }
-
-    // ... plan: let SplitNode do whatever;
-    // don't create frames on moved nodes;
-    // after SetSaveData, call CheckRedline... on start node,
-    // then MakeFrames
-    // ... what about end node ? will be either properly merged or properly un-merged after handling start node, so just include it in MakeFrames range.
-    //
-    // The interesting case is
-    //  f<delete start>o<redline start>o
-    //  b<redline end>a<redline start>r
-    //  b<redline end>a<delete end>z
-
     AddUndoRedoPaM(rContext, true);
 }
 
diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx
index 94299badd501..5afbde167ad2 100644
--- a/sw/source/core/undo/undobj.cxx
+++ b/sw/source/core/undo/undobj.cxx
@@ -1378,7 +1378,7 @@ void SwRedlineSaveData::RedlineToDoc( SwPaM const & rPam )
 bool SwUndo::FillSaveData(
     const SwPaM& rRange,
     SwRedlineSaveDatas& rSData,
-    DelRange const eDelRange,
+    bool bDelRange,
     bool bCopyNext )
 {
     rSData.clear();
@@ -1403,10 +1403,9 @@ bool SwUndo::FillSaveData(
             rSData.push_back(std::unique_ptr<SwRedlineSaveData, o3tl::default_delete<SwRedlineSaveData>>(new SwRedlineSaveData(eCmpPos, *pStt, *pEnd, *pRedl, bCopyNext)));
         }
     }
-    if (!rSData.empty() && eDelRange != DelRange::Ignore)
+    if( !rSData.empty() && bDelRange )
     {
-        rRange.GetDoc()->getIDocumentRedlineAccess().DeleteRedline(
-            rRange, false, USHRT_MAX, eDelRange == DelRange::DeleteNonJoining);
+        rRange.GetDoc()->getIDocumentRedlineAccess().DeleteRedline( rRange, false, USHRT_MAX );
     }
     return !rSData.empty();
 }
diff --git a/sw/source/core/undo/unovwr.cxx b/sw/source/core/undo/unovwr.cxx
index 6e6a64fbd52a..e2fb76a19f63 100644
--- a/sw/source/core/undo/unovwr.cxx
+++ b/sw/source/core/undo/unovwr.cxx
@@ -48,7 +48,7 @@ SwUndoOverwrite::SwUndoOverwrite( SwDoc* pDoc, SwPosition& rPos,
         SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex(),
                     rPos.nNode, rPos.nContent.GetIndex()+1 );
         pRedlSaveData.reset( new SwRedlineSaveDatas );
-        if (!FillSaveData( aPam, *pRedlSaveData, SwUndo::DelRange::Ignore))
+        if( !FillSaveData( aPam, *pRedlSaveData, false ))
         {
             pRedlSaveData.reset();
         }
@@ -125,7 +125,7 @@ bool SwUndoOverwrite::CanGrouping( SwDoc* pDoc, SwPosition& rPos,
         SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex(),
                     rPos.nNode, rPos.nContent.GetIndex()+1 );
 
-        const bool bSaved = FillSaveData(aPam, aTmpSav, SwUndo::DelRange::Ignore);
+        const bool bSaved = FillSaveData( aPam, aTmpSav, false );
 
         bool bOk = ( !pRedlSaveData && !bSaved ) ||
                    ( pRedlSaveData && bSaved &&
diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx
index 9bdad5c20299..58d2de808363 100644
--- a/sw/source/core/undo/unredln.cxx
+++ b/sw/source/core/undo/unredln.cxx
@@ -58,8 +58,7 @@ SwUndoRedline::SwUndoRedline( SwUndoId nUsrId, const SwPaM& rRange )
     sal_uLong nEndExtra = rDoc.GetNodes().GetEndOfExtras().GetIndex();
 
     mpRedlSaveData.reset( new SwRedlineSaveDatas );
-    if (!FillSaveData(rRange, *mpRedlSaveData, SwUndo::DelRange::Ignore,
-                      SwUndoId::REJECT_REDLINE != mnUserId))
+    if( !FillSaveData( rRange, *mpRedlSaveData, false, SwUndoId::REJECT_REDLINE != mnUserId ))
     {
         mpRedlSaveData.reset();
     }
@@ -119,8 +118,7 @@ void SwUndoRedline::RedoImpl(::sw::UndoRedoContext & rContext)
     if( mpRedlSaveData && mbHiddenRedlines )
     {
         sal_uLong nEndExtra = rDoc.GetNodes().GetEndOfExtras().GetIndex();
-        FillSaveData(rPam, *mpRedlSaveData, SwUndo::DelRange::Ignore,
-                SwUndoId::REJECT_REDLINE != mnUserId);
+        FillSaveData(rPam, *mpRedlSaveData, false, SwUndoId::REJECT_REDLINE != mnUserId );
 
         nEndExtra -= rDoc.GetNodes().GetEndOfExtras().GetIndex();
         nSttNode -= nEndExtra;
@@ -399,7 +397,7 @@ SwUndoCompDoc::SwUndoCompDoc( const SwRangeRedline& rRedl )
     }
 
     pRedlSaveData.reset( new SwRedlineSaveDatas );
-    if (!FillSaveData( rRedl, *pRedlSaveData, SwUndo::DelRange::Ignore))
+    if( !FillSaveData( rRedl, *pRedlSaveData, false ))
     {
         pRedlSaveData.reset();
     }
diff --git a/sw/source/core/undo/unsect.cxx b/sw/source/core/undo/unsect.cxx
index b225ae42235e..f17cae630316 100644
--- a/sw/source/core/undo/unsect.cxx
+++ b/sw/source/core/undo/unsect.cxx
@@ -88,7 +88,7 @@ SwUndoInsSection::SwUndoInsSection(
         SetRedlineFlags( rDoc.getIDocumentRedlineAccess().GetRedlineFlags() );
     }
         m_pRedlineSaveData.reset( new SwRedlineSaveDatas );
-        if (!FillSaveData( rPam, *m_pRedlineSaveData, SwUndo::DelRange::Ignore))
+        if( !FillSaveData( rPam, *m_pRedlineSaveData, false ))
             m_pRedlineSaveData.reset( nullptr );
 
     if( !rPam.HasMark() )
commit 1bc97300f9efd26eee9d56dd8bf529357ec63832
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 22 13:22:29 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    this looks like a wrong path...
    
    Change-Id: I81181ecb8fa3bae47e9dc0d2a5b49b92608629e6

diff --git a/sw/inc/IDocumentContentOperations.hxx b/sw/inc/IDocumentContentOperations.hxx
index fb4006334a15..b3204109a8a0 100644
--- a/sw/inc/IDocumentContentOperations.hxx
+++ b/sw/inc/IDocumentContentOperations.hxx
@@ -22,6 +22,7 @@
 
 #include <sal/types.h>
 #include <rtl/ustring.hxx>
+#include <functional>
 #include "swtypes.hxx"
 
 class SwPaM;
@@ -37,6 +38,9 @@ class SwFrameFormat;
 class SwDrawFrameFormat;
 class SwFlyFrameFormat;
 class SwNodeIndex;
+class SwTextNode;
+
+namespace sw { namespace mark { enum class RestoreMode; } }
 
 namespace utl { class TransliterationWrapper; }
 namespace svt { class EmbeddedObjectRef; }
@@ -186,7 +190,8 @@ public:
 
     /** Split a node at rPos (implemented only for TextNode).
     */
-    virtual bool SplitNode(const SwPosition &rPos, bool bChkTableStart) = 0;
+    virtual bool SplitNode(const SwPosition &rPos, bool bChkTableStart,
+        std::function<void ()> const* pRedlineRestore = nullptr) = 0;
 
     virtual bool AppendTextNode(SwPosition& rPos) = 0;
 
diff --git a/sw/inc/IDocumentRedlineAccess.hxx b/sw/inc/IDocumentRedlineAccess.hxx
index a68af07fb707..d6c44b24e680 100644
--- a/sw/inc/IDocumentRedlineAccess.hxx
+++ b/sw/inc/IDocumentRedlineAccess.hxx
@@ -180,7 +180,7 @@ public:
     virtual bool DeleteRedline(
         /*[in]*/const SwPaM& rPam,
         /*[in]*/bool bSaveInUndo,
-        /*[in]*/sal_uInt16 nDelType) = 0;
+        /*[in]*/sal_uInt16 nDelType, bool bIgnoreJoining = false) = 0;
 
     virtual bool DeleteRedline(
         /*[in]*/const SwStartNode& rSection,
diff --git a/sw/inc/undobj.hxx b/sw/inc/undobj.hxx
index 2e84ff9c1d6e..afb4ecee7184 100644
--- a/sw/inc/undobj.hxx
+++ b/sw/inc/undobj.hxx
@@ -119,9 +119,11 @@ public:
 
     bool IsDelBox() const;
 
+    enum class DelRange { Ignore, Delete, DeleteNonJoining };
     // Save and set Redline data.
     static bool FillSaveData( const SwPaM& rRange, SwRedlineSaveDatas& rSData,
-                              bool bDelRange = true, bool bCopyNext = true );
+                              DelRange eDelRange = DelRange::Delete,
+                              bool bCopyNext = true );
     static bool FillSaveDataForFormat( const SwPaM& , SwRedlineSaveDatas& );
     static void SetSaveData( SwDoc& rDoc, SwRedlineSaveDatas& rSData );
     static bool HasHiddenRedlines( const SwRedlineSaveDatas& rSData );
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index f6a2562983cd..688318420c85 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -2831,7 +2831,8 @@ SwDrawFrameFormat* DocumentContentOperationsManager::InsertDrawObj(
     return pFormat;
 }
 
-bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool bChkTableStart )
+bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool bChkTableStart,
+        std::function<void ()> const*const pRedlineRestore)
 {
     SwContentNode *pNode = rPos.nNode.GetNode().GetContentNode();
     if(nullptr == pNode)
@@ -2965,6 +2966,10 @@ bool DocumentContentOperationsManager::SplitNode( const SwPosition &rPos, bool b
                         m_rDoc.getIDocumentRedlineAccess().SplitRedline(aPam);
                     }
                 }
+                if (pRedlineRestore)
+                {
+                    (*pRedlineRestore)();
+                }
             }
         });
     pNode->GetTextNode()->SplitContentNode(rPos, &restoreFunc);
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx
index ad9c292810a1..beb8728b0c9a 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -1923,7 +1923,7 @@ bool DocumentRedlineManager::SplitRedline( const SwPaM& rRange )
 }
 
 bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUndo,
-                            sal_uInt16 nDelType )
+        sal_uInt16 const nDelType, bool const bIgnoreJoining)
 {
     if( RedlineFlags::IgnoreDeleteRedlines & meRedlineFlags ||
         !rRange.HasMark() || *rRange.GetMark() == *rRange.GetPoint() )
@@ -1956,6 +1956,13 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd
         SwPosition* pRStt = pRedl->Start(),
                   * pREnd = pRStt == pRedl->GetPoint() ? pRedl->GetMark()
                                                        : pRedl->GetPoint();
+        if (bIgnoreJoining && pRStt->nNode != pREnd->nNode
+            && pRStt->nNode.GetIndex() <= pStt->nNode.GetIndex()
+            && pEnd->nNode.GetIndex() <= pREnd->nNode.GetIndex())
+        {
+            continue; // ignore node-joining redline
+        }
+
         switch( ComparePosition( *pStt, *pEnd, *pRStt, *pREnd ) )
         {
         case SwComparePosition::Equal:
diff --git a/sw/source/core/inc/DocumentContentOperationsManager.hxx b/sw/source/core/inc/DocumentContentOperationsManager.hxx
index c60676617b78..55f15ad3b79e 100644
--- a/sw/source/core/inc/DocumentContentOperationsManager.hxx
+++ b/sw/source/core/inc/DocumentContentOperationsManager.hxx
@@ -78,7 +78,8 @@ public:
     SwFlyFrameFormat* InsertOLE(const SwPaM &rRg, const OUString& rObjName, sal_Int64 nAspect, const SfxItemSet* pFlyAttrSet,
                            const SfxItemSet* pGrfAttrSet) override;
 
-    bool SplitNode(const SwPosition &rPos, bool bChkTableStart) override;
+    bool SplitNode(const SwPosition &rPos, bool bChkTableStart,
+        std::function<void ()> const* pRedlineRestore = nullptr) override;
 
     bool AppendTextNode(SwPosition& rPos) override;
 
diff --git a/sw/source/core/inc/DocumentRedlineManager.hxx b/sw/source/core/inc/DocumentRedlineManager.hxx
index f534cccea3fd..d9cdf7ca3e59 100644
--- a/sw/source/core/inc/DocumentRedlineManager.hxx
+++ b/sw/source/core/inc/DocumentRedlineManager.hxx
@@ -61,7 +61,7 @@ public:
     virtual bool DeleteRedline(
         /*[in]*/const SwPaM& rPam,
         /*[in]*/bool bSaveInUndo,
-        /*[in]*/sal_uInt16 nDelType) override;
+        /*[in]*/sal_uInt16 nDelType, bool bIgnoreJoining = false) override;
 
     virtual bool DeleteRedline(
         /*[in]*/const SwStartNode& rSection,
diff --git a/sw/source/core/inc/UndoDelete.hxx b/sw/source/core/inc/UndoDelete.hxx
index f22832b18d54..699bc09c21b1 100644
--- a/sw/source/core/inc/UndoDelete.hxx
+++ b/sw/source/core/inc/UndoDelete.hxx
@@ -40,6 +40,7 @@ class SwUndoDelete
     std::unique_ptr<SwNodeIndex> m_pMvStt;            // Position of Nodes in UndoNodes-Array
     boost::optional<OUString> m_aSttStr, m_aEndStr;
     std::unique_ptr<SwRedlineSaveDatas> m_pRedlSaveData;
+    std::unique_ptr<SwRedlineSaveDatas> m_pRedlSaveDataAtEnd;
     std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
     std::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;
 
diff --git a/sw/source/core/undo/undel.cxx b/sw/source/core/undo/undel.cxx
index 7e942b427ecb..0b7e93979016 100644
--- a/sw/source/core/undo/undel.cxx
+++ b/sw/source/core/undo/undel.cxx
@@ -32,6 +32,8 @@
 #include <swundo.hxx>
 #include <pam.hxx>
 #include <ndtxt.hxx>
+#include <txtfrm.hxx>
+#include <rootfrm.hxx>
 #include <UndoCore.hxx>
 #include <rolbck.hxx>
 #include <poolfmt.hxx>
@@ -119,11 +121,15 @@ SwUndoDelete::SwUndoDelete(
     bCacheComment = false;
 
     SwDoc * pDoc = rPam.GetDoc();
+    bool bMustDelete(false);
 
     if( !pDoc->getIDocumentRedlineAccess().IsIgnoreRedline() && !pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty() )
     {
         m_pRedlSaveData.reset(new SwRedlineSaveDatas);
-        if( !FillSaveData( rPam, *m_pRedlSaveData ))
+//        if (!FillSaveData(rPam, *m_pRedlSaveData, false /*true in 2nd call*/))
+        bMustDelete = rPam.GetPoint()->nNode != rPam.GetMark()->nNode;
+//        if (!FillSaveData(rPam, *m_pRedlSaveData, rPam.GetPoint()->nNode == rPam.GetMark()->nNode))
+        if (!FillSaveData(rPam, *m_pRedlSaveData, SwUndo::DelRange::DeleteNonJoining))
         {
             m_pRedlSaveData.reset();
         }
@@ -210,7 +216,7 @@ SwUndoDelete::SwUndoDelete(
 
     if( !pSttTextNd && !pEndTextNd )
         --rPam.GetPoint()->nNode;
-    rPam.DeleteMark();          // the SPoint is in the selection
+//    rPam.DeleteMark();          // the SPoint is in the selection
 
     if( !pEndTextNd )
         nEndContent = 0;
@@ -354,6 +360,22 @@ SwUndoDelete::SwUndoDelete(
     // is a history necessary here at all?
     if( pHistory && !pHistory->Count() )
         pHistory.reset();
+
+    assert(pDoc->getIDocumentRedlineAccess().IsIgnoreRedline()
+        || pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty()
+        || (pStt->nNode != pEnd->nNode) == bMustDelete);
+    if (pStt->nNode != pEnd->nNode
+        && !pDoc->getIDocumentRedlineAccess().IsIgnoreRedline()
+        && !pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty())
+    {   // horrible duplication that SplitNode can undo
+        m_pRedlSaveDataAtEnd.reset(new SwRedlineSaveDatas);
+        if (!FillSaveData(rPam, *m_pRedlSaveDataAtEnd))
+        {
+            m_pRedlSaveDataAtEnd.reset();
+        }
+    }
+
+    rPam.DeleteMark(); // now it is no longer a range...
 }
 
 bool SwUndoDelete::SaveContent( const SwPosition* pStt, const SwPosition* pEnd,
@@ -484,7 +506,7 @@ bool SwUndoDelete::CanGrouping( SwDoc* pDoc, const SwPaM& rDelPam )
 
     {
         SwRedlineSaveDatas aTmpSav;
-        const bool bSaved = FillSaveData( rDelPam, aTmpSav, false );
+        const bool bSaved = FillSaveData(rDelPam, aTmpSav, SwUndo::DelRange::Ignore);
 
         bool bOk = ( !m_pRedlSaveData && !bSaved ) ||
                    ( m_pRedlSaveData && bSaved &&
@@ -788,6 +810,7 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
             pInsNd = nullptr;         // do not delete Node!
 
         bool bNodeMove = 0 != m_nNode;
+        bool bRedlAtEndRestored(false);
 
         if( m_aEndStr )
         {
@@ -803,7 +826,17 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
             if( m_aSttStr && !m_bFromTableCopy )
             {
                 sal_uLong nOldIdx = aPos.nNode.GetIndex();
-                rDoc.getIDocumentContentOperations().SplitNode( aPos, false );
+                // call this before messing with frames in SplitNode
+                std::function<void ()> restoreFunc(
+                    [&]()
+                    {
+                        if (m_pRedlSaveDataAtEnd)
+                        {
+                            SetSaveData(rDoc, *m_pRedlSaveDataAtEnd);
+                        }
+                    });
+                rDoc.getIDocumentContentOperations().SplitNode(aPos, false, &restoreFunc);
+                bRedlAtEndRestored = true;
                 // After the split all objects are anchored at the first
                 // paragraph, but the pHistory of the fly frame formats relies
                 // on anchoring at the start of the selection
@@ -812,6 +845,11 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
                     lcl_ReAnchorAtContentFlyFrames(*rDoc.GetSpzFrameFormats(), aPos, nOldIdx);
                 pTextNd = aPos.nNode.GetNode().GetTextNode();
             }
+            else if (m_pRedlSaveDataAtEnd)
+            {
+                SetSaveData(rDoc, *m_pRedlSaveDataAtEnd);
+                bRedlAtEndRestored = true;
+            }
             if( pTextNd )
             {
                 OUString const ins( pTextNd->InsertText(*m_aEndStr, aPos.nContent,
@@ -830,14 +868,30 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
                 if (nSttContent < pNd->GetText().getLength())
                 {
                     sal_uLong nOldIdx = aPos.nNode.GetIndex();
-                    rDoc.getIDocumentContentOperations().SplitNode( aPos, false );
+                    // call this before messing with frames in SplitNode
+                    std::function<void ()> restoreFunc(
+                        [&]()
+                        {
+                            if (m_pRedlSaveDataAtEnd)
+                            {
+                                SetSaveData(rDoc, *m_pRedlSaveDataAtEnd);
+                            }
+                        });
+                    rDoc.getIDocumentContentOperations().SplitNode(aPos, false, &restoreFunc);
+                    bRedlAtEndRestored = true;
                     if( m_bBackSp )
                         lcl_ReAnchorAtContentFlyFrames(*rDoc.GetSpzFrameFormats(), aPos, nOldIdx);
                 }
                 else
+                {
                     ++aPos.nNode;
+                }
             }
         }
+        if (!bRedlAtEndRestored && m_pRedlSaveDataAtEnd)
+        {
+            SetSaveData(rDoc, *m_pRedlSaveDataAtEnd);
+        }
         SwNode* pMovedNode = nullptr;
         if( m_nSectDiff )
         {
@@ -866,7 +920,23 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
         {
             SwNodeRange aRange( *m_pMvStt, 0, *m_pMvStt, m_nNode );
             SwNodeIndex aCopyIndex( aPos.nNode, -1 );
-            rDoc.GetUndoManager().GetUndoNodes().Copy_( aRange, aPos.nNode );
+            rDoc.GetUndoManager().GetUndoNodes().Copy_(aRange, aPos.nNode,
+                    // SplitNode would have inited this flag; at this point,
+                    // either all these nodes are Hidden or all are None
+                    // (it might be that in the None case, the 2nd SetSaveData
+                    //  below will introduce new redlines...)
+                    false);
+#if 0
+                    aPos.nNode.GetRedlineMergeFlag() == SwNode::Merge::None);
+#endif
+            if (aPos.nNode.GetNode().GetRedlineMergeFlag() != SwNode::Merge::None)
+            {
+                for (sal_uLong i = aCopyIndex.GetIndex() + m_nNode; aCopyIndex.GetIndex() < i; --i)
+                {
+                    rDoc.GetNodes()[i]->SetRedlineMergeFlag(SwNode::Merge::Hidden);
+                }
+            }
+            // TODO after the SetSaveData we need to check again ???
 
             if( m_nReplaceDummy )
             {
@@ -956,8 +1026,62 @@ void SwUndoDelete::UndoImpl(::sw::UndoRedoContext & rContext)
     if( pInsNd )
         rDoc.GetNodes().Delete( aIdx );
     if( m_pRedlSaveData )
+    {
         SetSaveData(rDoc, *m_pRedlSaveData);
 
+#if 0
+        if (m_aSttStr && (!m_bFromTableCopy || 0 != m_nNode))
+        {
+            // only now do we have redlines in the document again; fix up the frame
+            SwTextNode *const pStartNode(aIdx.GetNodes()[nSttNode]->GetTextNode());
+            SwTextNode *const pEndNode(aIdx.GetNodes()[nEndNode]->GetTextNode());
+            // FIXME we need to fetch frame of end node????
+            // the MakeCopy already creates frames of intermediate nodes depending on their flag... problem: deletion was with redlines shown, restore with hidden
+            assert(pNode);
+            std::vector<SwTextFrame*> frames;
+            SwIterator<SwTextFrame, SwTextNode, sw::IteratorMode::UnwrapMulti> aIter(*pEndNode);
+            for (SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next())
+            {
+                if (pFrame->getRootFrame()->IsHideRedlines())
+                {
+                    frames.push_back(pFrame);
+                }
+            }
+            for (SwTextFrame * pFrame : frames)
+            {
+// this is not going to work if there are intermediate nodes with frames                pFrame->RegisterToNode(*pStartNode);
+#if 0
+                SwTextNode & rFirstNode(pFrame->GetMergedPara()
+                    ? *pFrame->GetMergedPara()->pFirstNode
+                    : *pStartNode);
+                assert(rFirstNode.GetIndex() <= pNode->GetIndex());
+                pFrame->SetMergedPara(sw::CheckParaRedlineMerge(
+                            *pFrame, rFirstNode, sw::FrameMode::Existing));
+#endif
+            }
+        }
+#endif
+    }
+
+    // create frames after SetSaveData has recreated redlines
+    if (0 != m_nNode)
+    {
+        SwNodeIndex const start(rDoc.GetNodes(), nSttNode + 1);
+        SwNodeIndex const end(rDoc.GetNodes(), nEndNode);
+        ::MakeFrames(&rDoc, start, end);
+    }
+
+    // ... plan: let SplitNode do whatever;
+    // don't create frames on moved nodes;
+    // after SetSaveData, call CheckRedline... on start node,
+    // then MakeFrames
+    // ... what about end node ? will be either properly merged or properly un-merged after handling start node, so just include it in MakeFrames range.
+    //
+    // The interesting case is
+    //  f<delete start>o<redline start>o
+    //  b<redline end>a<redline start>r
+    //  b<redline end>a<delete end>z
+
     AddUndoRedoPaM(rContext, true);
 }
 
diff --git a/sw/source/core/undo/undobj.cxx b/sw/source/core/undo/undobj.cxx
index 5afbde167ad2..94299badd501 100644
--- a/sw/source/core/undo/undobj.cxx
+++ b/sw/source/core/undo/undobj.cxx
@@ -1378,7 +1378,7 @@ void SwRedlineSaveData::RedlineToDoc( SwPaM const & rPam )
 bool SwUndo::FillSaveData(
     const SwPaM& rRange,
     SwRedlineSaveDatas& rSData,
-    bool bDelRange,
+    DelRange const eDelRange,
     bool bCopyNext )
 {
     rSData.clear();
@@ -1403,9 +1403,10 @@ bool SwUndo::FillSaveData(
             rSData.push_back(std::unique_ptr<SwRedlineSaveData, o3tl::default_delete<SwRedlineSaveData>>(new SwRedlineSaveData(eCmpPos, *pStt, *pEnd, *pRedl, bCopyNext)));
         }
     }
-    if( !rSData.empty() && bDelRange )
+    if (!rSData.empty() && eDelRange != DelRange::Ignore)
     {
-        rRange.GetDoc()->getIDocumentRedlineAccess().DeleteRedline( rRange, false, USHRT_MAX );
+        rRange.GetDoc()->getIDocumentRedlineAccess().DeleteRedline(
+            rRange, false, USHRT_MAX, eDelRange == DelRange::DeleteNonJoining);
     }
     return !rSData.empty();
 }
diff --git a/sw/source/core/undo/unovwr.cxx b/sw/source/core/undo/unovwr.cxx
index e2fb76a19f63..6e6a64fbd52a 100644
--- a/sw/source/core/undo/unovwr.cxx
+++ b/sw/source/core/undo/unovwr.cxx
@@ -48,7 +48,7 @@ SwUndoOverwrite::SwUndoOverwrite( SwDoc* pDoc, SwPosition& rPos,
         SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex(),
                     rPos.nNode, rPos.nContent.GetIndex()+1 );
         pRedlSaveData.reset( new SwRedlineSaveDatas );
-        if( !FillSaveData( aPam, *pRedlSaveData, false ))
+        if (!FillSaveData( aPam, *pRedlSaveData, SwUndo::DelRange::Ignore))
         {
             pRedlSaveData.reset();
         }
@@ -125,7 +125,7 @@ bool SwUndoOverwrite::CanGrouping( SwDoc* pDoc, SwPosition& rPos,
         SwPaM aPam( rPos.nNode, rPos.nContent.GetIndex(),
                     rPos.nNode, rPos.nContent.GetIndex()+1 );
 
-        const bool bSaved = FillSaveData( aPam, aTmpSav, false );
+        const bool bSaved = FillSaveData(aPam, aTmpSav, SwUndo::DelRange::Ignore);
 
         bool bOk = ( !pRedlSaveData && !bSaved ) ||
                    ( pRedlSaveData && bSaved &&
diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx
index 58d2de808363..9bdad5c20299 100644
--- a/sw/source/core/undo/unredln.cxx
+++ b/sw/source/core/undo/unredln.cxx
@@ -58,7 +58,8 @@ SwUndoRedline::SwUndoRedline( SwUndoId nUsrId, const SwPaM& rRange )
     sal_uLong nEndExtra = rDoc.GetNodes().GetEndOfExtras().GetIndex();
 
     mpRedlSaveData.reset( new SwRedlineSaveDatas );
-    if( !FillSaveData( rRange, *mpRedlSaveData, false, SwUndoId::REJECT_REDLINE != mnUserId ))
+    if (!FillSaveData(rRange, *mpRedlSaveData, SwUndo::DelRange::Ignore,
+                      SwUndoId::REJECT_REDLINE != mnUserId))
     {
         mpRedlSaveData.reset();
     }
@@ -118,7 +119,8 @@ void SwUndoRedline::RedoImpl(::sw::UndoRedoContext & rContext)
     if( mpRedlSaveData && mbHiddenRedlines )
     {
         sal_uLong nEndExtra = rDoc.GetNodes().GetEndOfExtras().GetIndex();
-        FillSaveData(rPam, *mpRedlSaveData, false, SwUndoId::REJECT_REDLINE != mnUserId );
+        FillSaveData(rPam, *mpRedlSaveData, SwUndo::DelRange::Ignore,
+                SwUndoId::REJECT_REDLINE != mnUserId);
 
         nEndExtra -= rDoc.GetNodes().GetEndOfExtras().GetIndex();
         nSttNode -= nEndExtra;
@@ -397,7 +399,7 @@ SwUndoCompDoc::SwUndoCompDoc( const SwRangeRedline& rRedl )
     }
 
     pRedlSaveData.reset( new SwRedlineSaveDatas );
-    if( !FillSaveData( rRedl, *pRedlSaveData, false ))
+    if (!FillSaveData( rRedl, *pRedlSaveData, SwUndo::DelRange::Ignore))
     {
         pRedlSaveData.reset();
     }
diff --git a/sw/source/core/undo/unsect.cxx b/sw/source/core/undo/unsect.cxx
index f17cae630316..b225ae42235e 100644
--- a/sw/source/core/undo/unsect.cxx
+++ b/sw/source/core/undo/unsect.cxx
@@ -88,7 +88,7 @@ SwUndoInsSection::SwUndoInsSection(
         SetRedlineFlags( rDoc.getIDocumentRedlineAccess().GetRedlineFlags() );
     }
         m_pRedlineSaveData.reset( new SwRedlineSaveDatas );
-        if( !FillSaveData( rPam, *m_pRedlineSaveData, false ))
+        if (!FillSaveData( rPam, *m_pRedlineSaveData, SwUndo::DelRange::Ignore))
             m_pRedlineSaveData.reset( nullptr );
 
     if( !rPam.HasMark() )
commit 584106543c8f85fa24ac311fcc5569e0fd6c87ae
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 22 12:56:33 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2: SwContentNode::DelFrames()
    
    ... needs to remove extents when it's called when moving nodes to
    Undo-nodes-array.
    
    Change-Id: I32cf38074d9f3d614d5f854979be6b0135d53914

diff --git a/sw/source/core/docnode/node.cxx b/sw/source/core/docnode/node.cxx
index 9175a1b076be..1cfdb934672d 100644
--- a/sw/source/core/docnode/node.cxx
+++ b/sw/source/core/docnode/node.cxx
@@ -1320,7 +1320,7 @@ void SwContentNode::MakeFramesForAdjacentContentNode(SwContentNode& rNode)
  * Deletes all Views from the Doc for this Node.
  * The ContentFrames are removed from the corresponding Layout.
  */
-void SwContentNode::DelFrames(SwRootFrame const*const pLayout, bool const fromDtor)
+void SwContentNode::DelFrames(SwRootFrame const*const pLayout, bool const)
 {
     if( !HasWriterListeners() )
         return;
@@ -1339,24 +1339,27 @@ void SwContentNode::DelFrames(SwRootFrame const*const pLayout, bool const fromDt
             {
                 if (this != pMerged->pFirstNode)
                 {
-                    if (fromDtor)
+                    // pointer should have been updated to a different node
+                    assert(this != pMerged->pParaPropsNode);
+                    // SwNodes::RemoveNode iterates *backwards* - so
+                    // ensure there are no more extents pointing to this
+                    // node as SwFrame::InvalidatePage() will access them.
+                    // Note: cannot send via SwClientNotify from dtor
+                    // because that would access deleted wrong-lists
+                    sw::UpdateMergedParaForDelete(*pMerged, true,
+                            *static_cast<SwTextNode*>(this), 0, Len());
+                    if (this == pMerged->pLastNode)
                     {
-                        // pointer should have been updated to a different node
-                        assert(this != pMerged->pParaPropsNode);
-                        // manual update required i'm afraid...
-                        if (this == pMerged->pLastNode)
-                        {
-                            pMerged->pLastNode = GetNodes()[GetIndex()-1]->GetTextNode();
-                            // at first glance nothing guarantees this...
-                            // but the redline must end on a text-node...
-                            // so everything before this node that isn't a text
-                            // node should have been deleted already so that
-                            // there's a text node before.
-                            assert(pMerged->pLastNode->IsTextNode());
-                        }
-                        // avoid re-parenting mess (ModifyChangedHint)
-                        pMerged->listener.EndListening(this);
+                        pMerged->pLastNode = GetNodes()[GetIndex()-1]->GetTextNode();
+                        // at first glance nothing guarantees this...
+                        // but the redline must end on a text-node...
+                        // so everything before this node that isn't a text
+                        // node should have been deleted already so that
+                        // there's a text node before.
+                        assert(pMerged->pLastNode->IsTextNode());
                     }
+                    // avoid re-parenting mess (ModifyChangedHint)
+                    pMerged->listener.EndListening(this);
                     continue; // don't delete
                 }
             }
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index def5fcff7ce9..028c3605aa50 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -101,6 +101,10 @@ std::unique_ptr<sw::MergedPara> CheckParaRedlineMerge(SwTextFrame & rFrame, SwTe
 
 bool FrameContainsNode(SwContentFrame const& rFrame, sal_uLong nNodeIndex);
 
+TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged,
+        bool isRealDelete,
+        SwTextNode const& rNode, sal_Int32 nIndex, sal_Int32 nLen);
+
 } // namespace sw
 
 /// Represents the visualization of a paragraph. Typical upper is an
commit e597ccdf301c47c63f62b0c9c9570d81d55ff9c3
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 22 12:52:13 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2: assert calls with wrong start node
    
    Change-Id: I132ea43397b8990c5759db66f62749df8aaa45d5

diff --git a/sw/source/core/text/redlnitr.cxx b/sw/source/core/text/redlnitr.cxx
index 975a412e98de..f63aed9f9e1b 100644
--- a/sw/source/core/text/redlnitr.cxx
+++ b/sw/source/core/text/redlnitr.cxx
@@ -78,6 +78,7 @@ CheckParaRedlineMerge(SwTextFrame & rFrame, SwTextNode & rTextNode,
         SwPosition const*const pEnd(pRed->End());
         assert(*pStart != *pEnd); // empty delete allowed if shown ???
         bHaveRedlines = true;
+        assert(pNode != &rTextNode || &pStart->nNode.GetNode() == &rTextNode); // detect calls with wrong start node
         if (pStart->nContent != nLastEnd) // not 0 so we eliminate adjacent deletes
         {
             extents.emplace_back(pNode, nLastEnd, pStart->nContent.GetIndex());
commit a8b1b6230a18b14d4af27defc6f312be15e73574
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Aug 22 12:39:54 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw: add a real create-no-frames flag to MakeCopy/MakeTextNode
    
    SwNodes::CopyNodes calling MakeCopy() and then immediately DelFrames()
    considered silly.
    
    Apparently SwOLENode/SwGrfNode don't actually create frames anyway since
    that is done via their SwFrameFormats, so they just ignore the parameter.
    
    Change-Id: I8a8f52da1d25bb5689345e956a33aebd727e8fc7

diff --git a/sw/inc/ndarr.hxx b/sw/inc/ndarr.hxx
index e9a3a7f11788..598397c43cf6 100644
--- a/sw/inc/ndarr.hxx
+++ b/sw/inc/ndarr.hxx
@@ -204,7 +204,8 @@ public:
 
     /// Implementations of "Make...Node" are in the given .cxx-files.
     SwTextNode *MakeTextNode( const SwNodeIndex & rWhere,
-                            SwTextFormatColl *pColl ); ///< in ndtxt.cxx
+                            SwTextFormatColl *pColl,
+                            bool bNewFrames = true); ///< in ndtxt.cxx
     SwStartNode* MakeTextSection( const SwNodeIndex & rWhere,
                             SwStartNodeType eSttNdTyp,
                             SwTextFormatColl *pColl );
diff --git a/sw/inc/ndgrf.hxx b/sw/inc/ndgrf.hxx
index 0a6c67a65481..998c414a879f 100644
--- a/sw/inc/ndgrf.hxx
+++ b/sw/inc/ndgrf.hxx
@@ -109,7 +109,7 @@ public:
     void SetScaleImageMap( bool b )      { bScaleImageMap = b; }
 
     /// in ndcopy.cxx
-    virtual SwContentNode* MakeCopy( SwDoc*, const SwNodeIndex& ) const override;
+    virtual SwContentNode* MakeCopy(SwDoc*, const SwNodeIndex&, bool bNewFrames) const override;
 
     /** Re-read in case graphic was not OK. The current one
        gets replaced by the new one. */
diff --git a/sw/inc/ndole.hxx b/sw/inc/ndole.hxx
index 93139c986526..21896f6f99c0 100644
--- a/sw/inc/ndole.hxx
+++ b/sw/inc/ndole.hxx
@@ -112,7 +112,7 @@ public:
     virtual ~SwOLENode() override;
 
     /// Is in ndcopy.cxx.
-    virtual SwContentNode* MakeCopy( SwDoc*, const SwNodeIndex& ) const override;
+    virtual SwContentNode* MakeCopy(SwDoc*, const SwNodeIndex&, bool bNewFrames) const override;
 
     virtual Size GetTwipSize() const override;
 
diff --git a/sw/inc/ndtxt.hxx b/sw/inc/ndtxt.hxx
index bfb9d0b3fe4a..2a5e48145cd8 100644
--- a/sw/inc/ndtxt.hxx
+++ b/sw/inc/ndtxt.hxx
@@ -669,7 +669,7 @@ public:
 
     /// in ndcopy.cxx
     bool IsSymbolAt(sal_Int32 nBegin) const; // In itratr.cxx.
-    virtual SwContentNode* MakeCopy( SwDoc*, const SwNodeIndex& ) const override;
+    virtual SwContentNode* MakeCopy(SwDoc*, const SwNodeIndex&, bool bNewFrames) const override;
 
     /// Interactive hyphenation: we find TextFrame and call its CalcHyph.
     bool Hyphenate( SwInterHyphInfo &rHyphInf );
diff --git a/sw/inc/node.hxx b/sw/inc/node.hxx
index 60149f2fc24a..05b69c9acb21 100644
--- a/sw/inc/node.hxx
+++ b/sw/inc/node.hxx
@@ -418,7 +418,7 @@ public:
        There are differences between text node and formula node. */
     virtual sal_Int32 Len() const;
 
-    virtual SwContentNode* MakeCopy( SwDoc*, const SwNodeIndex& ) const = 0;
+    virtual SwContentNode* MakeCopy(SwDoc*, const SwNodeIndex&, bool bNewFrames) const = 0;
 
     /// Get information from Client.
     virtual bool GetInfo( SfxPoolItem& ) const override;
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 58a4fe796c54..f6a2562983cd 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -4307,7 +4307,7 @@ bool DocumentContentOperationsManager::CopyImpl( SwPaM& rPam, SwPosition& rPos,
                             pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD));
                     else
                     {
-                        pDestTextNd = pSttTextNd->MakeCopy( pDoc, aInsPos )->GetTextNode();
+                        pDestTextNd = pSttTextNd->MakeCopy(pDoc, aInsPos, true)->GetTextNode();
                         bCopyOk = true;
                     }
                     aDestIdx.Assign( pDestTextNd, 0 );
diff --git a/sw/source/core/docnode/ndcopy.cxx b/sw/source/core/docnode/ndcopy.cxx
index 431a91e35055..5ec923298e7e 100644
--- a/sw/source/core/docnode/ndcopy.cxx
+++ b/sw/source/core/docnode/ndcopy.cxx
@@ -52,7 +52,7 @@ struct MapTableFrameFormat
 
 typedef std::vector<MapTableFrameFormat> MapTableFrameFormats;
 
-SwContentNode* SwTextNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
+SwContentNode* SwTextNode::MakeCopy(SwDoc* pDoc, const SwNodeIndex& rIdx, bool const bNewFrames) const
 {
     // the Copy-Textnode is the Node with the Text, the Copy-Attrnode is the
     // node with the collection and hard attributes. Normally is the same
@@ -75,7 +75,7 @@ SwContentNode* SwTextNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) cons
     if( !pColl )
         pColl = pDoc->CopyTextColl( *GetTextColl() );
 
-    SwTextNode* pTextNd = pDoc->GetNodes().MakeTextNode( rIdx, pColl );
+    SwTextNode* pTextNd = pDoc->GetNodes().MakeTextNode(rIdx, pColl, bNewFrames);
 
     // METADATA: register copy
     pTextNd->RegisterAsCopyOf(*pCpyTextNd);
diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx
index 4aa473c4308e..aed8aafbdaeb 100644
--- a/sw/source/core/docnode/nodes.cxx
+++ b/sw/source/core/docnode/nodes.cxx
@@ -1858,11 +1858,8 @@ void SwNodes::CopyNodes( const SwNodeRange& rRange,
         case SwNodeType::Grf:
         case SwNodeType::Ole:
             {
-                SwContentNode* pNew = static_cast<SwContentNode*>(pCurrentNode)->MakeCopy(
-                                            pDoc, aInsPos );
-                // frames are always created as default, so delete if needed
-                if( !bNewFrames )
-                    pNew->DelFrames(nullptr);
+                 static_cast<SwContentNode*>(pCurrentNode)->MakeCopy(
+                                            pDoc, aInsPos, bNewFrames);
             }
             break;
 
diff --git a/sw/source/core/graphic/ndgrf.cxx b/sw/source/core/graphic/ndgrf.cxx
index ccf2a54a34a5..d607928ad112 100644
--- a/sw/source/core/graphic/ndgrf.cxx
+++ b/sw/source/core/graphic/ndgrf.cxx
@@ -700,7 +700,7 @@ void SwGrfNode::ScaleImageMap()
     }
 }
 
-SwContentNode* SwGrfNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
+SwContentNode* SwGrfNode::MakeCopy(SwDoc* pDoc, const SwNodeIndex& rIdx, bool) const
 {
     // copy formats into the other document
     SwGrfFormatColl* pColl = pDoc->CopyGrfColl( *GetGrfColl() );
diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx
index 8d59c502817c..924a4db44904 100644
--- a/sw/source/core/ole/ndole.cxx
+++ b/sw/source/core/ole/ndole.cxx
@@ -407,7 +407,7 @@ Size SwOLENode::GetTwipSize() const
     return const_cast<SwOLENode*>(this)->maOLEObj.GetObject().GetSize( &aMapMode );
 }
 
-SwContentNode* SwOLENode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
+SwContentNode* SwOLENode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx, bool) const
 {
     // If there's already a SvPersist instance, we use it
     SfxObjectShell* pPersistShell = pDoc->GetPersist();
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index a3fac54bd8f3..defd89105380 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -112,7 +112,7 @@ typedef std::vector<SwTextAttr*> SwpHts;
 #endif
 
 SwTextNode *SwNodes::MakeTextNode( const SwNodeIndex & rWhere,
-                                 SwTextFormatColl *pColl )
+                                 SwTextFormatColl *pColl, bool const bNewFrames)
 {
     OSL_ENSURE( pColl, "Collection pointer is 0." );
 
@@ -126,7 +126,8 @@ SwTextNode *SwNodes::MakeTextNode( const SwNodeIndex & rWhere,
 
     // if there is no layout or it is in a hidden section, MakeFrames is not needed
     const SwSectionNode* pSectNd;
-    if( !GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell() ||
+    if (!bNewFrames ||
+        !GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell() ||
         ( nullptr != (pSectNd = pNode->FindSectionNode()) &&
             pSectNd->GetSection().IsHiddenFlag() ))
         return pNode;
commit d000643932dd6123a1bf81f4bf899cf759a201fa
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 21 15:42:26 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2: tiny optimisation in SwTextFrame::SwClientNotify()
    
    If there are no items left that affect the frame (which is hard to
    predict for merged frames, nCount only refers to the incoming item set),
    skip calling SwContentFrame::Modify().
    
    Change-Id: I10bdb6420bcff9b89e73b6d57ebb762aa43a0648

diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index f4c3200d3a1f..c8bdae109b06 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -2199,7 +2199,10 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
                         aOldSet.ClearItem( RES_PARATR_SPLIT );
                         aNewSet.ClearItem( RES_PARATR_SPLIT );
                     }
-                    SwContentFrame::Modify( &aOldSet, &aNewSet );
+                    if (aOldSet.Count() || aNewSet.Count())
+                    {
+                        SwContentFrame::Modify( &aOldSet, &aNewSet );
+                    }
                 }
                 else
                     SwContentFrame::Modify( pOld, pNew );
commit 3ffe4a6f13c0cffa506c9e8cbd2c3271ec12e7a4
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Aug 21 15:37:51 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    svl: fix SfxItemIter on empty item set
    
    The problem is that IsAtEnd { return m_nCurrent == m_nEnd; } is never
    true because of the odd initialisation with m_nEnd > m_nStart.
    
    Change-Id: I477b0f111e2c2f47fe093800710a9b28ca8a5925

diff --git a/svl/source/items/itemiter.cxx b/svl/source/items/itemiter.cxx
index 2cc6ae36212d..cbe0f2f8ed03 100644
--- a/svl/source/items/itemiter.cxx
+++ b/svl/source/items/itemiter.cxx
@@ -27,7 +27,7 @@ SfxItemIter::SfxItemIter( const SfxItemSet& rItemSet )
 {
     if (!m_rSet.m_nCount)
     {
-        m_nStart = 1;
+        m_nStart = 0;
         m_nEnd = 0;
     }
     else
commit 24f0ee13a4e112e5b464b874474af2e2d0b2287f
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Aug 20 17:24:18 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2, can have 0-length inserts from redlines
    
    Change-Id: I2f3df32c51af15b1d624e1457cdf7f021a546a09

diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 79b5081812f4..f4c3200d3a1f 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -727,10 +727,14 @@ TextFrameIndex UpdateMergedParaForInsert(MergedPara & rMerged,
         bool const isRealInsert,
         SwTextNode const& rNode, sal_Int32 const nIndex, sal_Int32 const nLen)
 {
-    assert(nLen); // can 0 happen?
+    assert(!isRealInsert || nLen); // can 0 happen? yes, for redline in empty node
     assert(nIndex <= rNode.Len());
     assert(nIndex + nLen <= rNode.Len());
     assert(rMerged.pFirstNode->GetIndex() <= rNode.GetIndex() && rNode.GetIndex() <= rMerged.pLastNode->GetIndex());
+    if (!nLen)
+    {
+        return TextFrameIndex(0);
+    }
     OUStringBuffer text(rMerged.mergedText);
     sal_Int32 nTFIndex(0);
     sal_Int32 nInserted(0);
commit eb5e0dfed1428573838be130d0304bcb5bfd842e
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Aug 20 17:21:36 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw: fix listener registration of sw::UnoCursorPointer
    
    Listening at one SwUnoCursor at a time is enough; this triggers
    asserts added in 1925a57dee73933ffbdb3b57349b757470a8218a from
    SwNavigationMgr.
    
    Change-Id: I791355533214daeb1779cd7d1a6aac7faa1a1472

diff --git a/sw/inc/unocrsr.hxx b/sw/inc/unocrsr.hxx
index 01ea1112cc5d..d2eaa7829007 100644
--- a/sw/inc/unocrsr.hxx
+++ b/sw/inc/unocrsr.hxx
@@ -144,6 +144,10 @@ namespace sw
                 { return *get(); }
             UnoCursorPointer& operator=(UnoCursorPointer aOther)
             {
+                if (m_pCursor)
+                {
+                    EndListening(m_pCursor->m_aNotifier);
+                }
                 if(aOther.m_pCursor)
                     StartListening(aOther.m_pCursor->m_aNotifier);
                 m_pCursor = aOther.m_pCursor;
@@ -155,7 +159,7 @@ namespace sw
             {
                 if(pNew)
                     StartListening(pNew->m_aNotifier);
-                else if(m_pCursor)
+                if (m_pCursor)
                     EndListening(m_pCursor->m_aNotifier);
                 m_pCursor = pNew;
             }
commit 77ae9c0878797de5bbacffa60ff91d58d10d2953
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 17 18:57:37 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2: quite the nuisance when it happens, better assert
    
    Change-Id: I5cef7c2cea41a5b246268a541afd47945603ffed

diff --git a/sw/source/core/layout/ftnfrm.cxx b/sw/source/core/layout/ftnfrm.cxx
index b82f23e56198..3c475defe980 100644
--- a/sw/source/core/layout/ftnfrm.cxx
+++ b/sw/source/core/layout/ftnfrm.cxx
@@ -2821,6 +2821,8 @@ SwContentFrame* SwFootnoteFrame::GetRef()
     SAL_WARN_IF( mpReference != pRefAttr && !mpReference->IsAnFollow( pRefAttr )
             && !pRefAttr->IsAnFollow( mpReference ),
             "sw.core", "access to deleted Frame? pRef != pAttr->GetRef()" );
+    assert(mpReference == pRefAttr || mpReference->IsAnFollow(pRefAttr)
+            || pRefAttr->IsAnFollow(mpReference));
     return mpReference;
 }
 #endif
commit 42539e3ae4b549ef734d6915d4f9a5e3a2315d82
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 17 18:56:30 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2: fix wrong assertion
    
    Change-Id: I8b00f406ae52c3280f9ec07c845ef7aa6e41617f

diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index f52f336ad376..79b5081812f4 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -935,7 +935,7 @@ TextFrameIndex UpdateMergedParaForDelete(MergedPara & rMerged,
         }
     }
 //    assert(nFoundNode != 0 && "text node not found - why is it sending hints to us");
-    assert(nIndex - nDeleted <= rNode.Len());
+    assert(nIndex <= rNode.Len() + nLen);
     // if there's a remaining deletion, it must be in gap at the end of the node
 // can't do: might be last one in node was erased   assert(nLen == 0 || rMerged.empty() || (it-1)->nEnd <= nIndex);
     // note: if first node gets deleted then that must call DelFrames as
commit 03b4aa9ee470a1e03c04786666569ffd68cb20da
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 17 18:54:39 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2: invalidate more in DocumentRedlineManager::DeleteRedline
    
    To get the extents right, first invalidate old range with Remove,
    then new range with Add.
    
    Change-Id: If46954b9bb86680ae689de742ec878e0287f58d9

diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx
index 81b858cf5ee9..ad9c292810a1 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -1968,6 +1968,7 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd
         case SwComparePosition::OverlapBefore:
                 pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
                 pRedl->SetStart( *pEnd, pRStt );
+                pRedl->InvalidateRange(SwRangeRedline::Invalidation::Add);
                 // re-insert
                 mpRedlineTable->Remove( n );
                 mpRedlineTable->Insert( pRedl );
@@ -1977,6 +1978,7 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd
         case SwComparePosition::OverlapBehind:
                 pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
                 pRedl->SetEnd( *pStt, pREnd );
+                pRedl->InvalidateRange(SwRangeRedline::Invalidation::Add);
                 if( !pRedl->HasValidRange() )
                 {
                     // re-insert
@@ -1993,6 +1995,7 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd
                 if( *pRStt == *pStt )
                 {
                     pRedl->SetStart( *pEnd, pRStt );
+                    pRedl->InvalidateRange(SwRangeRedline::Invalidation::Add);
                     // re-insert
                     mpRedlineTable->Remove( n );
                     mpRedlineTable->Insert( pRedl );
@@ -2005,10 +2008,12 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd
                     {
                         pCpy = new SwRangeRedline( *pRedl );
                         pCpy->SetStart( *pEnd );
+                        pCpy->InvalidateRange(SwRangeRedline::Invalidation::Add);
                     }
                     else
                         pCpy = nullptr;
                     pRedl->SetEnd( *pStt, pREnd );
+                    pRedl->InvalidateRange(SwRangeRedline::Invalidation::Add);
                     if( !pRedl->HasValidRange() )
                     {
                         // re-insert
commit f7ae7d8d9d908824a9bbce8841a01c1ececede54
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Aug 17 17:52:52 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2: invalidate when delete redline goes away
    
    Add another new hint sw::RedlineUnDelText; the main use case is to send
    it from  DocumentRedlineManager::DeleteRedline() so the view is updated
    accordingly.
    
    Change-Id: Ia490116588dc8d3c695ec83c0c2ce8497736f76e

diff --git a/sw/inc/hints.hxx b/sw/inc/hints.hxx
index dc31d7424756..bee0ebb1c21a 100644
--- a/sw/inc/hints.hxx
+++ b/sw/inc/hints.hxx
@@ -95,6 +95,7 @@ public:
 
 namespace sw {
 
+/// new delete redline is created
 class RedlineDelText : public SfxHint
 {
 public:
@@ -104,6 +105,16 @@ public:
     RedlineDelText(sal_Int32 nS, sal_Int32 nL);
 };
 
+/// delete redline is removed
+class RedlineUnDelText : public SfxHint
+{
+public:
+    sal_Int32 nStart;
+    sal_Int32 nLen;
+
+    RedlineUnDelText(sal_Int32 nS, sal_Int32 nL);
+};
+
 }
 
 class SwUpdateAttr : public SwMsgPoolItem
diff --git a/sw/inc/redline.hxx b/sw/inc/redline.hxx
index cde78e743b0b..40d8377fcb54 100644
--- a/sw/inc/redline.hxx
+++ b/sw/inc/redline.hxx
@@ -253,8 +253,9 @@ public:
     /// Calculates the intersection with text node number nNdIdx.
     void CalcStartEnd(sal_uLong nNdIdx, sal_Int32& rStart, sal_Int32& rEnd) const;
 
+    enum class Invalidation { Add, Remove };
     /// Initiate the layout.
-    void InvalidateRange();
+    void InvalidateRange(Invalidation);
 
     bool IsOwnRedline( const SwRangeRedline& rRedl ) const
         { return GetAuthor() == rRedl.GetAuthor(); }
diff --git a/sw/source/core/attr/hints.cxx b/sw/source/core/attr/hints.cxx
index 44c60ff0fd17..7c1ff2a40aec 100644
--- a/sw/source/core/attr/hints.cxx
+++ b/sw/source/core/attr/hints.cxx
@@ -53,6 +53,11 @@ RedlineDelText::RedlineDelText(sal_Int32 const nS, sal_Int32 const nL)
 {
 }
 
+RedlineUnDelText::RedlineUnDelText(sal_Int32 const nS, sal_Int32 const nL)
+    : nStart(nS), nLen(nL)
+{
+}
+
 } // namespace sw
 
 SwUpdateAttr::SwUpdateAttr( sal_Int32 nS, sal_Int32 nE, sal_uInt16 nW )
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx
index c056c1c7a113..81b858cf5ee9 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -140,7 +140,7 @@ namespace
             eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
         }
 
-        pRedl->InvalidateRange();
+        pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
 
         switch( pRedl->GetType() )
         {
@@ -303,7 +303,7 @@ namespace
             eCmp = ComparePosition( *pSttRng, *pEndRng, *pRStt, *pREnd );
         }
 
-        pRedl->InvalidateRange();
+        pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
 
         switch( pRedl->GetType() )
         {
@@ -784,7 +784,7 @@ DocumentRedlineManager::AppendRedline(SwRangeRedline* pNewRedl, bool const bCall
 
     if (IsRedlineOn() && !IsShowOriginal(meRedlineFlags))
     {
-        pNewRedl->InvalidateRange();
+        pNewRedl->InvalidateRange(SwRangeRedline::Invalidation::Add);
 
         if( m_rDoc.IsAutoFormatRedline() )
         {
@@ -1900,7 +1900,7 @@ bool DocumentRedlineManager::SplitRedline( const SwPaM& rRange )
                 break;
 
             case 3:
-                pRedline->InvalidateRange();
+                pRedline->InvalidateRange(SwRangeRedline::Invalidation::Remove);
                 mpRedlineTable->DeleteAndDestroy( n-- );
                 pRedline = nullptr;
                 break;
@@ -1960,13 +1960,13 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd
         {
         case SwComparePosition::Equal:
         case SwComparePosition::Outside:
-            pRedl->InvalidateRange();
+            pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
             mpRedlineTable->DeleteAndDestroy( n-- );
             bChg = true;
             break;
 
         case SwComparePosition::OverlapBefore:
-                pRedl->InvalidateRange();
+                pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
                 pRedl->SetStart( *pEnd, pRStt );
                 // re-insert
                 mpRedlineTable->Remove( n );
@@ -1975,7 +1975,7 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd
             break;
 
         case SwComparePosition::OverlapBehind:
-                pRedl->InvalidateRange();
+                pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
                 pRedl->SetEnd( *pStt, pREnd );
                 if( !pRedl->HasValidRange() )
                 {
@@ -1989,7 +1989,7 @@ bool DocumentRedlineManager::DeleteRedline( const SwPaM& rRange, bool bSaveInUnd
         case SwComparePosition::Inside:
             {
                 // this one needs to be splitted
-                pRedl->InvalidateRange();
+                pRedl->InvalidateRange(SwRangeRedline::Invalidation::Remove);
                 if( *pRStt == *pStt )
                 {
                     pRedl->SetStart( *pEnd, pRStt );
@@ -2687,7 +2687,7 @@ void DocumentRedlineManager::UpdateRedlineAttr()
     for(SwRangeRedline* pRedl : rTable)
     {
         if( pRedl->IsVisible() )
-            pRedl->InvalidateRange();
+            pRedl->InvalidateRange(SwRangeRedline::Invalidation::Add);
     }
 
     // #TODO - add 'SwExtraRedlineTable' also ?
diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
index 0947b6a0cbfd..950526187efc 100644
--- a/sw/source/core/doc/docredln.cxx
+++ b/sw/source/core/doc/docredln.cxx
@@ -1162,7 +1162,7 @@ void SwRangeRedline::Show(sal_uInt16 nLoop, size_t nMyPos)
 
         case nsRedlineType_t::REDLINE_FORMAT:           // Attributes have been applied
         case nsRedlineType_t::REDLINE_TABLE:            // Table structure has been modified
-            InvalidateRange();
+            InvalidateRange(Invalidation::Add);
             break;
         default:
             break;
@@ -1199,7 +1199,7 @@ void SwRangeRedline::Hide(sal_uInt16 nLoop, size_t nMyPos)
     case nsRedlineType_t::REDLINE_FORMAT:           // Attributes have been applied
     case nsRedlineType_t::REDLINE_TABLE:            // Table structure has been modified
         if( 1 <= nLoop )
-            InvalidateRange();
+            InvalidateRange(Invalidation::Remove);
         break;
     default:
         break;
@@ -1241,7 +1241,7 @@ void SwRangeRedline::ShowOriginal(sal_uInt16 nLoop, size_t nMyPos)
     case nsRedlineType_t::REDLINE_FORMAT:           // Attributes have been applied
     case nsRedlineType_t::REDLINE_TABLE:            // Table structure has been modified
         if( 1 <= nLoop )
-            InvalidateRange();
+            InvalidateRange(Invalidation::Remove);
         break;
     default:
         break;
@@ -1249,7 +1249,8 @@ void SwRangeRedline::ShowOriginal(sal_uInt16 nLoop, size_t nMyPos)
     pDoc->getIDocumentRedlineAccess().SetRedlineFlags_intern( eOld );
 }
 
-void SwRangeRedline::InvalidateRange()       // trigger the Layout
+// trigger the Layout
+void SwRangeRedline::InvalidateRange(Invalidation const eWhy)
 {
     sal_uLong nSttNd = GetMark()->nNode.GetIndex(),
             nEndNd = GetPoint()->nNode.GetIndex();
@@ -1282,9 +1283,17 @@ void SwRangeRedline::InvalidateRange()       // trigger the Layout
             if (GetType() == nsRedlineType_t::REDLINE_DELETE)
             {
                 sal_Int32 const nStart(n == nSttNd ? nSttCnt : 0);
-                sw::RedlineDelText const hint(nStart,
-                    (n == nEndNd ? nEndCnt : pNd->GetText().getLength()) - nStart);
-                pNd->CallSwClientNotify(hint);
+                sal_Int32 const nLen((n == nEndNd ? nEndCnt : pNd->GetText().getLength()) - nStart);
+                if (eWhy == Invalidation::Add)
+                {
+                    sw::RedlineDelText const hint(nStart, nLen);
+                    pNd->CallSwClientNotify(hint);
+                }
+                else
+                {
+                    sw::RedlineUnDelText const hint(nStart, nLen);
+                    pNd->CallSwClientNotify(hint);
+                }
             }
         }
     }
@@ -1396,7 +1405,7 @@ void SwRangeRedline::MoveToSection()
         DeleteMark();
     }
     else
-        InvalidateRange();
+        InvalidateRange(Invalidation::Remove);
 }
 
 void SwRangeRedline::CopyToSection()
@@ -1676,7 +1685,7 @@ void SwRangeRedline::MoveFromSection(size_t nMyPos)
             *pItem = *End();
     }
     else
-        InvalidateRange();
+        InvalidateRange(Invalidation::Add);
 }
 
 // for Undo
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index 8bb1b0407f72..bcea7f789905 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -4480,7 +4480,7 @@ void SwRootFrame::SetHideRedlines(bool const bHideRedlines)
         // trigger repaint of text frames to add/remove the redline color font
         if (pRedline->GetType() != nsRedlineType_t::REDLINE_DELETE)
         {
-            pRedline->InvalidateRange();
+            pRedline->InvalidateRange(SwRangeRedline::Invalidation::Add);
         }
     }
 
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index c38af1cfa2ba..f52f336ad376 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -721,7 +721,10 @@ SwTextFrame::~SwTextFrame()
 
 namespace sw {
 
-void UpdateMergedParaForInsert(MergedPara & rMerged,
+// 1. if real insert => correct nStart/nEnd for full nLen
+// 2. if rl un-delete => do not correct nStart/nEnd but just include un-deleted
+TextFrameIndex UpdateMergedParaForInsert(MergedPara & rMerged,
+        bool const isRealInsert,
         SwTextNode const& rNode, sal_Int32 const nIndex, sal_Int32 const nLen)
 {
     assert(nLen); // can 0 happen?
@@ -730,6 +733,7 @@ void UpdateMergedParaForInsert(MergedPara & rMerged,
     assert(rMerged.pFirstNode->GetIndex() <= rNode.GetIndex() && rNode.GetIndex() <= rMerged.pLastNode->GetIndex());
     OUStringBuffer text(rMerged.mergedText);
     sal_Int32 nTFIndex(0);
+    sal_Int32 nInserted(0);
     bool bInserted(false);
     bool bFoundNode(false);
     auto itInsert(rMerged.extents.end());
@@ -737,22 +741,75 @@ void UpdateMergedParaForInsert(MergedPara & rMerged,
     {
         if (it->pNode == &rNode)
         {
-            bFoundNode = true;
-            if (it->nStart <= nIndex && nIndex <= it->nEnd)
-            {   // note: this can happen only once
-                text.insert(nTFIndex + (nIndex - it->nStart),
-                        rNode.GetText().copy(nIndex, nLen));
-                it->nEnd += nLen;
-                bInserted = true;
+            if (isRealInsert)
+            {
+                bFoundNode = true;
+                if (it->nStart <= nIndex && nIndex <= it->nEnd)
+                {   // note: this can happen only once
+                    text.insert(nTFIndex + (nIndex - it->nStart),
+                            rNode.GetText().copy(nIndex, nLen));
+                    it->nEnd += nLen;
+                    nInserted = nLen;
+                    assert(!bInserted);
+                    bInserted = true;
+                }
+                else if (nIndex < it->nStart)
+                {
+                    if (itInsert == rMerged.extents.end())
+                    {
+                        itInsert = it;
+                    }
+                    it->nStart += nLen;
+                    it->nEnd += nLen;
+                }
             }
-            else if (nIndex < it->nStart)
+            else
             {
-                if (itInsert == rMerged.extents.end())
+                assert(it == rMerged.extents.begin() || (it-1)->pNode != &rNode || (it-1)->nEnd < nIndex);
+                if (nIndex + nLen < it->nStart)
                 {
                     itInsert = it;
+                    break;
+                }
+                if (nIndex < it->nStart)
+                {
+                    text.insert(nTFIndex,
+                        rNode.GetText().copy(nIndex, it->nStart - nIndex));
+                    nInserted += it->nStart - nIndex;
+                    it->nStart = nIndex;
+                    bInserted = true;
+                }
+                assert(it->nStart <= nIndex);
+                if (nIndex <= it->nEnd)
+                {
+                    nTFIndex += it->nEnd - it->nStart;
+                    while (it->nEnd < nIndex + nLen)
+                    {
+                        auto *const pNext(
+                            (it+1) != rMerged.extents.end() && (it+1)->pNode == it->pNode
+                                ? &*(it+1)
+                                : nullptr);
+                        if (pNext && pNext->nStart <= nIndex + nLen)
+                        {
+                            text.insert(nTFIndex,
+                                rNode.GetText().copy(it->nEnd, pNext->nStart - it->nEnd));
+                            nTFIndex += pNext->nStart - it->nEnd;
+                            nInserted += pNext->nStart - it->nEnd;
+                            pNext->nStart = it->nStart;
+                            it = rMerged.extents.erase(it);
+                        }
+                        else
+                        {
+                            text.insert(nTFIndex,
+                                rNode.GetText().copy(it->nEnd, nIndex + nLen - it->nEnd));
+                            nTFIndex += nIndex + nLen - it->nEnd;
+                            nInserted += nIndex + nLen - it->nEnd;
+                            it->nEnd = nIndex + nLen;
+                        }
+                    }
+                    bInserted = true;
+                    break;
                 }
-                it->nStart += nLen;
-                it->nEnd += nLen;
             }
         }
         else if (rNode.GetIndex() < it->pNode->GetIndex() || bFoundNode)
@@ -767,12 +824,14 @@ void UpdateMergedParaForInsert(MergedPara & rMerged,
     {   // must be in a gap
         rMerged.extents.emplace(itInsert, const_cast<SwTextNode*>(&rNode), nIndex, nIndex + nLen);
         text.insert(nTFIndex, rNode.GetText().copy(nIndex, nLen));
+        nInserted = nLen;
         if (rNode.GetIndex() < rMerged.pParaPropsNode->GetIndex())
         {   // text inserted before current para-props node
             rMerged.pParaPropsNode = &rNode;
         }
     }
     rMerged.mergedText = text.makeStringAndClear();
+    return TextFrameIndex(nInserted);
 }
 
 // 1. if real delete => correct nStart/nEnd for full nLen
@@ -1613,6 +1672,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
     SfxPoolItem const* pOld(nullptr);
     SfxPoolItem const* pNew(nullptr);
     sw::RedlineDelText const* pRedlineDelText(nullptr);
+    sw::RedlineUnDelText const* pRedlineUnDelText(nullptr);
 
     if (auto const pHint = dynamic_cast<sw::LegacyModifyHint const*>(&rHint))
     {
@@ -1623,6 +1683,10 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
     {
         pRedlineDelText = pHynt;
     }
+    else if (auto const pHnt = dynamic_cast<sw::RedlineUnDelText const*>(&rHint))
+    {
+        pRedlineUnDelText = pHnt;
+    }
     else
     {
         assert(!"unexpected hint");
@@ -1709,6 +1773,34 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
             }
         }
     }
+    else if (pRedlineUnDelText)
+    {
+        if (m_pMergedPara)
+        {
+            sal_Int32 const nNPos = pRedlineUnDelText->nStart;
+            sal_Int32 const nNLen = pRedlineUnDelText->nLen;
+            nPos = MapModelToView(&rNode, nNPos);
+            nLen = UpdateMergedParaForInsert(*m_pMergedPara, false, rNode, nNPos, nNLen);
+            if (IsIdxInside(nPos, nLen))
+            {
+                if (!nLen)
+                {
+                    // Refresh NumPortions even when line is empty!
+                    if (nPos)
+                        InvalidateSize();
+                    else
+                        Prepare();
+                }
+                else
+                    InvalidateRange_( SwCharRange( nPos, nLen ), nNLen );
+            }
+            lcl_SetWrong( *this, rNode, nNPos, nNLen, true );
+            lcl_SetScriptInval( *this, nPos );
+            bSetFieldsDirty = true;
+            if (HasFollow())
+                lcl_ModifyOfst( this, nPos, nLen );
+        }
+    }
     else switch (nWhich)
     {
         case RES_LINENUMBER:
@@ -1725,7 +1817,7 @@ void SwTextFrame::SwClientNotify(SwModify const& rModify, SfxHint const& rHint)
             nLen = TextFrameIndex(nNLen);
             if (m_pMergedPara)
             {
-                UpdateMergedParaForInsert(*m_pMergedPara, rNode, nNPos, nNLen);
+                UpdateMergedParaForInsert(*m_pMergedPara, true, rNode, nNPos, nNLen);
             }
             if( IsIdxInside( nPos, nLen ) )
             {
diff --git a/sw/source/core/undo/unredln.cxx b/sw/source/core/undo/unredln.cxx
index 5a7334beb7ac..58d2de808363 100644
--- a/sw/source/core/undo/unredln.cxx
+++ b/sw/source/core/undo/unredln.cxx
@@ -486,7 +486,7 @@ void SwUndoCompDoc::RedoImpl(::sw::UndoRedoContext & rContext)
         {
             SwRangeRedline* pTmp = new SwRangeRedline(*pRedlData, rPam);
             rDoc.getIDocumentRedlineAccess().GetRedlineTable().Insert( pTmp );
-            pTmp->InvalidateRange();
+            pTmp->InvalidateRange(SwRangeRedline::Invalidation::Add);
         }
         else if( !( RedlineFlags::Ignore & GetRedlineFlags() ) &&
                 !rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty() )
@@ -510,7 +510,7 @@ void SwUndoCompDoc::RedoImpl(::sw::UndoRedoContext & rContext)
 
         SwRangeRedline* pTmp = new SwRangeRedline(*pRedlData, rPam);
         rDoc.getIDocumentRedlineAccess().GetRedlineTable().Insert( pTmp );
-        pTmp->InvalidateRange();
+        pTmp->InvalidateRange(SwRangeRedline::Invalidation::Add);
 
         SetPaM(rPam, true);
     }
commit e663af18b46eda51ed0b7c14bb55c7100f8df4ff
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Aug 16 18:59:10 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Thu Aug 30 17:40:08 2018 +0200

    sw_redlinehide_2: force SwAttrIter::GetNextAttr to make progress
    
    ... and skip over the redline if the start position is at the beginning
    of it.
    
    Change-Id: Ib12b459b12d49e1443257ce398963ab3ec64f2a5

diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx
index 82bdc5910d1b..4134c73f1b90 100644
--- a/sw/source/core/text/itratr.cxx
+++ b/sw/source/core/text/itratr.cxx
@@ -442,7 +442,8 @@ static void InsertCharAttrs(SfxPoolItem const** pAttrs, SfxItemSet const& rItems
 // if return false: portion ends at start of redline, indexes unchanged

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list