[Libreoffice-commits] core.git: Branch 'libreoffice-6-2' - 29 commits - sw/inc sw/qa sw/source sw/uiconfig sw/UIConfig_swriter.mk xmloff/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Tue Dec 18 21:32:29 UTC 2018


 sw/UIConfig_swriter.mk                                  |    1 
 sw/inc/crsrsh.hxx                                       |   21 
 sw/inc/editsh.hxx                                       |    2 
 sw/inc/pam.hxx                                          |   31 
 sw/inc/postithelper.hxx                                 |    5 
 sw/inc/reffld.hxx                                       |    3 
 sw/inc/swcrsr.hxx                                       |   21 
 sw/inc/txtftn.hxx                                       |    4 
 sw/qa/core/macros-test.cxx                              |    4 
 sw/qa/extras/uiwriter/uiwriter.cxx                      |    3 
 sw/qa/unit/data/sw-dialogs-test.txt                     |    1 
 sw/qa/unit/data/sw-dialogs-test_2.txt                   |    1 
 sw/source/core/crsr/crbm.cxx                            |   59 +
 sw/source/core/crsr/crsrsh.cxx                          |   16 
 sw/source/core/crsr/crstrvl.cxx                         |   12 
 sw/source/core/crsr/findattr.cxx                        |  302 +++++-
 sw/source/core/crsr/findcoll.cxx                        |   27 
 sw/source/core/crsr/findfmt.cxx                         |   45 
 sw/source/core/crsr/findtxt.cxx                         |  737 +++++++++++-----
 sw/source/core/crsr/pam.cxx                             |   40 
 sw/source/core/crsr/swcrsr.cxx                          |    9 
 sw/source/core/doc/DocumentContentOperationsManager.cxx |   25 
 sw/source/core/doc/DocumentRedlineManager.cxx           |  186 ++--
 sw/source/core/doc/docnum.cxx                           |   67 +
 sw/source/core/edit/acorrect.cxx                        |    2 
 sw/source/core/edit/autofmt.cxx                         |   11 
 sw/source/core/edit/eddel.cxx                           |    4 
 sw/source/core/edit/edfld.cxx                           |    9 
 sw/source/core/edit/editsh.cxx                          |   12 
 sw/source/core/edit/edtox.cxx                           |    2 
 sw/source/core/fields/postithelper.cxx                  |    8 
 sw/source/core/fields/reffld.cxx                        |   53 +
 sw/source/core/inc/DocumentRedlineManager.hxx           |    3 
 sw/source/core/inc/acorrect.hxx                         |   10 
 sw/source/core/inc/ftnfrm.hxx                           |    4 
 sw/source/core/inc/pamtyp.hxx                           |   39 
 sw/source/core/inc/txtfrm.hxx                           |    4 
 sw/source/core/layout/frmtool.cxx                       |   36 
 sw/source/core/layout/wsfrm.cxx                         |   40 
 sw/source/core/text/EnhancedPDFExportHelper.cxx         |   22 
 sw/source/core/text/frmcrsr.cxx                         |    1 
 sw/source/core/text/itratr.cxx                          |   44 
 sw/source/core/text/itratr.hxx                          |    3 
 sw/source/core/text/redlnitr.cxx                        |   56 -
 sw/source/core/text/txtdrop.cxx                         |    3 
 sw/source/core/text/txtfrm.cxx                          |   36 
 sw/source/core/txtnode/atrftn.cxx                       |    3 
 sw/source/core/txtnode/ndtxt.cxx                        |    7 
 sw/source/core/undo/undel.cxx                           |    4 
 sw/source/filter/xml/XMLRedlineImportHelper.cxx         |   31 
 sw/source/filter/xml/swxml.cxx                          |   13 
 sw/source/filter/xml/wrtxml.cxx                         |   27 
 sw/source/filter/xml/xmlexp.cxx                         |    5 
 sw/source/ui/fldui/DropDownFieldDialog.cxx              |    2 
 sw/source/ui/fldui/fldedt.cxx                           |    2 
 sw/source/ui/fldui/inpdlg.cxx                           |    4 
 sw/source/ui/index/swuiidxmrk.cxx                       |    2 
 sw/source/uibase/docvw/PostItMgr.cxx                    |   18 
 sw/source/uibase/fldui/fldmgr.cxx                       |    4 
 sw/source/uibase/inc/wrtsh.hxx                          |    2 
 sw/source/uibase/uiview/view2.cxx                       |   21 
 sw/source/uibase/uiview/viewsrch.cxx                    |    3 
 sw/source/uibase/uiview/viewstat.cxx                    |    7 
 sw/source/uibase/uno/unotxdoc.cxx                       |   12 
 sw/source/uibase/wrtsh/move.cxx                         |    3 
 sw/source/uibase/wrtsh/select.cxx                       |    6 
 sw/uiconfig/swriter/ui/queryshowchangesdialog.ui        |   35 
 xmloff/source/core/xmlimp.cxx                           |    1 
 68 files changed, 1533 insertions(+), 703 deletions(-)

New commits:
commit 7009749668311016c4e875e473bb8dc0da210022
Author:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
AuthorDate: Tue Dec 18 00:36:24 2018 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Tue Dec 18 22:30:17 2018 +0100

    sw_redlinehide: fix tdf#113479 by removing nag dialog
    
    No need to suggest showing redlines beyond 250 changes anymore.
    
    Change-Id: Ia219a4eb3af64079979538b8ab4aaf2a94ec19c8
    Reviewed-on: https://gerrit.libreoffice.org/65294
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <Michael.Stahl at cib.de>
    (cherry picked from commit 866f10e75ddcd9dcfa327d02f587a1f322e6b6b5)

diff --git a/sw/UIConfig_swriter.mk b/sw/UIConfig_swriter.mk
index 37dffed460ed..bba8c908e805 100644
--- a/sw/UIConfig_swriter.mk
+++ b/sw/UIConfig_swriter.mk
@@ -198,7 +198,6 @@ $(eval $(call gb_UIConfig_add_uifiles,modules/swriter,\
 	sw/uiconfig/swriter/ui/queryredlinedialog \
 	sw/uiconfig/swriter/ui/queryrotateintostandarddialog \
 	sw/uiconfig/swriter/ui/querysavelabeldialog \
-	sw/uiconfig/swriter/ui/queryshowchangesdialog \
 	sw/uiconfig/swriter/ui/mailmerge \
 	sw/uiconfig/swriter/ui/managechangessidebar \
 	sw/uiconfig/swriter/ui/mmaddressblockpage \
diff --git a/sw/qa/unit/data/sw-dialogs-test.txt b/sw/qa/unit/data/sw-dialogs-test.txt
index 931a40c09c28..54fa2761b575 100644
--- a/sw/qa/unit/data/sw-dialogs-test.txt
+++ b/sw/qa/unit/data/sw-dialogs-test.txt
@@ -163,7 +163,6 @@ modules/swriter/ui/querycontinueenddialog.ui
 modules/swriter/ui/querydefaultcompatdialog.ui
 modules/swriter/ui/queryrotateintostandarddialog.ui
 modules/swriter/ui/querysavelabeldialog.ui
-modules/swriter/ui/queryshowchangesdialog.ui
 modules/swriter/ui/renameautotextdialog.ui
 modules/swriter/ui/renameentrydialog.ui
 modules/swriter/ui/renameobjectdialog.ui
diff --git a/sw/qa/unit/data/sw-dialogs-test_2.txt b/sw/qa/unit/data/sw-dialogs-test_2.txt
index 797c410136dd..a36bbdca3dae 100644
--- a/sw/qa/unit/data/sw-dialogs-test_2.txt
+++ b/sw/qa/unit/data/sw-dialogs-test_2.txt
@@ -32,7 +32,6 @@ modules/swriter/ui/querycontinueenddialog.ui
 modules/swriter/ui/querydefaultcompatdialog.ui
 modules/swriter/ui/queryrotateintostandarddialog.ui
 modules/swriter/ui/querysavelabeldialog.ui
-modules/swriter/ui/queryshowchangesdialog.ui
 modules/swriter/ui/renameautotextdialog.ui
 modules/swriter/ui/renameentrydialog.ui
 modules/swriter/ui/renameobjectdialog.ui
diff --git a/sw/source/core/doc/DocumentRedlineManager.cxx b/sw/source/core/doc/DocumentRedlineManager.cxx
index a15c29e50937..7d79a3f1a233 100644
--- a/sw/source/core/doc/DocumentRedlineManager.cxx
+++ b/sw/source/core/doc/DocumentRedlineManager.cxx
@@ -800,7 +800,6 @@ DocumentRedlineManager::DocumentRedlineManager(SwDoc& i_rSwdoc)
     , mpRedlineTable(new SwRedlineTable)
     , mpExtraRedlineTable(new SwExtraRedlineTable)
     , mbIsRedlineMove(false)
-    , mbReadlineChecked(false)
     , mnAutoFormatRedlnCommentNo(0)
 {
 }
@@ -2982,27 +2981,6 @@ void DocumentRedlineManager::SetAutoFormatRedlineComment( const OUString* pText,
     mnAutoFormatRedlnCommentNo = nSeqNo;
 }
 
-#define MAX_REDLINE_COUNT   250
-
-void DocumentRedlineManager::checkRedlining(RedlineFlags& _rReadlineMode)
-{
-    const SwRedlineTable& rRedlineTable = GetRedlineTable();
-    SwEditShell* pEditShell = m_rDoc.GetEditShell();
-    vcl::Window* pParent = pEditShell ? pEditShell->GetWin() : nullptr;
-    if ( pParent && !mbReadlineChecked && rRedlineTable.size() > MAX_REDLINE_COUNT
-        && ((_rReadlineMode & RedlineFlags::ShowDelete) != RedlineFlags::ShowDelete) )
-    {
-        std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pParent->GetFrameWeld(), "modules/swriter/ui/queryshowchangesdialog.ui"));
-        std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("QueryShowChangesDialog"));
-        sal_uInt16 nResult = xQuery->run();
-        mbReadlineChecked = true;
-        if ( nResult == RET_YES )
-        {
-            _rReadlineMode |= RedlineFlags::ShowInsert | RedlineFlags::ShowDelete;
-        }
-    }
-}
-
 DocumentRedlineManager::~DocumentRedlineManager()
 {
 }
diff --git a/sw/source/core/inc/DocumentRedlineManager.hxx b/sw/source/core/inc/DocumentRedlineManager.hxx
index c25abf25d394..8412e9a57c04 100644
--- a/sw/source/core/inc/DocumentRedlineManager.hxx
+++ b/sw/source/core/inc/DocumentRedlineManager.hxx
@@ -124,8 +124,6 @@ public:
      Sequence number is for conjoining of Redlines by the UI. */
     void SetAutoFormatRedlineComment( const OUString* pText, sal_uInt16 nSeqNo = 0 );
 
-    void checkRedlining(RedlineFlags& _rReadlineMode);
-
     bool IsHideRedlines() const { return m_bHideRedlines; }
     void SetHideRedlines(bool const bHideRedlines) { m_bHideRedlines = bHideRedlines; }
 
@@ -143,7 +141,6 @@ private:
     std::unique_ptr<SwExtraRedlineTable> mpExtraRedlineTable;      //< List of all Extra Redlines.
     std::unique_ptr<OUString> mpAutoFormatRedlnComment;  //< Comment for Redlines inserted via AutoFormat.
     bool mbIsRedlineMove;    //< true: Redlines are moved into to / out of the section.
-    bool mbReadlineChecked;    //< true: if the query was already shown
     sal_uInt16 mnAutoFormatRedlnCommentNo;  /**< SeqNo for conjoining of AutoFormat-Redlines.
                                          by the UI. Managed by SwAutoFormat! */
     css::uno::Sequence <sal_Int8 > maRedlinePasswd;
diff --git a/sw/uiconfig/swriter/ui/queryshowchangesdialog.ui b/sw/uiconfig/swriter/ui/queryshowchangesdialog.ui
deleted file mode 100644
index 97b7a654f28b..000000000000
--- a/sw/uiconfig/swriter/ui/queryshowchangesdialog.ui
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.20.2 -->
-<interface domain="sw">
-  <requires lib="gtk+" version="3.18"/>
-  <object class="GtkMessageDialog" id="QueryShowChangesDialog">
-    <property name="can_focus">False</property>
-    <property name="title" translatable="yes" context="queryshowchangesdialog|QueryShowChangesDialog">Show changes?</property>
-    <property name="resizable">False</property>
-    <property name="modal">True</property>
-    <property name="type_hint">dialog</property>
-    <property name="skip_taskbar_hint">True</property>
-    <property name="message_type">question</property>
-    <property name="buttons">yes-no</property>
-    <property name="text" translatable="yes" context="queryshowchangesdialog|QueryShowChangesDialog">Do you want to show changes to avoid delays?</property>
-    <property name="secondary_text" translatable="yes" context="queryshowchangesdialog|QueryShowChangesDialog">In the current document, changes are being recorded but not shown as such. In large documents, delays can occur when the document is edited. Showing changes will avoid delays.</property>
-    <child internal-child="vbox">
-      <object class="GtkBox" id="messagedialog-vbox">
-        <property name="can_focus">False</property>
-        <property name="orientation">vertical</property>
-        <property name="spacing">12</property>
-        <child internal-child="action_area">
-          <object class="GtkButtonBox" id="messagedialog-action_area">
-            <property name="can_focus">False</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="pack_type">end</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-      </object>
-    </child>
-  </object>
-</interface>
commit 15328224ffabeb12a5c7741fe904a97e12787070
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Dec 18 15:26:07 2018 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Tue Dec 18 22:30:17 2018 +0100

    sw_redlinehide_4b: tdf#113479 SetRedlineFlags() calls no longer...
    
    ...able to be triggered by the UI, so the performance problem should be
    gone.
    
    The SwXTextDocument "ShowChanges" property allows API clients to call
    SetRedlineFlags() and change the model; this API should be retained
    as-is for now, because there is no way currently (outside of the rather
    specialised a11y API) to get a "merged view" of the paragraphs in the
    document, so API clients may want to (temporarily) toggle this property
    to then retrieve properties from the model.  In case we later find that
    there are no API clients that want to do such things, the property can
    be removed.
    
    A run with assert() instead of SAL_WARN_IF() found only 2 tests that
    explicitly call SetRedlineFlags() to clear ShowDelete.
    
    Change-Id: I44aee90f7727948ca0bbaaff9d04f8dd6b97cbd1
    Reviewed-on: https://gerrit.libreoffice.org/65350
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <Michael.Stahl at cib.de>
    (cherry picked from commit 09657e3166e875f280095bf7d2f1f2ca8e022803)

diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index 45508b9ac8a7..e1e53411115a 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -3689,7 +3689,6 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa
     assert(m_rDoc.getIDocumentRedlineAccess().IsRedlineOn());
 
     RedlineFlags eOld = m_rDoc.getIDocumentRedlineAccess().GetRedlineFlags();
-    m_rDoc.GetDocumentRedlineManager().checkRedlining( eOld );
 
     if (*rPam.GetPoint() == *rPam.GetMark())
     {
@@ -3750,9 +3749,10 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa
     std::vector<std::unique_ptr<SwUndoRedlineDelete>> undos;
     if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
     {
-        /* please don't translate -- for cultural reasons this comment is protected
-           until the redline implementation is finally fixed some day */
-        //JP 06.01.98: MUSS noch optimiert werden!!!
+        // this should no longer happen in calls from the UI but maybe via API
+        // (randomTest and testTdf54819 triggers it)
+        SAL_WARN_IF((eOld & RedlineFlags::ShowMask) != RedlineFlags::ShowMask,
+                "sw.core", "redlines will be moved in DeleteAndJoin");
         m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags(
             RedlineFlags::On | RedlineFlags::ShowInsert | RedlineFlags::ShowDelete);
         for (SwRangeRedline * pRedline : redlines)
@@ -3811,7 +3811,6 @@ bool DocumentContentOperationsManager::DeleteAndJoinWithRedlineImpl( SwPaM & rPa
         {
             m_rDoc.GetIDocumentUndoRedo().EndUndo(SwUndoId::EMPTY, nullptr);
         }
-        //JP 06.01.98: MUSS noch optimiert werden!!!
         m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags( eOld );
     }
     return true;
@@ -4075,9 +4074,12 @@ bool DocumentContentOperationsManager::ReplaceRangeImpl( SwPaM& rPam, const OUSt
         if( m_rDoc.getIDocumentRedlineAccess().IsRedlineOn() )
         {
             RedlineFlags eOld = m_rDoc.getIDocumentRedlineAccess().GetRedlineFlags();
-            m_rDoc.GetDocumentRedlineManager().checkRedlining(eOld);
             if (m_rDoc.GetIDocumentUndoRedo().DoesUndo())
             {
+                // this should no longer happen in calls from the UI but maybe via API
+                SAL_WARN_IF((eOld & RedlineFlags::ShowMask) != RedlineFlags::ShowMask,
+                        "sw.core", "redlines will be moved in ReplaceRange");
+
                 m_rDoc.GetIDocumentUndoRedo().StartUndo(SwUndoId::EMPTY, nullptr);
 
                 // If any Redline will change (split!) the node
@@ -4086,7 +4088,6 @@ bool DocumentContentOperationsManager::ReplaceRangeImpl( SwPaM& rPam, const OUSt
                         OUString(), IDocumentMarkAccess::MarkType::UNO_BOOKMARK,
                         ::sw::mark::InsertMode::New);
 
-                //JP 06.01.98: MUSS noch optimiert werden!!!
                 m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags(
                     RedlineFlags::On | RedlineFlags::ShowInsert | RedlineFlags::ShowDelete );
 
@@ -4185,7 +4186,6 @@ bool DocumentContentOperationsManager::ReplaceRangeImpl( SwPaM& rPam, const OUSt
                 rPam.GetPoint()->nNode = 0;
                 rPam.GetPoint()->nContent = rIdx;
                 *rPam.GetMark() = *rPam.GetPoint();
-                //JP 06.01.98: MUSS noch optimiert werden!!!
                 m_rDoc.getIDocumentRedlineAccess().SetRedlineFlags( eOld );
 
                 *rPam.GetPoint() = pBkmk->GetMarkPos();
diff --git a/sw/source/core/doc/docnum.cxx b/sw/source/core/doc/docnum.cxx
index a6e1c267f0f1..e99195f85a75 100644
--- a/sw/source/core/doc/docnum.cxx
+++ b/sw/source/core/doc/docnum.cxx
@@ -2261,10 +2261,12 @@ bool SwDoc::MoveParagraphImpl(SwPaM& rPam, long const nOffset,
             }
 
             RedlineFlags eOld = getIDocumentRedlineAccess().GetRedlineFlags();
-            GetDocumentRedlineManager().checkRedlining(eOld);
             if (GetIDocumentUndoRedo().DoesUndo())
             {
-                // Still NEEDS to be optimized (even after 14 years)
+                // this should no longer happen in calls from the UI but maybe via API
+                SAL_WARN_IF((eOld & RedlineFlags::ShowMask) != RedlineFlags::ShowMask,
+                    "sw.core", "redlines will be moved in DeleteAndJoin");
+
                 getIDocumentRedlineAccess().SetRedlineFlags(
                    RedlineFlags::On | RedlineFlags::ShowInsert | RedlineFlags::ShowDelete );
                 GetIDocumentUndoRedo().AppendUndo(
@@ -2285,7 +2287,6 @@ bool SwDoc::MoveParagraphImpl(SwPaM& rPam, long const nOffset,
             aPam.GetBound(false).nContent.Assign(aPam.GetBound(false).nNode.GetNode().GetContentNode(), 0);
             sw::UpdateFramesForAddDeleteRedline(*this, aPam);
 
-            // Still NEEDS to be optimized!
             getIDocumentRedlineAccess().SetRedlineFlags( eOld );
             GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr );
             getIDocumentState().SetModified();
commit 94c1af65367dcbc7272455cf6d4940252a289b62
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Nov 30 17:54:41 2018 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Tue Dec 18 22:30:17 2018 +0100

    sw_redlinehide: make layout based Show/Hide mode the default
    
    remove ExperimentalMode checks
    
    Change-Id: Ie098eda0840bbd3231696cae43cc572ad61379fc
    (cherry picked from commit 32902f66e7749b2d06d13f50416be5323a0c0ea9)

diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index fa698b44450d..e2844a663ded 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -1525,8 +1525,11 @@ void SwUiWriterTest::testTdf83260()
     SwAutoCorrect corr(*SvxAutoCorrCfg::Get().GetAutoCorrect());
 
     // enabled but not shown
+    CPPUNIT_ASSERT(pWrtShell->GetLayout()->IsHideRedlines());
+#if 0
     CPPUNIT_ASSERT(IDocumentRedlineAccess::IsHideChanges(
             pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
+#endif
     CPPUNIT_ASSERT(IDocumentRedlineAccess::IsRedlineOn(
             pDoc->getIDocumentRedlineAccess().GetRedlineFlags()));
     CPPUNIT_ASSERT(!pDoc->getIDocumentRedlineAccess().GetRedlineTable().empty());
diff --git a/sw/source/core/edit/autofmt.cxx b/sw/source/core/edit/autofmt.cxx
index 6b3059e86f32..b12d9a1605ff 100644
--- a/sw/source/core/edit/autofmt.cxx
+++ b/sw/source/core/edit/autofmt.cxx
@@ -2273,21 +2273,14 @@ SwAutoFormat::SwAutoFormat( SwEditShell* pEdShell, SvxSwAutoFormatFlags const &
                          m_pDoc->GetDocShell() );
     }
 
-    uno::Reference<uno::XComponentContext> const xContext(
-            comphelper::getProcessComponentContext());
-    bool const isExp(officecfg::Office::Common::Misc::ExperimentalMode::get(xContext));
     RedlineFlags eRedlMode = m_pDoc->getIDocumentRedlineAccess().GetRedlineFlags(), eOldMode = eRedlMode;
     if( m_aFlags.bWithRedlining )
     {
         m_pDoc->SetAutoFormatRedline( true );
-        eRedlMode = isExp
-            ? RedlineFlags::On | (eOldMode & RedlineFlags::ShowMask)
-            : RedlineFlags::On | RedlineFlags::ShowInsert;
+        eRedlMode = RedlineFlags::On | (eOldMode & RedlineFlags::ShowMask);
     }
     else
-      eRedlMode = isExp
-          ? RedlineFlags::Ignore | (eOldMode & RedlineFlags::ShowMask)
-          : RedlineFlags::ShowInsert | RedlineFlags::Ignore;
+      eRedlMode = RedlineFlags::Ignore | (eOldMode & RedlineFlags::ShowMask);
     m_pDoc->getIDocumentRedlineAccess().SetRedlineFlags( eRedlMode );
 
     // save undo state (might be turned off)
diff --git a/sw/source/filter/xml/XMLRedlineImportHelper.cxx b/sw/source/filter/xml/XMLRedlineImportHelper.cxx
index cec28a9b596a..d78e7e6b4849 100644
--- a/sw/source/filter/xml/XMLRedlineImportHelper.cxx
+++ b/sw/source/filter/xml/XMLRedlineImportHelper.cxx
@@ -344,19 +344,12 @@ XMLRedlineImportHelper::~XMLRedlineImportHelper()
         aAny <<= bShowChanges;
         if ( bHandleShowChanges )
         {
-            if (!utl::ConfigManager::IsFuzzing() && officecfg::Office::Common::Misc::ExperimentalMode::get(comphelper::getProcessComponentContext()))
-            {
-                aAny <<= true;
-                xModelPropertySet->setPropertyValue( g_sShowChanges, aAny );
-                // TODO maybe we need some property for the view-setting?
-                SwDoc *const pDoc(SwImport::GetDocFromXMLImport(m_rImport));
-                assert(pDoc);
-                pDoc->GetDocumentRedlineManager().SetHideRedlines(!bShowChanges);
-            }
-            else
-            {
-                xModelPropertySet->setPropertyValue( g_sShowChanges, aAny );
-            }
+            aAny <<= true;
+            xModelPropertySet->setPropertyValue( g_sShowChanges, aAny );
+            // TODO maybe we need some property for the view-setting?
+            SwDoc *const pDoc(SwImport::GetDocFromXMLImport(m_rImport));
+            assert(pDoc);
+            pDoc->GetDocumentRedlineManager().SetHideRedlines(!bShowChanges);
         }
         else
             xImportInfoPropertySet->setPropertyValue( g_sShowChanges, aAny );
diff --git a/sw/source/filter/xml/swxml.cxx b/sw/source/filter/xml/swxml.cxx
index f36ffb47a147..138dc19981c8 100644
--- a/sw/source/filter/xml/swxml.cxx
+++ b/sw/source/filter/xml/swxml.cxx
@@ -856,8 +856,7 @@ ErrCode XMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPaM, con
     if( !(IsOrganizerMode() || IsBlockMode() || m_bInsertMode ||
           m_aOption.IsFormatsOnly() ||
             // sw_redlinehide: disable layout cache for now
-          (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext) &&
-            !*o3tl::doAccess<bool>(xInfoSet->getPropertyValue(sShowChanges)))))
+          !*o3tl::doAccess<bool>(xInfoSet->getPropertyValue(sShowChanges))))
     {
         try
         {
@@ -905,14 +904,8 @@ ErrCode XMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPaM, con
     // tdf#83260 ensure that the first call of CompressRedlines after loading
     // the document is a no-op by calling it now
     rDoc.getIDocumentRedlineAccess().CompressRedlines();
-    if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
-    {   // can't set it on the layout or view shell because it doesn't exist yet
-        rDoc.GetDocumentRedlineManager().SetHideRedlines(!(nRedlineFlags & RedlineFlags::ShowDelete));
-    }
-    else
-    {
-        rDoc.getIDocumentRedlineAccess().SetRedlineFlags(nRedlineFlags);
-    }
+    // can't set it on the layout or view shell because it doesn't exist yet
+    rDoc.GetDocumentRedlineManager().SetHideRedlines(!(nRedlineFlags & RedlineFlags::ShowDelete));
 
     lcl_EnsureValidPam( rPaM ); // move Pam into valid content
 
diff --git a/sw/source/filter/xml/wrtxml.cxx b/sw/source/filter/xml/wrtxml.cxx
index 34e51e8f2ed9..495cd765aaa3 100644
--- a/sw/source/filter/xml/wrtxml.cxx
+++ b/sw/source/filter/xml/wrtxml.cxx
@@ -165,7 +165,6 @@ ErrCode SwXMLWriter::Write_( const uno::Reference < task::XStatusIndicator >& xS
 
     xInfoSet->setPropertyValue( "TargetStorage", Any( xStg ) );
 
-    uno::Any aAny;
     if (m_bShowProgress)
     {
         // set progress range and start status indicator
@@ -188,15 +187,9 @@ ErrCode SwXMLWriter::Write_( const uno::Reference < task::XStatusIndicator >& xS
     RedlineFlags const nOrigRedlineFlags = m_pDoc->getIDocumentRedlineAccess().GetRedlineFlags();
     RedlineFlags nRedlineFlags(nOrigRedlineFlags);
     bool isShowChanges;
-    if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
-    {   // TODO: ideally this would be stored per-view...
-        SwRootFrame const*const pLayout(m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
-        isShowChanges = pLayout == nullptr || !pLayout->IsHideRedlines();
-    }
-    else
-    {
-        isShowChanges = IDocumentRedlineAccess::IsShowChanges(nRedlineFlags);
-    }
+    // TODO: ideally this would be stored per-view...
+    SwRootFrame const*const pLayout(m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
+    isShowChanges = pLayout == nullptr || !pLayout->IsHideRedlines();
     xInfoSet->setPropertyValue(sShowChanges, makeAny(isShowChanges));
     // ... and hide redlines for export
     nRedlineFlags &= ~RedlineFlags::ShowMask;
@@ -415,19 +408,10 @@ ErrCode SwXMLWriter::Write_( const uno::Reference < task::XStatusIndicator >& xS
     xObjectResolver = nullptr;
 
     // restore redline mode
-    aAny = xInfoSet->getPropertyValue( sShowChanges );
     nRedlineFlags = m_pDoc->getIDocumentRedlineAccess().GetRedlineFlags();
     nRedlineFlags &= ~RedlineFlags::ShowMask;
     nRedlineFlags |= RedlineFlags::ShowInsert;
-    if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
-    {
-        nRedlineFlags |= nOrigRedlineFlags & RedlineFlags::ShowMask;
-    }
-    else
-    {
-        if (*o3tl::doAccess<bool>(aAny))
-            nRedlineFlags |= RedlineFlags::ShowDelete;
-    }
+    nRedlineFlags |= nOrigRedlineFlags & RedlineFlags::ShowMask;
     m_pDoc->getIDocumentRedlineAccess().SetRedlineFlags( nRedlineFlags );
 
     if (xStatusIndicator.is())
diff --git a/sw/source/filter/xml/xmlexp.cxx b/sw/source/filter/xml/xmlexp.cxx
index 0fd2296e97e8..3e408bed91bb 100644
--- a/sw/source/filter/xml/xmlexp.cxx
+++ b/sw/source/filter/xml/xmlexp.cxx
@@ -278,15 +278,8 @@ ErrCode SwXMLExport::exportDoc( enum XMLTokenEnum eClass )
         }
     }
     RedlineFlags nRedlineFlags = RedlineFlags::NONE;
-    if (officecfg::Office::Common::Misc::ExperimentalMode::get(getComponentContext()))
-    {
-        SwRootFrame const*const pLayout(m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
-        m_bSavedShowChanges = pLayout == nullptr || !pLayout->IsHideRedlines();
-    }
-    else
-    {
-        m_bSavedShowChanges = IDocumentRedlineAccess::IsShowChanges( pDoc->getIDocumentRedlineAccess().GetRedlineFlags() );
-    }
+    SwRootFrame const*const pLayout(m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
+    m_bSavedShowChanges = pLayout == nullptr || !pLayout->IsHideRedlines();
     if( bSaveRedline )
     {
         // now save and switch redline mode
diff --git a/sw/source/uibase/uiview/view2.cxx b/sw/source/uibase/uiview/view2.cxx
index 94c30d3cc274..a832d8fb246c 100644
--- a/sw/source/uibase/uiview/view2.cxx
+++ b/sw/source/uibase/uiview/view2.cxx
@@ -638,17 +638,10 @@ void SwView::Execute(SfxRequest &rReq)
                 if( static_cast<const SfxBoolItem*>(pItem)->GetValue() )
                     nMode |= RedlineFlags::ShowDelete;
 
-                uno::Reference<uno::XComponentContext> const xContext(
-                        comphelper::getProcessComponentContext());
-                if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
-                {
-                    m_pWrtShell->GetLayout()->SetHideRedlines(
-                        !static_cast<const SfxBoolItem*>(pItem)->GetValue());
-                    if (m_pWrtShell->IsRedlineOn())
-                        m_pWrtShell->SetInsMode();
-                }
-                else
-                    m_pWrtShell->SetRedlineFlagsAndCheckInsMode( nMode );
+                m_pWrtShell->GetLayout()->SetHideRedlines(
+                    !static_cast<const SfxBoolItem*>(pItem)->GetValue());
+                if (m_pWrtShell->IsRedlineOn())
+                    m_pWrtShell->SetInsMode();
             }
             break;
         case FN_MAILMERGE_SENDMAIL_CHILDWINDOW:
diff --git a/sw/source/uibase/uiview/viewstat.cxx b/sw/source/uibase/uiview/viewstat.cxx
index 38ffb27df5da..909ba9a67225 100644
--- a/sw/source/uibase/uiview/viewstat.cxx
+++ b/sw/source/uibase/uiview/viewstat.cxx
@@ -284,12 +284,7 @@ void SwView::GetState(SfxItemSet &rSet)
             {
                 uno::Reference<uno::XComponentContext> const xContext(
                         comphelper::getProcessComponentContext());
-                if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
-                {
-                    rSet.Put(SfxBoolItem(nWhich, !m_pWrtShell->GetLayout()->IsHideRedlines()));
-                }
-                else
-                    rSet.Put( SfxBoolItem( nWhich, IDocumentRedlineAccess::IsShowChanges(m_pWrtShell->GetRedlineFlags()) ));
+                rSet.Put(SfxBoolItem(nWhich, !m_pWrtShell->GetLayout()->IsHideRedlines()));
             }
             break;
             case SID_AVMEDIA_PLAYER :
commit a44be0f4d6ee7321f0cdf441b054a10ad6285440
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Dec 5 16:37:18 2018 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Tue Dec 18 22:30:17 2018 +0100

    sw_redlinehide_4b: temporarily add an assert that is wrong
    
    This assert is wrong, because there may be a legimate need to query
    a position that is currently hidden.
    
    However, oddly enough, we haven't found a legitimate document yet that
    triggers this, and it has pointed us to several interesting functions
    that needed adapting to merged frames... so keep it a little while and
    remove it (and return something other than COMPLETE_STRING from mapping
    functions) later...
    
    Change-Id: Ide2abf0c2ce054b75c917063a5d5aa8d13430426
    (cherry picked from commit b310378e874bc8fa7005352fcd85fa64eb075f54)

diff --git a/sw/source/core/text/frmcrsr.cxx b/sw/source/core/text/frmcrsr.cxx
index 7b6411163cb3..c756aedf4cd2 100644
--- a/sw/source/core/text/frmcrsr.cxx
+++ b/sw/source/core/text/frmcrsr.cxx
@@ -267,6 +267,7 @@ bool SwTextFrame::GetCharRect( SwRect& rOrig, const SwPosition &rPos,
 
         bool bGoOn = true;
         TextFrameIndex const nOffset = MapModelToViewPos(rPos);
+        assert(nOffset != TextFrameIndex(COMPLETE_STRING)); // not going to end well
         TextFrameIndex nNextOfst;
 
         do
commit 082e977297f1c1eaf078a9dfde3efd6d32c1963a
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Dec 17 21:46:13 2018 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Tue Dec 18 22:30:17 2018 +0100

    sw_redlinehide_4b: ODF export: restore previous redline show flags
    
    There's a test for that, testRedlineFlags() in sw_globalfilter
    
    Change-Id: I9c821732910298d74271d95f0bfd0e902af84dbd
    (cherry picked from commit 7f42b4de3a5a72e695da0705ddc7db8bce576901)

diff --git a/sw/source/filter/xml/wrtxml.cxx b/sw/source/filter/xml/wrtxml.cxx
index 0d5e53d4c319..34e51e8f2ed9 100644
--- a/sw/source/filter/xml/wrtxml.cxx
+++ b/sw/source/filter/xml/wrtxml.cxx
@@ -185,7 +185,8 @@ ErrCode SwXMLWriter::Write_( const uno::Reference < task::XStatusIndicator >& xS
 
     // save show redline mode ...
     const OUString sShowChanges("ShowChanges");
-    RedlineFlags nRedlineFlags = m_pDoc->getIDocumentRedlineAccess().GetRedlineFlags();
+    RedlineFlags const nOrigRedlineFlags = m_pDoc->getIDocumentRedlineAccess().GetRedlineFlags();
+    RedlineFlags nRedlineFlags(nOrigRedlineFlags);
     bool isShowChanges;
     if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
     {   // TODO: ideally this would be stored per-view...
@@ -420,7 +421,7 @@ ErrCode SwXMLWriter::Write_( const uno::Reference < task::XStatusIndicator >& xS
     nRedlineFlags |= RedlineFlags::ShowInsert;
     if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
     {
-        nRedlineFlags |= RedlineFlags::ShowDelete;
+        nRedlineFlags |= nOrigRedlineFlags & RedlineFlags::ShowMask;
     }
     else
     {
commit 3275900d262119ae797519729a89511e1afb2b55
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Dec 17 19:39:22 2018 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Tue Dec 18 22:30:17 2018 +0100

    sw_redlinehide_4b: export flag to flat-ODF
    
    Change-Id: Ief227f3f5b03ec186178f4d68c3a415969d65507
    (cherry picked from commit 5bc7fb209c0e6d7c6a46499d8c2e4d7abaa87bd7)

diff --git a/sw/source/filter/xml/xmlexp.cxx b/sw/source/filter/xml/xmlexp.cxx
index 4887e14075fb..0fd2296e97e8 100644
--- a/sw/source/filter/xml/xmlexp.cxx
+++ b/sw/source/filter/xml/xmlexp.cxx
@@ -26,6 +26,7 @@
 #include <com/sun/star/xforms/XFormsSupplier.hpp>
 
 #include <o3tl/any.hxx>
+#include <officecfg/Office/Common.hxx>
 #include <sax/tools/converter.hxx>
 #include <svx/svdmodel.hxx>
 #include <svx/svdpage.hxx>
@@ -46,6 +47,7 @@
 #include <swmodule.hxx>
 #include <docsh.hxx>
 #include <viewsh.hxx>
+#include <rootfrm.hxx>
 #include <docstat.hxx>
 #include <swerror.h>
 #include <unotext.hxx>
@@ -276,7 +278,15 @@ ErrCode SwXMLExport::exportDoc( enum XMLTokenEnum eClass )
         }
     }
     RedlineFlags nRedlineFlags = RedlineFlags::NONE;
-    m_bSavedShowChanges = IDocumentRedlineAccess::IsShowChanges( pDoc->getIDocumentRedlineAccess().GetRedlineFlags() );
+    if (officecfg::Office::Common::Misc::ExperimentalMode::get(getComponentContext()))
+    {
+        SwRootFrame const*const pLayout(m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
+        m_bSavedShowChanges = pLayout == nullptr || !pLayout->IsHideRedlines();
+    }
+    else
+    {
+        m_bSavedShowChanges = IDocumentRedlineAccess::IsShowChanges( pDoc->getIDocumentRedlineAccess().GetRedlineFlags() );
+    }
     if( bSaveRedline )
     {
         // now save and switch redline mode
commit d28d85c1d21ad466ead022daf41b910181affe98
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Dec 17 19:16:05 2018 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Tue Dec 18 22:30:17 2018 +0100

    sw_redlinehide_4b: xmloff: destroy TextImportHelper before Model
    
    nullpointer in ~XMLRedlineImportHelper in
    SwUiWriterTest::testThreadedException()
    
    Change-Id: Ic4a79ceffa831aced4db47836333a15a13773887
    (cherry picked from commit 68d77adb2d8242588b416240e6f7d47940099aaa)

diff --git a/xmloff/source/core/xmlimp.cxx b/xmloff/source/core/xmlimp.cxx
index d68a9debcfc2..556e39299454 100644
--- a/xmloff/source/core/xmlimp.cxx
+++ b/xmloff/source/core/xmlimp.cxx
@@ -431,6 +431,7 @@ void SvXMLImport::cleanup() throw ()
             pStylesContext->Clear();
         maContexts.pop();
     }
+    mxTextImport.clear(); // XMLRedlineImportHelper needs model
     DisposingModel();
 }
 
commit 646e6366581a9a42f90987f77a0a32bbb543ed10
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Dec 17 14:10:26 2018 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Tue Dec 18 22:30:16 2018 +0100

    sw_redlinehide_4b: adapt FindFormat()
    
    Change-Id: I78cfca1cd629bf518f8294450a34ee228a360ef9
    (cherry picked from commit 87514172c1924492c33a8aa261b082f0ae7f9b48)

diff --git a/sw/inc/swcrsr.hxx b/sw/inc/swcrsr.hxx
index 1a5a65bf0661..7dd94c4de962 100644
--- a/sw/inc/swcrsr.hxx
+++ b/sw/inc/swcrsr.hxx
@@ -123,7 +123,8 @@ public:
                 SwDocPositions nStart, SwDocPositions nEnde,
                 bool& bCancel,
                 FindRanges,
-                const SwTextFormatColl* pReplFormat );
+                const SwTextFormatColl* pReplFormat,
+                SwRootFrame const*const pLayout = nullptr);
     sal_uLong FindAttrs( const SfxItemSet& rSet, bool bNoCollections,
                 SwDocPositions nStart, SwDocPositions nEnde,
                 bool& bCancel,
diff --git a/sw/source/core/crsr/findcoll.cxx b/sw/source/core/crsr/findcoll.cxx
index b05fe2c5f742..ec033d6bb207 100644
--- a/sw/source/core/crsr/findcoll.cxx
+++ b/sw/source/core/crsr/findcoll.cxx
@@ -30,8 +30,13 @@
 struct SwFindParaFormatColl : public SwFindParas
 {
     const SwTextFormatColl *pFormatColl, *pReplColl;
-    SwFindParaFormatColl(const SwTextFormatColl& rFormatColl, const SwTextFormatColl* pRpColl)
-        : pFormatColl( &rFormatColl ), pReplColl( pRpColl )
+    SwRootFrame const* m_pLayout;
+    SwFindParaFormatColl(const SwTextFormatColl& rFormatColl,
+            const SwTextFormatColl *const pRpColl,
+            SwRootFrame const*const pLayout)
+        : pFormatColl( &rFormatColl )
+        , pReplColl( pRpColl )
+        , m_pLayout(pLayout)
     {}
     virtual ~SwFindParaFormatColl() {}
     virtual int DoFind(SwPaM &, SwMoveFnCollection const &, const SwPaM &, bool bInReadOnly) override;
@@ -45,11 +50,12 @@ int SwFindParaFormatColl::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnM
     if( bInReadOnly && pReplColl )
         bInReadOnly = false;
 
-    if (!sw::FindFormatImpl(rCursor, *pFormatColl, fnMove, rRegion, bInReadOnly))
+    if (!sw::FindFormatImpl(rCursor, *pFormatColl, fnMove, rRegion, bInReadOnly, m_pLayout))
         nRet = FIND_NOT_FOUND;
     else if( pReplColl )
     {
-        rCursor.GetDoc()->SetTextFormatColl(rCursor, const_cast<SwTextFormatColl*>(pReplColl));
+        rCursor.GetDoc()->SetTextFormatColl(rCursor,
+            const_cast<SwTextFormatColl*>(pReplColl), true, false, m_pLayout);
         nRet = FIND_NO_RING;
     }
     return nRet;
@@ -63,7 +69,8 @@ bool SwFindParaFormatColl::IsReplaceMode() const
 /// search for Format-Collections
 sal_uLong SwCursor::FindFormat( const SwTextFormatColl& rFormatColl, SwDocPositions nStart,
                           SwDocPositions nEnd, bool& bCancel,
-                          FindRanges eFndRngs, const SwTextFormatColl* pReplFormatColl )
+                          FindRanges eFndRngs, const SwTextFormatColl* pReplFormatColl,
+                          SwRootFrame const*const pLayout)
 {
     // switch off OLE-notifications
     SwDoc* pDoc = GetDoc();
@@ -83,7 +90,7 @@ sal_uLong SwCursor::FindFormat( const SwTextFormatColl& rFormatColl, SwDocPositi
                 &aRewriter );
     }
 
-    SwFindParaFormatColl aSwFindParaFormatColl(rFormatColl, pReplFormatColl);
+    SwFindParaFormatColl aSwFindParaFormatColl(rFormatColl, pReplFormatColl, pLayout);
 
     sal_uLong nRet = FindAll( aSwFindParaFormatColl, nStart, nEnd, eFndRngs, bCancel );
     pDoc->SetOle2Link( aLnk );
diff --git a/sw/source/core/crsr/findfmt.cxx b/sw/source/core/crsr/findfmt.cxx
index f45759e5a0d6..1193cf856ef8 100644
--- a/sw/source/core/crsr/findfmt.cxx
+++ b/sw/source/core/crsr/findfmt.cxx
@@ -20,13 +20,15 @@
 #include <doc.hxx>
 #include <pamtyp.hxx>
 #include <pam.hxx>
+#include <txtfrm.hxx>
 #include <memory>
 
 namespace sw {
 
 bool FindFormatImpl(SwPaM & rSearchPam,
         const SwFormat& rFormat, SwMoveFnCollection const & fnMove,
-        const SwPaM &rRegion, bool bInReadOnly)
+        const SwPaM &rRegion, bool bInReadOnly,
+        SwRootFrame const*const pLayout)
 {
     bool bFound = false;
     const bool bSrchForward = &fnMove == &fnMoveForward;
@@ -47,19 +49,37 @@ bool FindFormatImpl(SwPaM & rSearchPam,
 
     bool bFirst = true;
     SwContentNode* pNode;
-    while( nullptr != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly )))
+    while (nullptr != (pNode = ::GetNode(*pPam, bFirst, fnMove, bInReadOnly, pLayout)))
     {
-        if ( pNode->GetFormatColl() == &rFormat )
+        SwTextFrame const*const pFrame(pLayout && pNode->IsTextNode()
+            ? static_cast<SwTextFrame const*>(pNode->getLayoutFrame(pLayout))
+            : nullptr);
+        assert(!pLayout || !pNode->IsTextNode() || pFrame);
+        SwContentNode const& rPropsNode(*(pFrame
+            ? pFrame->GetTextNodeForParaProps()
+            : pNode));
+
+        if (rPropsNode.GetFormatColl() == &rFormat)
         {
             // if a FormatCollection is found then it is definitely a SwContentNode
 
             // FORWARD:  SPoint at the end, GetMark at the beginning of the node
             // BACKWARD: SPoint at the beginning, GetMark at the end of the node
             // always: incl. start and incl. end
-            *rSearchPam.GetPoint() = *pPam->GetPoint();
-            rSearchPam.SetMark();
-            pNode->MakeEndIndex( &rSearchPam.GetPoint()->nContent );
-            rSearchPam.GetMark()->nContent = 0;
+            if (pFrame)
+            {
+                *rSearchPam.GetPoint() = *pPam->GetPoint();
+                rSearchPam.SetMark();
+                *rSearchPam.GetMark() = pFrame->MapViewToModelPos(
+                    TextFrameIndex(bSrchForward ? pFrame->GetText().getLength() : 0));
+            }
+            else
+            {
+                *rSearchPam.GetPoint() = *pPam->GetPoint();
+                rSearchPam.SetMark();
+                pNode->MakeEndIndex( &rSearchPam.GetPoint()->nContent );
+                rSearchPam.GetMark()->nContent = 0;
+            }
 
             // if backward search, switch point and mark
             if( !bSrchForward )
diff --git a/sw/source/core/inc/pamtyp.hxx b/sw/source/core/inc/pamtyp.hxx
index b51212b23633..c9fc8124b876 100644
--- a/sw/source/core/inc/pamtyp.hxx
+++ b/sw/source/core/inc/pamtyp.hxx
@@ -95,7 +95,8 @@ namespace sw {
     bool FindFormatImpl(SwPaM & rSearchPam,
                 const SwFormat& rFormat,
                 SwMoveFnCollection const & fnMove,
-                const SwPaM & rRegion, bool bInReadOnly = false);
+                const SwPaM & rRegion, bool bInReadOnly,
+                SwRootFrame const* pLayout);
     bool FindAttrImpl(SwPaM & rSearchPam,
                 const SfxPoolItem& rAttr,
                 SwMoveFnCollection const & fnMove,
commit dc812e205f9959359b2139521872e9ac20878702
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Dec 17 13:13:46 2018 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Tue Dec 18 22:30:16 2018 +0100

    sw_redlinehide_4b: adapt FindAttrImpl()
    
    * rename the only user, some UpdateFields() overload, to UpateOneField()
    * restrict it to search for non-formatting hints; the FindAttrsImpl()
      should be used for formatting hints instead
    
    Change-Id: I15002610a287fcdcd76777733a277d2ce64904bc
    (cherry picked from commit 1199902fc9cbf2cf51733f7bc4205d6c32d781d1)

diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx
index 3da4e3617ca0..48a041375c29 100644
--- a/sw/inc/editsh.hxx
+++ b/sw/inc/editsh.hxx
@@ -394,7 +394,7 @@ public:
 
     void Insert2(SwField const &, const bool bForceExpandHints);
 
-    void UpdateFields( SwField & );   ///< One single field.
+    void UpdateOneField(SwField &);   ///< One single field.
 
     size_t GetFieldTypeCount(SwFieldIds nResId = SwFieldIds::Unknown) const;
     SwFieldType* GetFieldType(size_t nField, SwFieldIds nResId = SwFieldIds::Unknown) const;
diff --git a/sw/source/core/crsr/findattr.cxx b/sw/source/core/crsr/findattr.cxx
index d50e0c41d496..9d5f2745afda 100644
--- a/sw/source/core/crsr/findattr.cxx
+++ b/sw/source/core/crsr/findattr.cxx
@@ -154,12 +154,11 @@ static void lcl_SetAttrPam( SwPaM& rPam, sal_Int32 nStart, const sal_Int32* pEnd
     @param rPam     ???
     @param rCmpItem ???
     @param fnMove   ???
-    @param bValue   ???
     @return Returns <true> if found, <false> otherwise.
 */
-static bool lcl_Search( const SwTextNode& rTextNd, SwPaM& rPam,
+static bool lcl_SearchAttr( const SwTextNode& rTextNd, SwPaM& rPam,
                     const SfxPoolItem& rCmpItem,
-                    SwMoveFnCollection const & fnMove, bool bValue )
+                    SwMoveFnCollection const & fnMove)
 {
     if ( !rTextNd.HasHints() )
         return false;
@@ -170,8 +169,7 @@ static bool lcl_Search( const SwTextNode& rTextNd, SwPaM& rPam,
     sal_Int32 nContentPos = rPam.GetPoint()->nContent.GetIndex();
 
     while( nullptr != ( pTextHt=(*fnMove.fnGetHint)(rTextNd.GetSwpHints(),nPos,nContentPos)))
-        if( pTextHt->Which() == rCmpItem.Which() &&
-            ( !bValue || CmpAttr( pTextHt->GetAttr(), rCmpItem )))
+        if (pTextHt->Which() == rCmpItem.Which())
         {
             lcl_SetAttrPam( rPam, pTextHt->GetStart(), pTextHt->End(), bForward );
             return true;
@@ -891,12 +889,14 @@ static bool lcl_Search( const SwContentNode& rCNd, const SfxItemSet& rCmpSet, bo
 namespace sw {
 
 bool FindAttrImpl(SwPaM & rSearchPam,
-        const SfxPoolItem& rAttr, bool bValue, SwMoveFnCollection const & fnMove,
-        const SwPaM & rRegion, bool bInReadOnly)
+        const SfxPoolItem& rAttr, SwMoveFnCollection const & fnMove,
+        const SwPaM & rRegion, bool bInReadOnly,
+        SwRootFrame const*const pLayout)
 {
     // determine which attribute is searched:
     const sal_uInt16 nWhich = rAttr.Which();
     bool bCharAttr = isCHRATR(nWhich) || isTXTATR(nWhich);
+    assert(isTXTATR(nWhich)); // sw_redlinehide: only works for non-formatting hints such as needed in UpdateFields; use FindAttrsImpl for others
 
     std::unique_ptr<SwPaM> pPam(sw::MakeRegion(fnMove, rRegion));
 
@@ -904,8 +904,6 @@ bool FindAttrImpl(SwPaM & rSearchPam,
     bool bFirst = true;
     const bool bSrchForward = &fnMove == &fnMoveForward;
     SwContentNode * pNode;
-    const SfxPoolItem* pItem;
-    SwpFormats aFormatArr;
 
     // if at beginning/end then move it out of the node
     if( bSrchForward
@@ -920,27 +918,73 @@ bool FindAttrImpl(SwPaM & rSearchPam,
         pPam->GetPoint()->nContent.Assign( pNd, bSrchForward ? 0 : pNd->Len() );
     }
 
-    while( nullptr != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
+    while (nullptr != (pNode = ::GetNode(*pPam, bFirst, fnMove, bInReadOnly, pLayout)))
     {
         if( bCharAttr )
         {
             if( !pNode->IsTextNode() ) // CharAttr are only in text nodes
                 continue;
 
-            if( pNode->GetTextNode()->HasHints() &&
-                lcl_Search( *pNode->GetTextNode(), *pPam, rAttr, fnMove,  bValue ))
+            SwTextFrame const*const pFrame(pLayout
+                ? static_cast<SwTextFrame const*>(pNode->getLayoutFrame(pLayout))
+                : nullptr);
+            if (pFrame)
+            {
+                SwTextNode const* pAttrNode(nullptr);
+                SwTextAttr const* pAttr(nullptr);
+                if (bSrchForward)
+                {
+                    sw::MergedAttrIter iter(*pFrame);
+                    do
+                    {
+                        pAttr = iter.NextAttr(&pAttrNode);
+                    }
+                    while (pAttr
+                        && (pAttrNode->GetIndex() < pPam->GetPoint()->nNode.GetIndex()
+                            || (pAttrNode->GetIndex() == pPam->GetPoint()->nNode.GetIndex()
+                                && pAttr->GetStart() < pPam->GetPoint()->nContent.GetIndex())
+                            || pAttr->Which() != nWhich));
+                }
+                else
+                {
+                    sw::MergedAttrIterReverse iter(*pFrame);
+                    do
+                    {
+                        pAttr = iter.PrevAttr(&pAttrNode);
+                    }
+                    while (pAttr
+                        && (pPam->GetPoint()->nNode.GetIndex() < pAttrNode->GetIndex()
+                            || (pPam->GetPoint()->nNode.GetIndex() == pAttrNode->GetIndex()
+                                && pPam->GetPoint()->nContent.GetIndex() <= pAttr->GetStart())
+                            || pAttr->Which() != nWhich));
+                }
+                if (pAttr)
+                {
+                    assert(pAttrNode);
+                    pPam->GetPoint()->nNode = *pAttrNode;
+                    lcl_SetAttrPam(*pPam, pAttr->GetStart(), pAttr->End(), bSrchForward);
+                    bFound = true;
+                    break;
+                }
+            }
+            else if (!pLayout && pNode->GetTextNode()->HasHints() &&
+                lcl_SearchAttr(*pNode->GetTextNode(), *pPam, rAttr, fnMove))
+            {
+                bFound = true;
+            }
+            if (bFound)
             {
                 // set to the values of the attribute
                 rSearchPam.SetMark();
                 *rSearchPam.GetPoint() = *pPam->GetPoint();
                 *rSearchPam.GetMark() = *pPam->GetMark();
-                bFound = true;
                 break;
             }
             else if (isTXTATR(nWhich))
                 continue;
         }
 
+#if 0
         // no hard attribution, so check if node was asked for this attr before
         if( !pNode->HasSwAttrSet() )
         {
@@ -951,7 +995,7 @@ bool FindAttrImpl(SwPaM & rSearchPam,
         }
 
         if( SfxItemState::SET == pNode->GetSwAttrSet().GetItemState( nWhich,
-            true, &pItem ) && ( !bValue || *pItem == rAttr ) )
+                true, &pItem ))
         {
             // FORWARD:  SPoint at the end, GetMark at the beginning of the node
             // BACKWARD: SPoint at the beginning, GetMark at the end of the node
@@ -962,6 +1006,7 @@ bool FindAttrImpl(SwPaM & rSearchPam,
             bFound = true;
             break;
         }
+#endif
     }
 
     // if backward search, switch point and mark
diff --git a/sw/source/core/edit/edfld.cxx b/sw/source/core/edit/edfld.cxx
index da0a15e0199e..3311439fd862 100644
--- a/sw/source/core/edit/edfld.cxx
+++ b/sw/source/core/edit/edfld.cxx
@@ -206,7 +206,7 @@ static SwTextField* lcl_FindInputField( SwDoc* pDoc, SwField& rField )
     return pTField;
 }
 
-void SwEditShell::UpdateFields( SwField &rField )
+void SwEditShell::UpdateOneField(SwField &rField)
 {
     SET_CURR_SHELL( this );
     StartAllAction();
@@ -261,9 +261,9 @@ void SwEditShell::UpdateFields( SwField &rField )
                 // Search for SwTextField ...
                 while(  bOkay
                      && pCurStt->nContent != pCurEnd->nContent
-                     && (sw::FindAttrImpl(aPam, aFieldHint, false, fnMoveForward, aCurPam, true)
-                          || sw::FindAttrImpl(aPam, aAnnotationFieldHint, false, fnMoveForward, aCurPam)
-                          || sw::FindAttrImpl(aPam, aInputFieldHint, false, fnMoveForward, aCurPam)))
+                     && (sw::FindAttrImpl(aPam, aFieldHint, fnMoveForward, aCurPam, true, GetLayout())
+                          || sw::FindAttrImpl(aPam, aAnnotationFieldHint, fnMoveForward, aCurPam, false, GetLayout())
+                          || sw::FindAttrImpl(aPam, aInputFieldHint, fnMoveForward, aCurPam, false, GetLayout())))
                 {
                     // if only one PaM has more than one field  ...
                     if( aPam.Start()->nContent != pCurStt->nContent )
diff --git a/sw/source/core/inc/pamtyp.hxx b/sw/source/core/inc/pamtyp.hxx
index a0ebf2bea708..b51212b23633 100644
--- a/sw/source/core/inc/pamtyp.hxx
+++ b/sw/source/core/inc/pamtyp.hxx
@@ -97,9 +97,10 @@ namespace sw {
                 SwMoveFnCollection const & fnMove,
                 const SwPaM & rRegion, bool bInReadOnly = false);
     bool FindAttrImpl(SwPaM & rSearchPam,
-                const SfxPoolItem& rAttr, bool bValue,
+                const SfxPoolItem& rAttr,
                 SwMoveFnCollection const & fnMove,
-                const SwPaM & rPam, bool bInReadOnly = false);
+                const SwPaM & rPam, bool bInReadOnly,
+                SwRootFrame const* pLayout);
 
 } // namespace sw
 
diff --git a/sw/source/ui/fldui/DropDownFieldDialog.cxx b/sw/source/ui/fldui/DropDownFieldDialog.cxx
index 5ccead9f8504..387bccc39490 100644
--- a/sw/source/ui/fldui/DropDownFieldDialog.cxx
+++ b/sw/source/ui/fldui/DropDownFieldDialog.cxx
@@ -96,7 +96,7 @@ void sw::DropDownFieldDialog::Apply()
                 static_cast<SwDropDownField*>(m_pDropField->CopyField().release()));
 
             pCopy->SetPar1(sSelect);
-            m_rSh.SwEditShell::UpdateFields(*pCopy);
+            m_rSh.SwEditShell::UpdateOneField(*pCopy);
 
             m_rSh.SetUndoNoResetModified();
             m_rSh.EndAllAction();
diff --git a/sw/source/ui/fldui/fldedt.cxx b/sw/source/ui/fldui/fldedt.cxx
index 2f4dfe8020bb..49ea19d1c098 100644
--- a/sw/source/ui/fldui/fldedt.cxx
+++ b/sw/source/ui/fldui/fldedt.cxx
@@ -334,7 +334,7 @@ IMPL_LINK_NOARG(SwFieldEditDlg, AddressHdl, Button*, void)
     ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateSwAddressAbstractDlg(this, aSet));
     if (RET_OK == pDlg->Execute())
     {
-        pSh->UpdateFields( *pCurField );
+        pSh->UpdateOneField(*pCurField);
     }
 }
 
diff --git a/sw/source/ui/fldui/inpdlg.cxx b/sw/source/ui/fldui/inpdlg.cxx
index 361d14a184a8..f2bc3de52fe2 100644
--- a/sw/source/ui/fldui/inpdlg.cxx
+++ b/sw/source/ui/fldui/inpdlg.cxx
@@ -133,14 +133,14 @@ void SwFieldInputDlg::Apply()
         else if( aTmp != pInpField->GetPar1() )
         {
             pInpField->SetPar1(aTmp);
-            rSh.SwEditShell::UpdateFields(*pInpField);
+            rSh.SwEditShell::UpdateOneField(*pInpField);
             bModified = true;
         }
     }
     else if( aTmp != pSetField->GetPar2())
     {
         pSetField->SetPar2(aTmp);
-        rSh.SwEditShell::UpdateFields(*pSetField);
+        rSh.SwEditShell::UpdateOneField(*pSetField);
         bModified = true;
     }
 
diff --git a/sw/source/uibase/fldui/fldmgr.cxx b/sw/source/uibase/fldui/fldmgr.cxx
index 52c8a12bd17e..440fc0b35ddf 100644
--- a/sw/source/uibase/fldui/fldmgr.cxx
+++ b/sw/source/uibase/fldui/fldmgr.cxx
@@ -1518,7 +1518,7 @@ bool SwFieldMgr::InsertField(
     if(bTable)
     {
         pCurShell->Left(CRSR_SKIP_CHARS, false, 1, false );
-        pCurShell->UpdateFields(*pField);
+        pCurShell->UpdateOneField(*pField);
         pCurShell->Right(CRSR_SKIP_CHARS, false, 1, false );
     }
     else if( bPageVar )
@@ -1690,7 +1690,7 @@ void SwFieldMgr::UpdateCurField(sal_uInt32 nFormat,
     }
     else {
         // mb: #32157
-        pSh->SwEditShell::UpdateFields(*pTmpField);
+        pSh->SwEditShell::UpdateOneField(*pTmpField);
         GetCurField();
     }
 
commit 7583bada89fd50accc893d2596e2e5a1fa197041
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Dec 13 15:49:10 2018 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Tue Dec 18 22:30:16 2018 +0100

    sw_redlinehide_4b: adapt FindAttrs()
    
    Iterate over merged nodes, and iterate over extents in them, so the
    complex attribute-finding logic doesn't need to be changed.
    
    Change-Id: Id72ca9247165a0c93f0cf2a38b7a0249771ca2eb
    (cherry picked from commit 4caef398af256be5f0c2a159129b528ee3702e5c)

diff --git a/sw/inc/swcrsr.hxx b/sw/inc/swcrsr.hxx
index cd07cafdf46a..1a5a65bf0661 100644
--- a/sw/inc/swcrsr.hxx
+++ b/sw/inc/swcrsr.hxx
@@ -129,7 +129,8 @@ public:
                 bool& bCancel,
                 FindRanges,
                 const i18nutil::SearchOptions2* pSearchOpt,
-                const SfxItemSet* rReplSet = nullptr );
+                const SfxItemSet* rReplSet = nullptr,
+                SwRootFrame const*const pLayout = nullptr);
 
     // UI versions
     bool IsStartEndSentence(bool bEnd, SwRootFrame const* pLayout) const;
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 1085a34a655f..607c6f42ca92 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -3366,7 +3366,7 @@ sal_uLong SwCursorShell::FindAttrs( const SfxItemSet& rSet,
     m_pTableCursor = nullptr;
     SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
     sal_uLong nRet = m_pCurrentCursor->FindAttrs(rSet, bNoCollections, eStart, eEnd,
-                                     bCancel, eRng, pSearchOpt, rReplSet );
+                         bCancel, eRng, pSearchOpt, rReplSet, GetLayout());
     if( nRet )
         UpdateCursor();
     return nRet;
diff --git a/sw/source/core/crsr/findattr.cxx b/sw/source/core/crsr/findattr.cxx
index 500d4628ad27..d50e0c41d496 100644
--- a/sw/source/core/crsr/findattr.cxx
+++ b/sw/source/core/crsr/findattr.cxx
@@ -41,6 +41,7 @@
 #include <editsh.hxx>
 #include <ndtxt.hxx>
 #include <pamtyp.hxx>
+#include <txtfrm.hxx>
 #include <swundo.hxx>
 #include <boost/optional.hpp>
 
@@ -976,7 +977,8 @@ typedef bool (*FnSearchAttr)( const SwTextNode&, SwAttrCheckArr&, SwPaM& );
 
 static bool FindAttrsImpl(SwPaM & rSearchPam,
         const SfxItemSet& rSet, bool bNoColls, SwMoveFnCollection const & fnMove,
-        const SwPaM & rRegion, bool bInReadOnly, bool bMoveFirst)
+        const SwPaM & rRegion, bool bInReadOnly, bool bMoveFirst,
+        SwRootFrame const*const pLayout)
 {
     std::unique_ptr<SwPaM> pPam(sw::MakeRegion(fnMove, rRegion));
 
@@ -1010,22 +1012,100 @@ static bool FindAttrsImpl(SwPaM & rSearchPam,
         pPam->GetPoint()->nContent.Assign( pNd, bSrchForward ? 0 : pNd->Len() );
     }
 
-    while( nullptr != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ) )
+    while (nullptr != (pNode = ::GetNode(*pPam, bFirst, fnMove, bInReadOnly, pLayout)))
     {
+        SwTextFrame const*const pFrame(pLayout && pNode->IsTextNode()
+            ? static_cast<SwTextFrame const*>(pNode->getLayoutFrame(pLayout))
+            : nullptr);
+        assert(!pLayout || !pNode->IsTextNode() || pFrame);
+        // sw_redlinehide: it's apparently not possible to find break items
+        // with the UI, so checking one node is enough
+        SwContentNode const& rPropsNode(*(pFrame
+            ? pFrame->GetTextNodeForParaProps()
+            : pNode));
+
         if( aCmpArr.Count() )
         {
             if( !pNode->IsTextNode() ) // CharAttr are only in text nodes
                 continue;
 
-            if( (!aOtherSet.Count() ||
-                lcl_Search( *pNode, aOtherSet, bNoColls )) &&
-                (*fnSearch)( *pNode->GetTextNode(), aCmpArr, *pPam ))
+            if (aOtherSet.Count() &&
+                !lcl_Search(rPropsNode, aOtherSet, bNoColls))
+            {
+                continue;
+            }
+            sw::MergedPara const*const pMergedPara(pFrame ? pFrame->GetMergedPara() : nullptr);
+            if (pMergedPara)
+            {
+                SwPosition const& rStart(*pPam->Start());
+                SwPosition const& rEnd(*pPam->End());
+                // no extents? fall back to searching index 0 of propsnode
+                // to find its node items
+                if (pMergedPara->extents.empty())
+                {
+                    if (rStart.nNode.GetIndex() <= rPropsNode.GetIndex()
+                        && rPropsNode.GetIndex() <= rEnd.nNode.GetIndex())
+                    {
+                        SwPaM tmp(rPropsNode, 0, rPropsNode, 0);
+                        bFound = (*fnSearch)(*pNode->GetTextNode(), aCmpArr, tmp);
+                        if (bFound)
+                        {
+                            *pPam = tmp;
+                        }
+                    }
+                }
+                else
+                {
+                    // iterate the extents, and intersect with input pPam:
+                    // the found ranges should never include delete redlines
+                    // so that subsequent Replace will not affect them
+                    for (size_t i = 0; i < pMergedPara->extents.size(); ++i)
+                    {
+                        auto const rExtent(pMergedPara->extents[bSrchForward
+                                ? i
+                                : pMergedPara->extents.size() - i - 1]);
+                        if (rExtent.pNode->GetIndex() < rStart.nNode.GetIndex()
+                            || rEnd.nNode.GetIndex() < rExtent.pNode->GetIndex())
+                        {
+                            continue;
+                        }
+                        sal_Int32 const nStart(rExtent.pNode == &rStart.nNode.GetNode()
+                                ? rStart.nContent.GetIndex()
+                                : 0);
+                        if (rExtent.nEnd <= nStart)
+                        {
+                            continue;
+                        }
+                        sal_Int32 const nEnd(rExtent.pNode == &rEnd.nNode.GetNode()
+                                ? rEnd.nContent.GetIndex()
+                                : rExtent.pNode->Len());
+                        if (nEnd < rExtent.nStart
+                            || (nStart != nEnd && nEnd == rExtent.nStart))
+                        {
+                            continue;
+                        }
+                        SwPaM tmp(*rExtent.pNode, std::max(nStart, rExtent.nStart),
+                            *rExtent.pNode, std::min(nEnd, rExtent.nEnd));
+                        tmp.Normalize(bSrchForward);
+                        bFound = (*fnSearch)(*rExtent.pNode, aCmpArr, tmp);
+                        if (bFound)
+                        {
+                            *pPam = tmp;
+                            break;
+                        }
+                    }
+                }
+            }
+            else
+            {
+                bFound = (*fnSearch)(*pNode->GetTextNode(), aCmpArr, *pPam);
+            }
+            if (bFound)
             {
                 // set to the values of the attribute
                 rSearchPam.SetMark();
                 *rSearchPam.GetPoint() = *pPam->GetPoint();
                 *rSearchPam.GetMark() = *pPam->GetMark();
-                bFound = true;
                 break;
             }
             continue; // text attribute
@@ -1035,22 +1115,39 @@ static bool FindAttrsImpl(SwPaM & rSearchPam,
             continue;
 
         // no hard attribution, so check if node was asked for this attr before
-        if( !pNode->HasSwAttrSet() )
+        // (as an optimisation)
+        if (!rPropsNode.HasSwAttrSet())
         {
-            SwFormat* pTmpFormat = pNode->GetFormatColl();
+            SwFormat* pTmpFormat = rPropsNode.GetFormatColl();
             if( aFormatArr.find( pTmpFormat ) != aFormatArr.end() )
                 continue; // collection was requested earlier
             aFormatArr.insert( pTmpFormat );
         }
 
-        if( lcl_Search( *pNode, aOtherSet, bNoColls ))
+        if (lcl_Search(rPropsNode, aOtherSet, bNoColls))
         {
             // FORWARD:  SPoint at the end, GetMark at the beginning of the node
             // BACKWARD: SPoint at the beginning, GetMark at the end of the node
-            // always: incl. start and incl. end
-            *rSearchPam.GetPoint() = *pPam->GetPoint();
-            rSearchPam.SetMark();
-            pNode->MakeEndIndex( &rSearchPam.GetPoint()->nContent );
+            if (pFrame)
+            {
+                *rSearchPam.GetPoint() = *pPam->GetPoint();
+                rSearchPam.SetMark();
+                *rSearchPam.GetMark() = pFrame->MapViewToModelPos(
+                    TextFrameIndex(bSrchForward ? pFrame->GetText().getLength() : 0));
+            }
+            else
+            {
+                *rSearchPam.GetPoint() = *pPam->GetPoint();
+                rSearchPam.SetMark();
+                if (bSrchForward)
+                {
+                    pNode->MakeEndIndex( &rSearchPam.GetPoint()->nContent );
+                }
+                else
+                {
+                    pNode->MakeStartIndex( &rSearchPam.GetPoint()->nContent );
+                }
+            }
             bFound = true;
             break;
         }
@@ -1066,17 +1163,23 @@ static bool FindAttrsImpl(SwPaM & rSearchPam,
 /// parameters for search for attributes
 struct SwFindParaAttr : public SwFindParas
 {
-    bool const bValue;
+    bool const m_bNoCollection;
     const SfxItemSet *pSet, *pReplSet;
     const i18nutil::SearchOptions2 *pSearchOpt;
     SwCursor& m_rCursor;
+    SwRootFrame const* m_pLayout;
     std::unique_ptr<utl::TextSearch> pSText;
 
     SwFindParaAttr( const SfxItemSet& rSet, bool bNoCollection,
                     const i18nutil::SearchOptions2* pOpt, const SfxItemSet* pRSet,
-                    SwCursor& rCursor )
-        : bValue( bNoCollection ), pSet( &rSet ), pReplSet( pRSet ),
-          pSearchOpt( pOpt ), m_rCursor( rCursor ) {}
+                    SwCursor& rCursor, SwRootFrame const*const pLayout)
+        : m_bNoCollection(bNoCollection)
+        , pSet( &rSet )
+        , pReplSet( pRSet )
+        , pSearchOpt( pOpt )
+        , m_rCursor(rCursor)
+        , m_pLayout(pLayout)
+    {}
 
     virtual ~SwFindParaAttr()   {}
 
@@ -1106,7 +1209,7 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove,
             if( pSet->Count() ) // any attributes?
             {
                 // first attributes
-                if (!FindAttrsImpl(aSrchPam, *pSet, bValue, fnMove, aRegion, bInReadOnly, bMoveFirst))
+                if (!FindAttrsImpl(aSrchPam, *pSet, m_bNoCollection, fnMove, aRegion, bInReadOnly, bMoveFirst, m_pLayout))
                     return FIND_NOT_FOUND;
                 bMoveFirst = true;
 
@@ -1135,7 +1238,7 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove,
             // TODO: searching for attributes in Outliner text?!
 
             // continue search in correct section (pTextRegion)
-            if (sw::FindTextImpl(aSrchPam, *pSearchOpt, false/*bSearchInNotes*/, *pSText, fnMove, *pTextRegion, bInReadOnly, nullptr/*FIXME*/) &&
+            if (sw::FindTextImpl(aSrchPam, *pSearchOpt, false/*bSearchInNotes*/, *pSText, fnMove, *pTextRegion, bInReadOnly, m_pLayout) &&
                 *aSrchPam.GetMark() != *aSrchPam.GetPoint() )
                 break; // found
             else if( !pSet->Count() )
@@ -1165,10 +1268,12 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove,
         }
 
         std::unique_ptr<OUString> pRepl(bRegExp
-                ? sw::ReplaceBackReferences(*pSearchOpt, &rCursor, nullptr/*FIXME*/)
+                ? sw::ReplaceBackReferences(*pSearchOpt, &rCursor, m_pLayout)
                 : nullptr);
-        m_rCursor.GetDoc()->getIDocumentContentOperations().ReplaceRange(
-            rCursor, pRepl ? *pRepl : pSearchOpt->replaceString, bRegExp);
+        sw::ReplaceImpl(rCursor,
+                pRepl ? *pRepl : pSearchOpt->replaceString, bRegExp,
+                *m_rCursor.GetDoc(), m_pLayout);
+
         m_rCursor.SaveTableBoxContent( rCursor.GetPoint() );
 
         if( bRegExp )
@@ -1192,7 +1297,8 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove,
         // they are not in ReplaceSet
         if( !pSet->Count() )
         {
-            rCursor.GetDoc()->getIDocumentContentOperations().InsertItemSet(rCursor, *pReplSet);
+            rCursor.GetDoc()->getIDocumentContentOperations().InsertItemSet(
+                    rCursor, *pReplSet, SetAttrMode::DEFAULT, m_pLayout);
         }
         else
         {
@@ -1213,7 +1319,8 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove,
                 pItem = aIter.NextItem();
             }
             aSet.Put( *pReplSet );
-            rCursor.GetDoc()->getIDocumentContentOperations().InsertItemSet(rCursor, aSet);
+            rCursor.GetDoc()->getIDocumentContentOperations().InsertItemSet(
+                    rCursor, aSet, SetAttrMode::DEFAULT, m_pLayout);
         }
 
         return FIND_NO_RING;
@@ -1233,7 +1340,8 @@ sal_uLong SwCursor::FindAttrs( const SfxItemSet& rSet, bool bNoCollections,
                           SwDocPositions nStart, SwDocPositions nEnd,
                           bool& bCancel, FindRanges eFndRngs,
                           const i18nutil::SearchOptions2* pSearchOpt,
-                          const SfxItemSet* pReplSet )
+                          const SfxItemSet* pReplSet,
+                          SwRootFrame const*const pLayout)
 {
     // switch off OLE-notifications
     SwDoc* pDoc = GetDoc();
@@ -1250,7 +1358,7 @@ sal_uLong SwCursor::FindAttrs( const SfxItemSet& rSet, bool bNoCollections,
     }
 
     SwFindParaAttr aSwFindParaAttr( rSet, bNoCollections, pSearchOpt,
-                                    pReplSet, *this );
+                                    pReplSet, *this, pLayout );
 
     sal_uLong nRet = FindAll( aSwFindParaAttr, nStart, nEnd, eFndRngs, bCancel );
     pDoc->SetOle2Link( aLnk );
commit 0aa544b5054e76f49eb105d0c4dc3f6ec0edf8ef
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Dec 10 15:25:37 2018 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Tue Dec 18 22:30:16 2018 +0100

    sw_redlinehide_4b: FindText() adapt the replace part as well
    
    When redlining is enabled, the result will be a delete redline for the
    existing text, and an insert redline for the new text; that much is
    obious (and ReplaceRange can deal with a selection larger than one
    SwTextNode easily, since it mostly adds redlines).
    
    For the case when redlining is disabled, there are 2 options,
    and i don't really know which is preferrable from UX point of view:
    
    One approach is to reuse GetRanges() to ignore delete redlines in
    the replace range; move its declaration to different header.
    
    Another approach is to DeleteAndJoin() the existing delete redlines,
    which is the same as the previous model based Hide mode,
    which calls DeleteRedline() to remove the hidden redlines.
    
    Also change ChgAutoCorrWord() to call DeleteSelImpl() directly.
    
    Change-Id: I5974409d09eb39e04cc0b5dfc20d4db510e1cf58
    (cherry picked from commit 5e81b966778d82692b4763d892b457186a7f269d)

diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx
index fca0cc4f78f5..a5c8e1acc4d2 100644
--- a/sw/inc/crsrsh.hxx
+++ b/sw/inc/crsrsh.hxx
@@ -43,6 +43,7 @@
 class SfxItemSet;
 class SfxPoolItem;
 class SwContentFrame;
+class SwUnoCursor;
 class SwFormatField;
 class SwTextFormatColl;
 class SwTextINetFormat;
@@ -125,8 +126,19 @@ struct SwContentAtPos
 const int CRSR_POSOLD = 0x01,   // cursor stays at old position
           CRSR_POSCHG = 0x02;   // position changed by the layout
 
+namespace sw {
+
+bool ReplaceImpl(SwPaM & rCursor, OUString const& rReplacement,
+        bool const bRegExp, SwDoc & rDoc, SwRootFrame const*const pLayout);
+
 /// Helperfunction to resolve backward references in regular expressions
-OUString *ReplaceBackReferences( const i18nutil::SearchOptions2& rSearchOpt, SwPaM* pPam );
+OUString *ReplaceBackReferences(const i18nutil::SearchOptions2& rSearchOpt,
+        SwPaM* pPam, SwRootFrame const* pLayout );
+
+bool GetRanges(std::vector<std::shared_ptr<SwUnoCursor>> & rRanges,
+        SwDoc & rDoc, SwPaM const& rDelPam);
+
+} // namespace sw
 
 class SW_DLLPUBLIC SwCursorShell
     : public SwViewShell
diff --git a/sw/source/core/crsr/findattr.cxx b/sw/source/core/crsr/findattr.cxx
index 9da44ada4dfe..500d4628ad27 100644
--- a/sw/source/core/crsr/findattr.cxx
+++ b/sw/source/core/crsr/findattr.cxx
@@ -1164,8 +1164,9 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove,
             const_cast<SwPaM &>(rRegion).GetRingContainer().merge( m_rCursor.GetRingContainer() );
         }
 
-        std::unique_ptr<OUString> pRepl( bRegExp ?
-                ReplaceBackReferences(*pSearchOpt, &rCursor) : nullptr );
+        std::unique_ptr<OUString> pRepl(bRegExp
+                ? sw::ReplaceBackReferences(*pSearchOpt, &rCursor, nullptr/*FIXME*/)
+                : nullptr);
         m_rCursor.GetDoc()->getIDocumentContentOperations().ReplaceRange(
             rCursor, pRepl ? *pRepl : pSearchOpt->replaceString, bRegExp);
         m_rCursor.SaveTableBoxContent( rCursor.GetPoint() );
diff --git a/sw/source/core/crsr/findtxt.cxx b/sw/source/core/crsr/findtxt.cxx
index 85c6cb7fd11a..f45516361c2d 100644
--- a/sw/source/core/crsr/findtxt.cxx
+++ b/sw/source/core/crsr/findtxt.cxx
@@ -36,11 +36,14 @@
 #include <txtatr.hxx>
 #include <txtfld.hxx>
 #include <txtfrm.hxx>
+#include <rootfrm.hxx>
 #include <swcrsr.hxx>
+#include <redline.hxx>
 #include <doc.hxx>
 #include <IDocumentUndoRedo.hxx>
 #include <IDocumentState.hxx>
 #include <IDocumentDrawModelAccess.hxx>
+#include <IDocumentRedlineAccess.hxx>
 #include <dcontact.hxx>
 #include <pamtyp.hxx>
 #include <ndtxt.hxx>
@@ -940,9 +943,12 @@ int SwFindParaText::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove,
         }
 
         std::unique_ptr<OUString> pRepl( bRegExp
-                ? ReplaceBackReferences(m_rSearchOpt, &rCursor) : nullptr );
-        bool const bReplaced = m_rCursor.GetDoc()->getIDocumentContentOperations().ReplaceRange(
-            rCursor, pRepl ? *pRepl : m_rSearchOpt.replaceString, bRegExp);
+                ? sw::ReplaceBackReferences(m_rSearchOpt, &rCursor, m_pLayout)
+                : nullptr );
+        bool const bReplaced = sw::ReplaceImpl(rCursor,
+                pRepl ? *pRepl : m_rSearchOpt.replaceString,
+                bRegExp, *m_rCursor.GetDoc(), m_pLayout);
+
         m_rCursor.SaveTableBoxContent( rCursor.GetPoint() );
 
         if( bRegExp )
@@ -1009,22 +1015,115 @@ sal_uLong SwCursor::Find_Text( const i18nutil::SearchOptions2& rSearchOpt, bool
     return nRet;
 }
 
-OUString *ReplaceBackReferences( const i18nutil::SearchOptions2& rSearchOpt, SwPaM* pPam )
+namespace sw {
+
+bool ReplaceImpl(
+        SwPaM & rCursor,
+        OUString const& rReplacement,
+        bool const bRegExp,
+        SwDoc & rDoc,
+        SwRootFrame const*const pLayout)
+{
+    bool bReplaced(true);
+    IDocumentContentOperations & rIDCO(rDoc.getIDocumentContentOperations());
+#if 0
+    // FIXME there's some problem with multiple redlines here on Undo
+    std::vector<std::shared_ptr<SwUnoCursor>> ranges;
+    if (rDoc.getIDocumentRedlineAccess().IsRedlineOn()
+        || !pLayout
+        || !pLayout->IsHideRedlines()
+        || sw::GetRanges(ranges, rDoc, rCursor))
+    {
+        bReplaced = rIDCO.ReplaceRange(rCursor, rReplacement, bRegExp);
+    }
+    else
+    {
+        assert(!ranges.empty());
+        assert(ranges.front()->GetPoint()->nNode == ranges.front()->GetMark()->nNode);
+        bReplaced = rIDCO.ReplaceRange(*ranges.front(), rReplacement, bRegExp);
+        for (auto it = ranges.begin() + 1; it != ranges.end(); ++it)
+        {
+            bReplaced &= rIDCO.DeleteAndJoin(**it);
+        }
+    }
+#else
+    IDocumentRedlineAccess const& rIDRA(rDoc.getIDocumentRedlineAccess());
+    if (pLayout && pLayout->IsHideRedlines()
+        && !rIDRA.IsRedlineOn() // otherwise: ReplaceRange will handle it
+        && (rIDRA.GetRedlineFlags() & RedlineFlags::ShowDelete)) // otherwise: ReplaceRange will DeleteRedline()
+    {
+        SwRedlineTable::size_type tmp;
+        rIDRA.GetRedline(*rCursor.Start(), &tmp);
+        while (tmp < rIDRA.GetRedlineTable().size())
+        {
+            SwRangeRedline const*const pRedline(rIDRA.GetRedlineTable()[tmp]);
+            if (*rCursor.End() <= *pRedline->Start())
+            {
+                break;
+            }
+            if (*pRedline->End() <= *rCursor.Start())
+            {
+                ++tmp;
+                continue;
+            }
+            if (pRedline->GetType() == nsRedlineType_t::REDLINE_DELETE)
+            {
+                assert(*pRedline->Start() != *pRedline->End());
+                // search in hidden layout can't overlap redlines
+                assert(*rCursor.Start() <= *pRedline->Start() && *pRedline->End() <= *rCursor.End());
+                SwPaM pam(*pRedline, nullptr);
+                bReplaced &= rIDCO.DeleteAndJoin(pam);
+            }
+            else
+            {
+                ++tmp;
+            }
+        }
+    }
+    bReplaced &= rIDCO.ReplaceRange(rCursor, rReplacement, bRegExp);
+#endif
+    return bReplaced;
+}
+
+OUString *ReplaceBackReferences(const i18nutil::SearchOptions2& rSearchOpt,
+        SwPaM *const pPam, SwRootFrame const*const pLayout)
 {
     OUString *pRet = nullptr;
     if( pPam && pPam->HasMark() &&
         SearchAlgorithms2::REGEXP == rSearchOpt.AlgorithmType2 )
     {
         const SwContentNode* pTextNode = pPam->GetContentNode();
+        if (!pTextNode || !pTextNode->IsTextNode())
+        {
+            return pRet;
+        }
+        SwTextFrame const*const pFrame(pLayout
+            ? static_cast<SwTextFrame const*>(pTextNode->getLayoutFrame(pLayout))
+            : nullptr);
         const bool bParaEnd = rSearchOpt.searchString == "$" || rSearchOpt.searchString == "^$" || rSearchOpt.searchString == "$^";
-        if ( pTextNode && pTextNode->IsTextNode() && (bParaEnd || pTextNode == pPam->GetContentNode( false )) )
+        if (bParaEnd || (pLayout
+                ? sw::FrameContainsNode(*pFrame, pPam->GetMark()->nNode.GetIndex())
+                : pTextNode == pPam->GetContentNode(false)))
         {
             utl::TextSearch aSText( utl::TextSearch::UpgradeToSearchOptions2( rSearchOpt) );
-            OUString rStr = pTextNode->GetTextNode()->GetText();
-            sal_Int32 nStart = pPam->Start()->nContent.GetIndex();
-            sal_Int32 nEnd = pPam->End()->nContent.GetIndex();
+            OUString rStr = pLayout
+                ? pFrame->GetText()
+                : pTextNode->GetTextNode()->GetText();
+            AmbiguousIndex nStart;
+            AmbiguousIndex nEnd;
+            if (pLayout)
+            {
+                nStart.SetFrameIndex(pFrame->MapModelToViewPos(*pPam->Start()));
+                nEnd.SetFrameIndex(pFrame->MapModelToViewPos(*pPam->End()));
+            }
+            else
+            {
+                nStart.SetModelIndex(pPam->Start()->nContent.GetIndex());
+                nEnd.SetModelIndex(pPam->End()->nContent.GetIndex());
+            }
             SearchResult aResult;
-            if ( bParaEnd || aSText.SearchForward( rStr, &nStart, &nEnd, &aResult ) )
+            if (bParaEnd ||
+                aSText.SearchForward(rStr, &nStart.GetAnyIndex(), &nEnd.GetAnyIndex(), &aResult))
             {
                 if ( bParaEnd )
                 {
@@ -1044,4 +1143,6 @@ OUString *ReplaceBackReferences( const i18nutil::SearchOptions2& rSearchOpt, SwP
     return pRet;
 }
 
+} // namespace sw
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx
index ceb468b7b1ae..45508b9ac8a7 100644
--- a/sw/source/core/doc/DocumentContentOperationsManager.cxx
+++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx
@@ -4062,10 +4062,6 @@ bool DocumentContentOperationsManager::ReplaceRangeImpl( SwPaM& rPam, const OUSt
 
         SwPosition *pStt = aDelPam.Start(),
                    *pEnd = aDelPam.End();
-        OSL_ENSURE( pStt->nNode == pEnd->nNode ||
-                ( pStt->nNode.GetIndex() + 1 == pEnd->nNode.GetIndex() &&
-                    !pEnd->nContent.GetIndex() ),
-                "invalid range: Point and Mark on different nodes" );
         bool bOneNode = pStt->nNode == pEnd->nNode;
 
         // Own Undo?
@@ -4201,6 +4197,11 @@ bool DocumentContentOperationsManager::ReplaceRangeImpl( SwPaM& rPam, const OUSt
         }
         else
         {
+            assert((pStt->nNode == pEnd->nNode ||
+                    ( pStt->nNode.GetIndex() + 1 == pEnd->nNode.GetIndex() &&
+                        !pEnd->nContent.GetIndex() )) &&
+                    "invalid range: Point and Mark on different nodes" );
+
             if( !m_rDoc.getIDocumentRedlineAccess().IsIgnoreRedline() && !m_rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty() )
                 m_rDoc.getIDocumentRedlineAccess().DeleteRedline( aDelPam, true, USHRT_MAX );
 
diff --git a/sw/source/core/edit/acorrect.cxx b/sw/source/core/edit/acorrect.cxx
index e5ca4d63c69b..eaf61bec0451 100644
--- a/sw/source/core/edit/acorrect.cxx
+++ b/sw/source/core/edit/acorrect.cxx
@@ -416,7 +416,7 @@ bool SwAutoCorrDoc::ChgAutoCorrWord( sal_Int32& rSttPos, sal_Int32 nEndPos,
                             *ranges.front(), pFnd->GetLong(), false);
                     for (auto it = ranges.begin() + 1; it != ranges.end(); ++it)
                     {
-                        DeleteSel(**it);
+                        DeleteSelImpl(**it);
                     }
                 }
 
diff --git a/sw/source/core/edit/eddel.cxx b/sw/source/core/edit/eddel.cxx
index 126b5000a923..1a37235190a9 100644
--- a/sw/source/core/edit/eddel.cxx
+++ b/sw/source/core/edit/eddel.cxx
@@ -22,9 +22,11 @@
 #include <doc.hxx>
 #include <IDocumentUndoRedo.hxx>
 #include <IDocumentContentOperations.hxx>
+#include <IDocumentRedlineAccess.hxx>
 #include <editsh.hxx>
 #include <cntfrm.hxx>
 #include <pam.hxx>
+#include <unocrsr.hxx>
 #include <swundo.hxx>
 #include <edimp.hxx>
 #include <IMark.hxx>
@@ -318,7 +320,7 @@ bool SwEditShell::Replace( const OUString& rNewStr, bool bRegExpRplc )
         {
             if( rPaM.HasMark() && *rPaM.GetMark() != *rPaM.GetPoint() )
             {
-                bRet = GetDoc()->getIDocumentContentOperations().ReplaceRange( rPaM, rNewStr, bRegExpRplc )
+                bRet = sw::ReplaceImpl(rPaM, rNewStr, bRegExpRplc, *GetDoc(), GetLayout())
                     || bRet;
                 SaveTableBoxContent( rPaM.GetPoint() );
             }
diff --git a/sw/source/core/inc/acorrect.hxx b/sw/source/core/inc/acorrect.hxx
index 73f63c1ebac8..39bd19e91584 100644
--- a/sw/source/core/inc/acorrect.hxx
+++ b/sw/source/core/inc/acorrect.hxx
@@ -21,14 +21,11 @@
 #define INCLUDED_SW_SOURCE_CORE_INC_ACORRECT_HXX
 
 #include <memory>
-#include <vector>
 
 #include <tools/solar.h>
 #include <editeng/svxacorr.hxx>
 #include <swundo.hxx>
 
-class SwDoc;
-class SwUnoCursor;
 class SwEditShell;
 class SwPaM;
 class SwNodeIndex;
@@ -116,13 +113,6 @@ public:
     bool CheckDelChar(const SwPosition& rPos);
 };
 
-namespace sw {
-
-bool GetRanges(std::vector<std::shared_ptr<SwUnoCursor>> & rRanges,
-        SwDoc & rDoc, SwPaM const& rDelPam);
-
-} // namespace sw
-
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/viewsrch.cxx b/sw/source/uibase/uiview/viewsrch.cxx
index 09fd18015ae6..96b1708eb4be 100644
--- a/sw/source/uibase/uiview/viewsrch.cxx
+++ b/sw/source/uibase/uiview/viewsrch.cxx
@@ -309,7 +309,8 @@ void SwView::ExecSearch(SfxRequest& rReq)
                             m_pWrtShell->Push();
                         OUString aReplace( m_pSrchItem->GetReplaceString() );
                         i18nutil::SearchOptions2 aTmp( m_pSrchItem->GetSearchOptions() );
-                        OUString *pBackRef = ReplaceBackReferences( aTmp, m_pWrtShell->GetCursor() );
+                        OUString *pBackRef = sw::ReplaceBackReferences(aTmp,
+                            m_pWrtShell->GetCursor(), m_pWrtShell->GetLayout());
                         if( pBackRef )
                             m_pSrchItem->SetReplaceString( *pBackRef );
                         Replace();
commit 71531cf13471993333373161d01577a637460fe8
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Dec 4 15:57:47 2018 +0100
Commit:     Thorsten Behrens <Thorsten.Behrens at CIB.de>
CommitDate: Tue Dec 18 22:30:16 2018 +0100

    sw_redlinehide_4b: adapt FindText()
    
    Generally speaking, the find functions should find the strings that are
    visible in the document view.  However, they may also be called from
    SwXTextDocument functions, where they ought to find the strings that are
    actually in the document model.
    
    So concoct some funny helper types and adapt this so it can handle both
    cases; it's not pretty but maybe it even works.
    
    Change-Id: I1917398ff928e922673353e75e8fb724dc042031
    (cherry picked from commit 77e67e7cd2baeca13c357fbda4c44a90db23de11)

diff --git a/sw/inc/swcrsr.hxx b/sw/inc/swcrsr.hxx
index 2ae2f58924d2..cd07cafdf46a 100644
--- a/sw/inc/swcrsr.hxx
+++ b/sw/inc/swcrsr.hxx
@@ -117,7 +117,8 @@ public:
                 SwDocPositions nStart, SwDocPositions nEnde,
                 bool& bCancel,
                 FindRanges,
-                bool bReplace = false );
+                bool bReplace = false,
+                SwRootFrame const*const pLayout = nullptr);
     sal_uLong FindFormat( const SwTextFormatColl& rFormatColl,
                 SwDocPositions nStart, SwDocPositions nEnde,
                 bool& bCancel,
diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 335d44ea6fcf..1085a34a655f 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -3328,7 +3328,7 @@ sal_uLong SwCursorShell::Find_Text( const i18nutil::SearchOptions2& rSearchOpt,
     m_pTableCursor = nullptr;
     SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed
     sal_uLong nRet = m_pCurrentCursor->Find_Text(rSearchOpt, bSearchInNotes, eStart, eEnd,
-                                     bCancel, eRng, bReplace );
+                                     bCancel, eRng, bReplace, GetLayout());
     if( nRet || bCancel )
         UpdateCursor();
     return nRet;
diff --git a/sw/source/core/crsr/findattr.cxx b/sw/source/core/crsr/findattr.cxx
index 4999c07d734b..9da44ada4dfe 100644
--- a/sw/source/core/crsr/findattr.cxx
+++ b/sw/source/core/crsr/findattr.cxx
@@ -1135,7 +1135,7 @@ int SwFindParaAttr::DoFind(SwPaM & rCursor, SwMoveFnCollection const & fnMove,
             // TODO: searching for attributes in Outliner text?!
 
             // continue search in correct section (pTextRegion)
-            if (sw::FindTextImpl(aSrchPam, *pSearchOpt, false/*bSearchInNotes*/, *pSText, fnMove, *pTextRegion, bInReadOnly) &&
+            if (sw::FindTextImpl(aSrchPam, *pSearchOpt, false/*bSearchInNotes*/, *pSText, fnMove, *pTextRegion, bInReadOnly, nullptr/*FIXME*/) &&
                 *aSrchPam.GetMark() != *aSrchPam.GetPoint() )
                 break; // found
             else if( !pSet->Count() )
diff --git a/sw/source/core/crsr/findtxt.cxx b/sw/source/core/crsr/findtxt.cxx
index 85a77e86f772..85c6cb7fd11a 100644
--- a/sw/source/core/crsr/findtxt.cxx
+++ b/sw/source/core/crsr/findtxt.cxx
@@ -35,6 +35,7 @@
 #include <fmtfld.hxx>
 #include <txtatr.hxx>
 #include <txtfld.hxx>
+#include <txtfrm.hxx>
 #include <swcrsr.hxx>
 #include <doc.hxx>
 #include <IDocumentUndoRedo.hxx>
@@ -54,59 +55,198 @@
 using namespace ::com::sun::star;
 using namespace util;
 
+/// because the Find may be called on the View or the Model, we need an index
+/// afflicted by multiple personality disorder
+struct AmbiguousIndex
+{
+private:
+    sal_Int32 m_value;
+
+#ifndef NDEBUG
+    enum class tags : char { Any, Frame, Model };
+    tags m_tag;
+#endif
+
+public:
+    AmbiguousIndex() : m_value(-1)
+#ifndef NDEBUG
+           , m_tag(tags::Any)
+#endif
+    {}
+    explicit AmbiguousIndex(sal_Int32 const value
+#ifndef NDEBUG
+            , tags const tag
+#endif
+        )   : m_value(value)
+#ifndef NDEBUG
+            , m_tag(tag)
+#endif
+    {}
+
+    sal_Int32 & GetAnyIndex() { return m_value; } ///< for arithmetic
+    sal_Int32 const& GetAnyIndex() const { return m_value; } ///< for arithmetic
+    TextFrameIndex GetFrameIndex() const
+    {
+        assert(m_tag != tags::Model);
+        return TextFrameIndex(m_value);
+    }
+    sal_Int32 GetModelIndex() const
+    {
+        assert(m_tag != tags::Frame);
+        return m_value;
+    }
+    void SetFrameIndex(TextFrameIndex const value)
+    {
+#ifndef NDEBUG
+        m_tag = tags::Frame;
+#endif
+        m_value = sal_Int32(value);
+    }
+    void SetModelIndex(sal_Int32 const value)
+    {
+#ifndef NDEBUG
+        m_tag = tags::Model;
+#endif
+        m_value = value;
+    }
+
+    bool operator ==(AmbiguousIndex const& rOther) const
+    {
+        assert(m_tag == tags::Any || rOther.m_tag == tags::Any || m_tag == rOther.m_tag);
+        return m_value == rOther.m_value;
+    }
+    bool operator <=(AmbiguousIndex const& rOther) const
+    {
+        assert(m_tag == tags::Any || rOther.m_tag == tags::Any || m_tag == rOther.m_tag);
+        return m_value <= rOther.m_value;
+    }
+    bool operator < (AmbiguousIndex const& rOther) const
+    {
+        assert(m_tag == tags::Any || rOther.m_tag == tags::Any || m_tag == rOther.m_tag);
+        return m_value <  rOther.m_value;
+    }
+    AmbiguousIndex operator - (AmbiguousIndex const& rOther) const
+    {
+        assert(m_tag == tags::Any || rOther.m_tag == tags::Any || m_tag == rOther.m_tag);
+        return AmbiguousIndex(m_value - rOther.m_value
+#ifndef NDEBUG
+                , std::max(m_tag, rOther.m_tag)
+#endif
+            );
+    }
+};
+
+class MaybeMergedIter
+{
+    boost::optional<sw::MergedAttrIter> m_oMergedIter;
+    SwTextNode const*const m_pNode;
+    size_t m_HintIndex;
+
+public:
+    MaybeMergedIter(SwTextFrame const*const pFrame, SwTextNode const*const pNode)
+        : m_pNode(pNode)
+        , m_HintIndex(0)
+    {
+        if (pFrame)
+        {
+            m_oMergedIter.emplace(*pFrame);
+        }
+    }
+
+    SwTextAttr const* NextAttr(SwTextNode const*& rpNode)
+    {
+        if (m_oMergedIter)
+        {
+            return m_oMergedIter->NextAttr(&rpNode);
+        }
+        if (SwpHints const*const pHints = m_pNode->GetpSwpHints())
+        {
+            if (m_HintIndex < pHints->Count())
+            {
+                rpNode = m_pNode;
+                return pHints->Get(m_HintIndex++);
+            }
+        }
+        return nullptr;
+    }
+};
+
 static OUString
-lcl_CleanStr(const SwTextNode& rNd, sal_Int32 const nStart, sal_Int32& rEnd,
-             std::vector<sal_Int32> &rArr, bool const bRemoveSoftHyphen, bool const bRemoveCommentAnchors)
+lcl_CleanStr(const SwTextNode& rNd,
+             SwTextFrame const*const pFrame,
+             SwRootFrame const*const pLayout,
+             AmbiguousIndex const nStart, AmbiguousIndex & rEnd,
+             std::vector<AmbiguousIndex> &rArr,
+             bool const bRemoveSoftHyphen, bool const bRemoveCommentAnchors)
 {
-    OUStringBuffer buf(rNd.GetText());
+    OUStringBuffer buf(pLayout ? pFrame->GetText() : rNd.GetText());
     rArr.clear();
 
-    const SwpHints *pHts = rNd.GetpSwpHints();
+    MaybeMergedIter iter(pLayout ? pFrame : nullptr, pLayout ? nullptr : &rNd);
 
-    size_t n = 0;
-    sal_Int32 nSoftHyphen = nStart;
-    sal_Int32 nHintStart = -1;
+    AmbiguousIndex nSoftHyphen = nStart;
+    AmbiguousIndex nHintStart;
     bool bNewHint       = true;
     bool bNewSoftHyphen = true;
-    const sal_Int32 nEnd = rEnd;
-    std::vector<sal_Int32> aReplaced;
+    const AmbiguousIndex nEnd = rEnd;
+    std::vector<AmbiguousIndex> aReplaced;
+    SwTextNode const* pNextHintNode(nullptr);
+    SwTextAttr const* pNextHint(iter.NextAttr(pNextHintNode));
 
     do
     {
         if ( bNewHint )
-            nHintStart = pHts && n < pHts->Count() ?
-                         pHts->Get(n)->GetStart() :
-                         -1;
+        {
+            if (pLayout)
+            {
+                nHintStart.SetFrameIndex(pNextHint
+                        ? pFrame->MapModelToView(pNextHintNode, pNextHint->GetStart())
+                        : TextFrameIndex(-1));
+            }
+            else
+            {
+                nHintStart.SetModelIndex(pNextHint ? pNextHint->GetStart() : -1);
+            }
+        }
 
         if ( bNewSoftHyphen )
         {
-            nSoftHyphen = bRemoveSoftHyphen
-                    ?  rNd.GetText().indexOf(CHAR_SOFTHYPHEN, nSoftHyphen)
-                    : -1;
+            if (pLayout)
+            {
+                nSoftHyphen.SetFrameIndex(TextFrameIndex(bRemoveSoftHyphen
+                    ? pFrame->GetText().indexOf(CHAR_SOFTHYPHEN, nSoftHyphen.GetAnyIndex())
+                    : -1));
+            }
+            else
+            {
+                nSoftHyphen.SetModelIndex(bRemoveSoftHyphen
+                    ? rNd.GetText().indexOf(CHAR_SOFTHYPHEN, nSoftHyphen.GetAnyIndex())
+                    : -1);
+            }
         }
 
         bNewHint       = false;
         bNewSoftHyphen = false;
-        sal_Int32 nStt = 0;
+        AmbiguousIndex nStt;
 
         // Check if next stop is a hint.
-        if ( nHintStart>=0
-            && (-1 == nSoftHyphen || nHintStart < nSoftHyphen)
+        if (0 <= nHintStart.GetAnyIndex()
+            && (-1 == nSoftHyphen.GetAnyIndex() || nHintStart < nSoftHyphen)
             && nHintStart < nEnd )
         {
             nStt = nHintStart;
             bNewHint = true;
         }
         // Check if next stop is a soft hyphen.
-        else if (   -1 != nSoftHyphen
-                 && (-1 == nHintStart || nSoftHyphen < nHintStart)
+        else if (   -1 != nSoftHyphen.GetAnyIndex()
+                 && (-1 == nHintStart.GetAnyIndex() || nSoftHyphen < nHintStart)
                  && nSoftHyphen < nEnd)
         {
             nStt = nSoftHyphen;
             bNewSoftHyphen = true;
         }
         // If nSoftHyphen == nHintStart, the current hint *must* be a hint with an end.
-        else if (-1 != nSoftHyphen && nSoftHyphen == nHintStart)
+        else if (-1 != nSoftHyphen.GetAnyIndex() && nSoftHyphen == nHintStart)
         {
             nStt = nSoftHyphen;
             bNewHint = true;
@@ -115,14 +255,14 @@ lcl_CleanStr(const SwTextNode& rNd, sal_Int32 const nStart, sal_Int32& rEnd,
         else
             break;
 
-        const sal_Int32 nCurrent = nStt - rArr.size();
+        AmbiguousIndex nCurrent(nStt);
+        nCurrent.GetAnyIndex() -= rArr.size();
 
         if ( bNewHint )
         {
-            const SwTextAttr* pHt = pHts->Get(n);
-            if ( pHt->HasDummyChar() && (nStt >= nStart) )
+            if (pNextHint->HasDummyChar() && (nStart <= nStt))
             {
-                switch( pHt->Which() )
+                switch (pNextHint->Which())
                 {
                 case RES_TXTATR_FLYCNT:
                 case RES_TXTATR_FTN:
@@ -139,19 +279,19 @@ lcl_CleanStr(const SwTextNode& rNd, sal_Int32 const nStart, sal_Int32& rEnd,
                         // simply removed if first. If at the end, we keep the
                         // replacement and remove afterwards all at a string's
                         // end (might be normal 0x7f).
-                        const bool bEmpty = pHt->Which() != RES_TXTATR_FIELD
-                            || (static_txtattr_cast<SwTextField const*>(pHt)->GetFormatField().GetField()->ExpandField(true, nullptr).isEmpty());
+                        const bool bEmpty = pNextHint->Which() != RES_TXTATR_FIELD
+                            || (static_txtattr_cast<SwTextField const*>(pNextHint)->GetFormatField().GetField()->ExpandField(true, pLayout).isEmpty());
                         if ( bEmpty && nStart == nCurrent )
                         {
                             rArr.push_back( nCurrent );
-                            --rEnd;
-                            buf.remove(nCurrent, 1);
+                            --rEnd.GetAnyIndex();
+                            buf.remove(nCurrent.GetAnyIndex(), 1);
                         }
                         else
                         {
                             if ( bEmpty )
                                 aReplaced.push_back( nCurrent );
-                            buf[nCurrent] = '\x7f';
+                            buf[nCurrent.GetAnyIndex()] = '\x7f';
                         }
                     }
                     break;
@@ -160,8 +300,8 @@ lcl_CleanStr(const SwTextNode& rNd, sal_Int32 const nStart, sal_Int32& rEnd,
                         if( bRemoveCommentAnchors )
                         {
                             rArr.push_back( nCurrent );
-                            --rEnd;
-                            buf.remove( nCurrent, 1 );
+                            --rEnd.GetAnyIndex();
+                            buf.remove( nCurrent.GetAnyIndex(), 1 );
                         }
                     }
                     break;
@@ -170,69 +310,40 @@ lcl_CleanStr(const SwTextNode& rNd, sal_Int32 const nStart, sal_Int32& rEnd,
                     break;
                 }
             }
-            ++n;
+            pNextHint = iter.NextAttr(pNextHintNode);
         }
 
         if ( bNewSoftHyphen )
         {
             rArr.push_back( nCurrent );
-            --rEnd;
-            buf.remove(nCurrent, 1);
-            ++nSoftHyphen;
+            --rEnd.GetAnyIndex();
+            buf.remove(nCurrent.GetAnyIndex(), 1);
+            ++nSoftHyphen.GetAnyIndex();
         }
     }
     while ( true );
 
-    for( std::vector<sal_Int32>::size_type i = aReplaced.size(); i; )
+    for (auto i = aReplaced.size(); i; )
     {
-        const sal_Int32 nTmp = aReplaced[ --i ];
-        if (nTmp == buf.getLength() - 1)
+        const AmbiguousIndex nTmp = aReplaced[ --i ];
+        if (nTmp.GetAnyIndex() == buf.getLength() - 1)
         {
-            buf.truncate(nTmp);
+            buf.truncate(nTmp.GetAnyIndex());
             rArr.push_back( nTmp );
-            --rEnd;
+            --rEnd.GetAnyIndex();
         }
     }
 
     return buf.makeStringAndClear();
 }
 
-// skip all non SwPostIts inside the array
-static size_t GetPostIt(sal_Int32 aCount,const SwpHints *pHts)
-{
-    size_t aIndex = 0;
-    while (aCount)
-    {
-        for (size_t i = 0; i < pHts->Count(); ++i )
-        {
-            aIndex++;
-            const SwTextAttr* pTextAttr = pHts->Get(i);
-            if ( pTextAttr->Which() == RES_TXTATR_ANNOTATION )
-            {
-                aCount--;
-                if (!aCount)
-                    break;
-            }
-        }
-    }
-    // throw away all following non postits
-    for( size_t i = aIndex; i < pHts->Count(); ++i )
-    {
-        const SwTextAttr* pTextAttr = pHts->Get(i);
-        if ( pTextAttr->Which() == RES_TXTATR_ANNOTATION )
-            break;
-        else
-            aIndex++;
-    }
-    return aIndex;
-}
-
 static bool DoSearch(SwPaM & rSearchPam,
     const i18nutil::SearchOptions2& rSearchOpt, utl::TextSearch& rSText,
     SwMoveFnCollection const & fnMove,
     bool bSrchForward, bool bRegSearch, bool bChkEmptyPara, bool bChkParaEnd,
-    sal_Int32 &nStart, sal_Int32 &nEnd, sal_Int32 nTextLen, SwNode* pNode,
-    SwPaM* pPam);
+    AmbiguousIndex & nStart, AmbiguousIndex & nEnd, AmbiguousIndex nTextLen,
+    SwTextNode const* pNode, SwTextFrame const* pTextFrame,
+    SwRootFrame const* pLayout, SwPaM* pPam);
 
 namespace sw {
 
@@ -240,7 +351,7 @@ bool FindTextImpl(SwPaM & rSearchPam,
         const i18nutil::SearchOptions2& rSearchOpt, bool bSearchInNotes,
         utl::TextSearch& rSText,
         SwMoveFnCollection const & fnMove, const SwPaM & rRegion,
-        bool bInReadOnly)
+        bool bInReadOnly, SwRootFrame const*const pLayout)
 {
     if( rSearchOpt.searchString.isEmpty() )
         return false;
@@ -267,47 +378,95 @@ bool FindTextImpl(SwPaM & rSearchPam,
     aSearchItem.SetBackward(!bSrchForward);
 
     // LanguageType eLastLang = 0;
-    while( nullptr != ( pNode = ::GetNode( *pPam, bFirst, fnMove, bInReadOnly ) ))
+    while (nullptr != (pNode = ::GetNode(*pPam, bFirst, fnMove, bInReadOnly, pLayout)))
     {
         if( pNode->IsTextNode() )
         {
             SwTextNode& rTextNode = *pNode->GetTextNode();
-            sal_Int32 nTextLen = rTextNode.GetText().getLength();
-            sal_Int32 nEnd;
-            if( rNdIdx == pPam->GetMark()->nNode )
-                nEnd = pPam->GetMark()->nContent.GetIndex();
+            SwTextFrame const*const pFrame(pLayout
+                ? static_cast<SwTextFrame const*>(rTextNode.getLayoutFrame(pLayout))
+                : nullptr);
+            assert(!pLayout || pFrame);
+            AmbiguousIndex nTextLen;
+            if (pLayout)
+            {
+                nTextLen.SetFrameIndex(TextFrameIndex(pFrame->GetText().getLength()));
+            }
             else
-                nEnd = bSrchForward ? nTextLen : 0;
-            sal_Int32 nStart = rContentIdx.GetIndex();
+            {
+                nTextLen.SetModelIndex(rTextNode.GetText().getLength());
+            }
+            AmbiguousIndex nEnd;
+            if (pLayout
+                    ? FrameContainsNode(*pFrame, pPam->GetMark()->nNode.GetIndex())
+                    : rNdIdx == pPam->GetMark()->nNode)
+            {
+                if (pLayout)
+                {
+                    nEnd.SetFrameIndex(pFrame->MapModelToViewPos(*pPam->GetMark()));
+                }
+                else
+                {
+                    nEnd.SetModelIndex(pPam->GetMark()->nContent.GetIndex());
+                }
+            }
+            else
+            {
+                if (bSrchForward)
+                {
+                    nEnd = nTextLen;
+                }
+                else
+                {
+                    if (pLayout)
+                    {
+                        nEnd.SetFrameIndex(TextFrameIndex(0));
+                    }
+                    else
+                    {
+                        nEnd.SetModelIndex(0);
+                    }
+                }
+            }
+            AmbiguousIndex nStart;
+            if (pLayout)
+            {
+                nStart.SetFrameIndex(pFrame->MapModelToViewPos(*pPam->GetPoint()));
+            }
+            else
+            {
+                nStart.SetModelIndex(rContentIdx.GetIndex());
+            }
 
             /* #i80135# */
             // if there are SwPostItFields inside our current node text, we
             // split the text into separate pieces and search for text inside
             // the pieces as well as inside the fields
-            const SwpHints *pHts = rTextNode.GetpSwpHints();
+            MaybeMergedIter iter(pLayout ? pFrame : nullptr, pLayout ? nullptr : &rTextNode);
 
             // count PostItFields by looping over all fields
-            sal_Int32 aNumberPostits = 0;
-            sal_Int32 aIgnore = 0;
-            if (pHts && bSearchInNotes)
+            std::vector<std::pair<SwTextAttr const*, AmbiguousIndex>> postits;
+            if (bSearchInNotes)
             {
                 if (!bSrchForward)
                 {
                     std::swap(nStart, nEnd);
                 }
 
-                for( size_t i = 0; i < pHts->Count(); ++i )
+                SwTextNode const* pTemp(nullptr);
+                while (SwTextAttr const*const pTextAttr = iter.NextAttr(pTemp))
                 {
-                    const SwTextAttr* pTextAttr = pHts->Get(i);
                     if ( pTextAttr->Which()==RES_TXTATR_ANNOTATION )
                     {
-                        const sal_Int32 aPos = pTextAttr->GetStart();
-                        if ( (aPos >= nStart) && (aPos <= nEnd) )
-                            aNumberPostits++;
-                        else
+                        AmbiguousIndex aPos;
+                        aPos.SetModelIndex(pTextAttr->GetStart());
+                        if (pLayout)
+                        {
+                            aPos.SetFrameIndex(pFrame->MapModelToView(pTemp, aPos.GetModelIndex()));
+                        }
+                        if ((nStart <= aPos) && (aPos <= nEnd))
                         {

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list