[Libreoffice-commits] core.git: Branch 'private/mst/sw_redlinehide_3' - 22 commits - sw/inc sw/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Mon Oct 15 14:03:31 UTC 2018


Rebased ref, commits from common ancestor:
commit 663a185104b7dbc942859621f51068d50b479fa4
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Mon Oct 15 15:24:08 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: fix SwAccessibleParagraph not being disposed
    
    If it is merged, it doesn't have GetDep().
    
    Change-Id: I5a362c03fe7fcb0a6246aef0a0ac2824c48ede36

diff --git a/sw/source/core/layout/ssfrm.cxx b/sw/source/core/layout/ssfrm.cxx
index 8550f4a7f4f6..bdec06fb726c 100644
--- a/sw/source/core/layout/ssfrm.cxx
+++ b/sw/source/core/layout/ssfrm.cxx
@@ -325,8 +325,10 @@ void SwFrame::DestroyImpl()
 
     // accessible objects for fly and cell frames have been already disposed
     // by the destructors of the derived classes.
-    if( IsAccessibleFrame() && !(IsFlyFrame() || IsCellFrame()) && GetDep() )
+    if (IsAccessibleFrame() && !(IsFlyFrame() || IsCellFrame())
+        && (GetDep() || IsTextFrame())) // sw_redlinehide: text frame may not have Dep!
     {
+        assert(!IsTextFrame() || GetDep() || static_cast<SwTextFrame*>(this)->GetMergedPara());
         SwRootFrame *pRootFrame = getRootFrame();
         if( pRootFrame && pRootFrame->IsAnyShellAccessible() )
         {
commit 877ca8d821ec300810a76d1a2ddb2e409d225540
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Oct 12 16:33:00 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: fix crash when storing clipboard document
    
    It doesn't have a layout, of course.
    
    Change-Id: Iec4809ec4a14e1fa9852d09619a8b344419b29e7

diff --git a/sw/source/filter/xml/wrtxml.cxx b/sw/source/filter/xml/wrtxml.cxx
index df75d14868db..0d5e53d4c319 100644
--- a/sw/source/filter/xml/wrtxml.cxx
+++ b/sw/source/filter/xml/wrtxml.cxx
@@ -189,7 +189,8 @@ ErrCode SwXMLWriter::Write_( const uno::Reference < task::XStatusIndicator >& xS
     bool isShowChanges;
     if (officecfg::Office::Common::Misc::ExperimentalMode::get(xContext))
     {   // TODO: ideally this would be stored per-view...
-        isShowChanges = !m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout()->IsHideRedlines();
+        SwRootFrame const*const pLayout(m_pDoc->getIDocumentLayoutAccess().GetCurrentLayout());
+        isShowChanges = pLayout == nullptr || !pLayout->IsHideRedlines();
     }
     else
     {
commit 20d2357e0050fbbd68dde7acaef72e26b8f2e1cc
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Oct 12 16:31:31 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: fix SwAttrIter::SeekFwd()
    
    This never called Rst() in the loops because the m_nPosition wasn't updated.
    
    Change-Id: I5a9cf47d9fe6d92bb7fccf255acbbd22f04b7f47

diff --git a/sw/source/core/text/itratr.cxx b/sw/source/core/text/itratr.cxx
index 0533fae9be27..18145cb38523 100644
--- a/sw/source/core/text/itratr.cxx
+++ b/sw/source/core/text/itratr.cxx
@@ -260,7 +260,7 @@ bool SwAttrIter::SeekStartAndChgAttrIter( OutputDevice* pOut, const bool bParaFo
 }
 
 // AMA: New AttrIter Nov 94
-void SwAttrIter::SeekFwd( const sal_Int32 nNewPos )
+void SwAttrIter::SeekFwd(const sal_Int32 nOldPos, const sal_Int32 nNewPos)
 {
     SwpHints const*const pHints(m_pTextNode->GetpSwpHints());
     SwTextAttr *pTextAttr;
@@ -276,7 +276,7 @@ void SwAttrIter::SeekFwd( const sal_Int32 nNewPos )
         {
             // Close the TextAttributes, whose StartPos were before or at
             // the old nPos and are currently open
-            if (pTextAttr->GetStart() <= m_nPosition)  Rst( pTextAttr );
+            if (pTextAttr->GetStart() <= nOldPos)  Rst( pTextAttr );
             m_nEndIndex++;
         }
     }
@@ -320,14 +320,15 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
             sal_Int32 nPos(m_nPosition);
             do
             {
+                sal_Int32 const nOldPos(nPos);
                 nPos = GetNextAttrImpl(m_pTextNode, m_nStartIndex, m_nEndIndex, nPos);
                 if (nPos <= m_pTextNode->Len())
                 {
-                    SeekFwd(nPos);
+                    SeekFwd(nOldPos, nPos);
                 }
                 else
                 {
-                    SeekFwd(m_pTextNode->Len());
+                    SeekFwd(nOldPos, m_pTextNode->Len());
                 }
             }
             while (nPos < m_pTextNode->Len());
@@ -399,21 +400,22 @@ bool SwAttrIter::Seek(TextFrameIndex const nNewPos)
             sal_Int32 nPos(m_nPosition);
             do
             {
+                sal_Int32 const nOldPos(nPos);
                 nPos = GetNextAttrImpl(m_pTextNode, m_nStartIndex, m_nEndIndex, nPos);
                 if (nPos <= newPos.second)
                 {
-                    SeekFwd(nPos);
+                    SeekFwd(nOldPos, nPos);
                 }
                 else
                 {
-                    SeekFwd(newPos.second);
+                    SeekFwd(nOldPos, newPos.second);
                 }
             }
             while (nPos < newPos.second);
         }
         else
         {
-            SeekFwd(newPos.second);
+            SeekFwd(m_nPosition, newPos.second);
         }
     }
 
diff --git a/sw/source/core/text/itratr.hxx b/sw/source/core/text/itratr.hxx
index 99741c87b965..959436609608 100644
--- a/sw/source/core/text/itratr.hxx
+++ b/sw/source/core/text/itratr.hxx
@@ -63,7 +63,7 @@ private:
     const SwTextNode* m_pTextNode;
     sw::MergedPara const* m_pMergedPara;
 
-    void SeekFwd( const sal_Int32 nPos );
+    void SeekFwd(sal_Int32 nOldPos, sal_Int32 nNewPos);
     void SetFnt( SwFont* pNew ) { m_pFont = pNew; }
     void InitFontAndAttrHandler(SwTextNode const& rTextNode,
         OUString const& rText, bool const* pbVertLayout);
commit b22bbacf5caf307a61bc77f410f5187766d5197d
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Fri Oct 12 15:06:35 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: fix SwAccessibleParagraph::getRunAttributes() index
    
    ... check, which should accept the past-the-last-char index, because
    as the comments say it returns the hard attributes of the SwTextNode
    as well, so it should work for empty paragraphs too.
    
    (similar fix was done in getCharacterAttributes() in IA2)
    
    Change-Id: I01e1a8f66f103b63584e88ce785ac2044c5db2b9

diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx
index eec1a569da46..2e66b453b57d 100644
--- a/sw/source/core/access/accpara.cxx
+++ b/sw/source/core/access/accpara.cxx
@@ -1415,7 +1415,7 @@ uno::Sequence<PropertyValue> SwAccessibleParagraph::getCharacterAttributes(
 
     const OUString& rText = GetString();
 
-    if( ! IsValidChar( nIndex, rText.getLength()+1 ) )
+    if (!IsValidPosition(nIndex, rText.getLength()))
         throw lang::IndexOutOfBoundsException();
 
     bool bSupplementalMode = false;
@@ -1844,7 +1844,7 @@ uno::Sequence< PropertyValue > SwAccessibleParagraph::getRunAttributes(
 
     {
         const OUString& rText = GetString();
-        if ( !IsValidChar( nIndex, rText.getLength() ) )
+        if (!IsValidPosition(nIndex, rText.getLength()))
         {
             throw lang::IndexOutOfBoundsException();
         }
commit 7b69774c9d407a728b7c72cabf53439692732cd2
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Oct 11 18:03:27 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: rewrite MergedAttrIterByEnd
    
    It doesn't actually work with a similar logic to the other iterators,
    because it iterates ByEnd but forwards, so the hints and the extents
    don't come in a matching order.
    
    To prevent complicating this further, replace it with a new
    implementation that does only what the one client expects, and put it
    directly in SwTextFormatter replacing the previous integer iterator
    m_nHintEndIndex, so that it is created only once.
    
    Change-Id: I144bfcf7e837a4fb0e7ec279edfba4732d0ae897

diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 0cb3f3defe83..f537a98d0f95 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -971,11 +971,15 @@ public:
 };
 
 class MergedAttrIterByEnd
-    : public MergedAttrIterBase
 {
+private:
+    std::vector<std::pair<SwTextNode const*, SwTextAttr const*>> m_Hints;
+    SwTextNode const*const m_pNode;
+    size_t m_CurrentHint;
 public:
-    MergedAttrIterByEnd(SwTextFrame const& rFrame) : MergedAttrIterBase(rFrame) {}
-    SwTextAttr const* NextAttr(SwTextNode const** ppNode = nullptr);
+    MergedAttrIterByEnd(SwTextFrame const& rFrame);
+    SwTextAttr const* NextAttr(SwTextNode const*& rpNode);
+    void PrevAttr();
 };
 
 class MergedAttrIterReverse
diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 16d35e581131..879da6c822d9 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -97,7 +97,7 @@ void SwTextFormatter::CtorInitTextFormatter( SwTextFrame *pNewFrame, SwTextForma
     nCntMidHyph = 0;
     nLeftScanIdx = TextFrameIndex(COMPLETE_STRING);
     nRightScanIdx = TextFrameIndex(0);
-    m_nHintEndIndex = 0;
+    m_pByEndIter.reset();
     m_pFirstOfBorderMerge = nullptr;
 
     if (m_nStart > TextFrameIndex(GetInfo().GetText().getLength()))
@@ -289,7 +289,7 @@ SwLinePortion *SwTextFormatter::Underflow( SwTextFormatInfo &rInf )
         static_cast<SwFieldPortion*>(pRest)->IsNoLength())
     {
         // HACK: decrement again, so we pick up the suffix in next line!
-        --m_nHintEndIndex;
+        m_pByEndIter->PrevAttr();
     }
     delete pRest;
     rInf.SetRest(nullptr);
diff --git a/sw/source/core/text/itrform2.hxx b/sw/source/core/text/itrform2.hxx
index ff430b8616d1..555fed20cdcc 100644
--- a/sw/source/core/text/itrform2.hxx
+++ b/sw/source/core/text/itrform2.hxx
@@ -31,6 +31,8 @@ class SwExpandPortion;
 class SwMultiPortion;
 class SwFootnotePortion;
 
+namespace sw { class MergedAttrIterByEnd; }
+
 class SwTextFormatter : public SwTextPainter
 {
     const SwFormatDrop *pDropFormat;
@@ -43,7 +45,7 @@ class SwTextFormatter : public SwTextPainter
     bool bFlyInCntBase : 1; // Base reference that sets a character-bound frame
     bool bTruncLines : 1; // Flag for extending the repaint rect, if needed
     bool bUnclipped : 1; // Flag whether repaint is larger than the fixed line height
-    size_t m_nHintEndIndex; // HACK for TryNewNoLengthPortion
+    std::unique_ptr<sw::MergedAttrIterByEnd> m_pByEndIter; // HACK for TryNewNoLengthPortion
     SwLinePortion* m_pFirstOfBorderMerge; // The first text portion of a joined border (during portion building)
 
     SwLinePortion *NewPortion( SwTextFormatInfo &rInf );
diff --git a/sw/source/core/text/txtfld.cxx b/sw/source/core/text/txtfld.cxx
index b70b4bc7456b..196b11b84cf9 100644
--- a/sw/source/core/text/txtfld.cxx
+++ b/sw/source/core/text/txtfld.cxx
@@ -307,9 +307,9 @@ static SwFieldPortion * lcl_NewMetaPortion(SwTextAttr & rHint, const bool bPrefi
 /**
  * Try to create a new portion with zero length, for an end of a hint
  * (where there is no CH_TXTATR). Because there may be multiple hint ends at a
- * given index, m_nHintEndIndex is used to keep track of the already created
+ * given index, m_pByEndIter is used to keep track of the already created
  * portions. But the portions created here may actually be deleted again,
- * due to Underflow. In that case, m_nHintEndIndex must be decremented,
+ * due to Underflow. In that case, m_pByEndIter must be decremented,
  * so the portion will be created again on the next line.
  */
 SwExpandPortion * SwTextFormatter::TryNewNoLengthPortion(SwTextFormatInfo const & rInfo)
@@ -319,26 +319,24 @@ SwExpandPortion * SwTextFormatter::TryNewNoLengthPortion(SwTextFormatInfo const
     // sw_redlinehide: because there is a dummy character at the start of these
     // hints, it's impossible to have ends of hints from different nodes at the
     // same view position, so it's sufficient to check the hints of the current
-    // node.  However, m_nHintEndIndex exists for the whole text frame, so
+    // node.  However, m_pByEndIter exists for the whole text frame, so
     // it's necessary to iterate all hints for that purpose...
+    if (!m_pByEndIter)
+    {
+        m_pByEndIter.reset(new sw::MergedAttrIterByEnd(*rInfo.GetTextFrame()));
+    }
     SwTextNode const* pNode(nullptr);
-    sw::MergedAttrIterByEnd iter(*rInfo.GetTextFrame());
-    size_t i(0);
-    for (SwTextAttr const* pHint = iter.NextAttr(&pNode); pHint;
-         pHint = iter.NextAttr(&pNode))
+    for (SwTextAttr const* pHint = m_pByEndIter->NextAttr(pNode); pHint;
+         pHint = m_pByEndIter->NextAttr(pNode))
     {
-        if (i++ < m_nHintEndIndex)
-        {
-            continue; // skip ones that were handled earlier
-        }
         SwTextAttr & rHint(const_cast<SwTextAttr&>(*pHint));
         TextFrameIndex const nEnd(
             rInfo.GetTextFrame()->MapModelToView(pNode, *rHint.GetAnyEnd()));
         if (nEnd > nIdx)
         {
+            m_pByEndIter->PrevAttr();
             break;
         }
-        ++m_nHintEndIndex;
         if (nEnd == nIdx)
         {
             if (RES_TXTATR_METAFIELD == rHint.Which())
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index a81a7df905d6..a07d712cd4c7 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -153,44 +153,24 @@ namespace sw {
         }
     }
 
-    SwTextAttr const* MergedAttrIterByEnd::NextAttr(SwTextNode const** ppNode)
+    MergedAttrIterByEnd::MergedAttrIterByEnd(SwTextFrame const& rFrame)
+        : m_pNode(rFrame.GetMergedPara() ? nullptr : rFrame.GetTextNodeFirst())
+        , m_CurrentHint(0)
     {
-        if (m_pMerged)
+        if (!m_pNode)
         {
-            while (m_CurrentExtent < m_pMerged->extents.size())
+            MergedAttrIterReverse iter(rFrame);
+            SwTextNode const* pNode(nullptr);
+            while (SwTextAttr const* pHint = iter.PrevAttr(&pNode))
             {
-                sw::Extent const& rExtent(m_pMerged->extents[m_CurrentExtent]);
-                if (SwpHints const*const pHints = rExtent.pNode->GetpSwpHints())
-                {
-                    while (m_CurrentHint < pHints->Count())
-                    {
-                        SwTextAttr const*const pHint(
-                                pHints->GetSortedByEnd(m_CurrentHint));
-                        if (rExtent.nEnd <= *pHint->GetAnyEnd())
-                        {
-                            break;
-                        }
-                        ++m_CurrentHint;
-                        if (rExtent.nStart < *pHint->GetAnyEnd())
-                        {
-                            if (ppNode)
-                            {
-                                *ppNode = rExtent.pNode;
-                            }
-                            return pHint;
-                        }
-                    }
-                }
-                ++m_CurrentExtent;
-                if (m_CurrentExtent < m_pMerged->extents.size() &&
-                    rExtent.pNode != m_pMerged->extents[m_CurrentExtent].pNode)
-                {
-                    m_CurrentHint = 0; // reset
-                }
+                m_Hints.emplace_back(pNode, pHint);
             }
-            return nullptr;
         }
-        else
+    }
+
+    SwTextAttr const* MergedAttrIterByEnd::NextAttr(SwTextNode const*& rpNode)
+    {
+        if (m_pNode)
         {
             SwpHints const*const pHints(m_pNode->GetpSwpHints());
             if (pHints)
@@ -200,15 +180,29 @@ namespace sw {
                     SwTextAttr const*const pHint(
                             pHints->GetSortedByEnd(m_CurrentHint));
                     ++m_CurrentHint;
-                    if (ppNode)
-                    {
-                        *ppNode = m_pNode;
-                    }
+                    rpNode = m_pNode;
                     return pHint;
                 }
             }
             return nullptr;
         }
+        else
+        {
+            if (m_CurrentHint < m_Hints.size())
+            {
+                auto const ret = m_Hints[m_Hints.size() - m_CurrentHint - 1];
+                ++m_CurrentHint;
+                rpNode = ret.first;
+                return ret.second;
+            }
+            return nullptr;
+        }
+    }
+
+    void MergedAttrIterByEnd::PrevAttr()
+    {
+        assert(0 < m_CurrentHint); // should only rewind as far as 0
+        --m_CurrentHint;
     }
 
     MergedAttrIterReverse::MergedAttrIterReverse(SwTextFrame const& rFrame)
commit 4f21227a29ed0860a555e4439b712267a7bedced
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Oct 11 12:41:32 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: fix MergedAttrIterReverse
    
    Was using the wrong node when iterating; also the tricky case of empty
    or without-end hints at the start of an extent was wrong.
    
    MergedAttrIter also shouldn't include wihout-end hints and non-empty
    hints at the end of an extent.
    
    Change-Id: Ia0776c1d3043cbd6d76fa04905b4937ebba53398

diff --git a/sw/source/core/text/txtfld.cxx b/sw/source/core/text/txtfld.cxx
index e66b7ed2c884..b70b4bc7456b 100644
--- a/sw/source/core/text/txtfld.cxx
+++ b/sw/source/core/text/txtfld.cxx
@@ -424,9 +424,9 @@ static void checkApplyParagraphMarkFormatToNumbering( SwFont* pNumFnt, SwTextFor
     for (SwTextAttr const* pHint = iter.PrevAttr(&pNode); pHint;
          pHint = iter.PrevAttr(&pNode))
     {
-        TextFrameIndex const nHintStart(
-            rInf.GetTextFrame()->MapModelToView(pNode, pHint->GetStart()));
-        if (nHintStart < nTextLen)
+        TextFrameIndex const nHintEnd(
+            rInf.GetTextFrame()->MapModelToView(pNode, *pHint->GetAnyEnd()));
+        if (nHintEnd < nTextLen)
         {
             break; // only those at para end are interesting
         }
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 5603d7800914..a81a7df905d6 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -104,8 +104,12 @@ namespace sw {
                 {
                     while (m_CurrentHint < pHints->Count())
                     {
-                        SwTextAttr const*const pHint(pHints->Get(m_CurrentHint));
-                        if (rExtent.nEnd < pHint->GetStart())
+                        SwTextAttr *const pHint(pHints->Get(m_CurrentHint));
+                        if (rExtent.nEnd < pHint->GetStart()
+                                // <= if it has no end or isn't empty
+                            || (rExtent.nEnd == pHint->GetStart()
+                                && (!pHint->GetEnd()
+                                    || *pHint->GetEnd() != pHint->GetStart())))
                         {
                             break;
                         }
@@ -238,13 +242,18 @@ namespace sw {
                 {
                     while (0 < m_CurrentHint)
                     {
-                        SwTextAttr const*const pHint(pHints->Get(m_CurrentHint - 1));
-                        if (pHint->GetStart() < rExtent.nStart)
+                        SwTextAttr *const pHint(
+                                pHints->GetSortedByEnd(m_CurrentHint - 1));
+                        if (*pHint->GetAnyEnd() < rExtent.nStart
+                                // <= if it has end and isn't empty
+                            || (pHint->GetEnd()
+                                && *pHint->GetEnd() != pHint->GetStart()
+                                && *pHint->GetEnd() == rExtent.nStart))
                         {
                             break;
                         }
                         --m_CurrentHint;
-                        if (pHint->GetStart() <= rExtent.nEnd)
+                        if (*pHint->GetAnyEnd() <= rExtent.nEnd)
                         {
                             if (ppNode)
                             {
@@ -258,7 +267,8 @@ namespace sw {
                 if (0 < m_CurrentExtent &&
                     rExtent.pNode != m_pMerged->extents[m_CurrentExtent-1].pNode)
                 {
-                    SwpHints const*const pHints(rExtent.pNode->GetpSwpHints());
+                    SwpHints const*const pHints(
+                        m_pMerged->extents[m_CurrentExtent-1].pNode->GetpSwpHints());
                     m_CurrentHint = pHints ? pHints->Count() : 0; // reset
                 }
             }
@@ -271,7 +281,7 @@ namespace sw {
             {
                 while (0 < m_CurrentHint)
                 {
-                    SwTextAttr const*const pHint(pHints->Get(m_CurrentHint - 1));
+                    SwTextAttr const*const pHint(pHints->GetSortedByEnd(m_CurrentHint - 1));
                     --m_CurrentHint;
                     if (ppNode)
                     {
commit 8c8aa24eccf8a5468066af799971a46428917568
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Oct 11 11:17:09 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: fix typo bug in SwCursorShell::GetSelText()
    
    Change-Id: Ieee07d149d045b7953ea8d5489f2fb6aed13e5e4

diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx
index 565acb6d60fd..42febd5f6271 100644
--- a/sw/source/core/crsr/crsrsh.cxx
+++ b/sw/source/core/crsr/crsrsh.cxx
@@ -2428,7 +2428,7 @@ OUString SwCursorShell::GetSelText() const
                             : 0);
                     sal_Int32 const nEnd(i == pEnd->nNode.GetIndex()
                             ? pEnd->nContent.GetIndex()
-                            : pEnd->nNode.GetNode().GetTextNode()->Len());
+                            : rNode.GetTextNode()->Len());
                     buf.append(rNode.GetTextNode()->GetExpandText(
                                 nStart, nEnd - nStart, false, false, false,
                                 ExpandMode::HideDeletions));
commit 20c6a16446afb455f44dd336884f146718117705
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Oct 10 16:49:58 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw: simplify & fix SwAccessibleParagraph::getHyperLink()
    
    There is an inconsistency between getHyperLinkCount and getHyperLink,
    as the latter uses index 0 as a no-op for some ToC link that was never
    implemented, so all the real hyperlinks have their index offset by 1.
    
    Also it's pointless to call getHyperLinkCount once per loop iteration.
    
    (regression from 76c549eb01dcb7b5bf28a271ce00e386f3d388ba)
    
    Change-Id: Iec83b6680abbdff5d372ca40358bd1306f3bd991

diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx
index f323317d96cf..eec1a569da46 100644
--- a/sw/source/core/access/accpara.cxx
+++ b/sw/source/core/access/accpara.cxx
@@ -2892,36 +2892,13 @@ uno::Reference< XAccessibleHyperlink > SAL_CALL
 
     const SwTextFrame *pTextFrame = static_cast<const SwTextFrame*>( GetFrame() );
     SwHyperlinkIter_Impl aHIter(*pTextFrame);
-    sal_Int32 nTIndex = -1;
-    SwTOXSortTabBase* pTBase = GetTOXSortTabBase();
     SwTextNode const* pNode(nullptr);
     SwTextAttr* pHt = const_cast<SwTextAttr*>(aHIter.next(&pNode));
-    while( (nLinkIndex < getHyperLinkCount()) && nTIndex < nLinkIndex)
+    for (sal_Int32 nTIndex = 0; pHt && nTIndex <= nLinkIndex; ++nTIndex)
     {
-        sal_Int32 nHStt = -1;
-        bool bH = false;
-
-        if( pHt )
-            nHStt = pHt->GetStart();
-        bool bTOC = false;
-        // Inside TOC & get the first link
-        if( pTBase && nTIndex == -1 )
-        {
-            nTIndex++;
-            bTOC = true;
-        }
-        else if( nHStt >= 0 )
-        {
-              // only hyperlink available
-            nTIndex++;
-            bH = true;
-        }
-
         if( nTIndex == nLinkIndex )
         {   // found
-            if( bH )
             {   // it's a hyperlink
-                if( pHt )
                 {
                     if( !m_pHyperTextData )
                         m_pHyperTextData.reset( new SwAccessibleHyperTextData );
@@ -2955,15 +2932,8 @@ uno::Reference< XAccessibleHyperlink > SAL_CALL
             break;
         }
 
-        // iterate next
-        if( bH )
-            // iterate next hyperlink
-            pHt = const_cast<SwTextAttr*>(aHIter.next(&pNode));
-        else if(bTOC)
-            continue;
-        else
-            // no candidate, exit
-            break;
+        // iterate next hyperlink
+        pHt = const_cast<SwTextAttr*>(aHIter.next(&pNode));
     }
     if( !xRet.is() )
         throw lang::IndexOutOfBoundsException();
commit fe6bb0c290991d3122f36f0aadd9387d32e79889
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Oct 10 14:44:14 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: convert SwAccessibleMap
    
    BuildSelectedParas() needs a little tweak to create idempotent map
    entries while it iterates over the nodes of a merged paragraph.
    
    InvalidateShapeInParaSelection() has some dodgy code to check if flys
    are selected; probably should check for the start pos. of the frame
    for AT_PARA anchor.
    
    Change-Id: I2abe5dff1fb7fd0b95cc6c78b756f250db5f0872

diff --git a/sw/source/core/access/accmap.cxx b/sw/source/core/access/accmap.cxx
index eb6557db7bea..299f78eee657 100644
--- a/sw/source/core/access/accmap.cxx
+++ b/sw/source/core/access/accmap.cxx
@@ -598,13 +598,13 @@ public:
 
 struct SwAccessibleParaSelection
 {
-    sal_Int32 const nStartOfSelection;
-    sal_Int32 const nEndOfSelection;
+    TextFrameIndex const nStartOfSelection;
+    TextFrameIndex const nEndOfSelection;
 
-    SwAccessibleParaSelection( const sal_Int32 _nStartOfSelection,
-                               const sal_Int32 _nEndOfSelection )
-        : nStartOfSelection( _nStartOfSelection ),
-          nEndOfSelection( _nEndOfSelection )
+    SwAccessibleParaSelection(const TextFrameIndex nStartOfSelection_,
+                              const TextFrameIndex nEndOfSelection_)
+        : nStartOfSelection(nStartOfSelection_)
+        , nEndOfSelection(nEndOfSelection_)
     {}
 };
 
@@ -1173,6 +1173,18 @@ void SwAccessibleMap::InvalidateShapeInParaSelection()
                     if( pCursor != nullptr )
                     {
                         const SwTextNode* pNode = pPos->nNode.GetNode().GetTextNode();
+                        SwTextFrame const*const pFrame(static_cast<SwTextFrame*>(pNode->getLayoutFrame(pVSh->GetLayout())));
+                        sal_uLong nFirstNode(pFrame->GetTextNodeFirst()->GetIndex());
+                        sal_uLong nLastNode;
+                        if (sw::MergedPara const*const pMerged = pFrame->GetMergedPara())
+                        {
+                            nLastNode = pMerged->pLastNode->GetIndex();
+                        }
+                        else
+                        {
+                            nLastNode = nFirstNode;
+                        }
+
                         sal_uLong nHere = pNode->GetIndex();
 
                         for(SwPaM& rTmpCursor : pCursor->GetRingContainer())
@@ -1186,8 +1198,9 @@ void SwAccessibleMap::InvalidateShapeInParaSelection()
                                 sal_uLong nStartIndex = pStart->nNode.GetIndex();
                                 SwPosition* pEnd = rTmpCursor.End();
                                 sal_uLong nEndIndex = pEnd->nNode.GetIndex();
-                                if( ( nHere >= nStartIndex ) && (nHere <= nEndIndex)  )
+                                if ((nStartIndex <= nLastNode) && (nFirstNode <= nEndIndex))
                                 {
+                                    // FIXME: what about missing FLY_AT_CHAR?
                                     if( rAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR )
                                     {
                                         if( ( ((nHere == nStartIndex) && (nIndex >= pStart->nContent.GetIndex())) || (nHere > nStartIndex) )
@@ -1206,8 +1219,9 @@ void SwAccessibleMap::InvalidateShapeInParaSelection()
                                     }
                                     else if( rAnchor.GetAnchorId() == RndStdIds::FLY_AT_PARA )
                                     {
-                                        if( ((nHere > nStartIndex) || pStart->nContent.GetIndex() ==0 )
-                                            && (nHere < nEndIndex ) )
+                                        if (((nStartIndex < nFirstNode) ||
+                                             (nFirstNode == nStartIndex && pStart->nContent.GetIndex() == 0))
+                                            && (nLastNode < nEndIndex))
                                         {
                                             uno::Reference < XAccessible > xAcc( (*aIter).second );
                                             if( xAcc.is() )
@@ -1313,13 +1327,17 @@ void SwAccessibleMap::InvalidateShapeInParaSelection()
             {
                 SwNodeIndex nStartIndex( rTmpCursor.Start()->nNode );
                 SwNodeIndex nEndIndex( rTmpCursor.End()->nNode );
-                while(nStartIndex <= nEndIndex)
+                for (; nStartIndex <= nEndIndex; ++nStartIndex)
                 {
                     SwFrame *pFrame = nullptr;
                     if(nStartIndex.GetNode().IsContentNode())
                     {
                         SwContentNode* pCNd = static_cast<SwContentNode*>(&(nStartIndex.GetNode()));
                         pFrame = SwIterator<SwFrame, SwContentNode, sw::IteratorMode::UnwrapMulti>(*pCNd).First();
+                        if (mapTemp.find(pFrame) != mapTemp.end())
+                        {
+                            continue; // sw_redlinehide: once is enough
+                        }
                     }
                     else if( nStartIndex.GetNode().IsTableNode() )
                     {
@@ -1354,7 +1372,6 @@ void SwAccessibleMap::InvalidateShapeInParaSelection()
                             mapTemp.emplace( pFrame, xAcc );
                         }
                     }
-                    ++nStartIndex;
                 }
             }
         }
@@ -3313,17 +3330,19 @@ std::unique_ptr<SwAccessibleSelectedParas_Impl> SwAccessibleMap::BuildSelectedPa
                             {
                                 xWeakAcc = (*aMapIter).second;
                                 SwAccessibleParaSelection aDataEntry(
-                                    pTextNode == &(pStartPos->nNode.GetNode())
-                                                ? pStartPos->nContent.GetIndex()
-                                                : 0,
-                                    pTextNode == &(pEndPos->nNode.GetNode())
-                                                ? pEndPos->nContent.GetIndex()
-                                                : -1 );
+                                    sw::FrameContainsNode(*pTextFrame, pStartPos->nNode.GetIndex())
+                                        ? pTextFrame->MapModelToViewPos(*pStartPos)
+                                        : TextFrameIndex(0),
+
+                                    sw::FrameContainsNode(*pTextFrame, pEndPos->nNode.GetIndex())
+                                        ? pTextFrame->MapModelToViewPos(*pEndPos)
+                                        : TextFrameIndex(COMPLETE_STRING));
                                 if ( !pRetSelectedParas )
                                 {
                                     pRetSelectedParas.reset(
                                             new SwAccessibleSelectedParas_Impl);
                                 }
+                                // sw_redlinehide: should be idempotent for multiple nodes in a merged para
                                 pRetSelectedParas->emplace( xWeakAcc, aDataEntry );
                             }
                         }
commit af0a9aaf9d9adaeacf3b3ca477adadd8efd07617
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Oct 10 12:02:53 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: adapt SwAccessibleDocument::getAccFlowTo()
    
    This looks like it wants to deduplicate paragraphs; just use a std::set
    for the frames, and retrieve them with a particular SwPosition, which
    should deduplicate fine.
    
    Change-Id: I0d0bd5cc4eb8d41d0a2f64979ccfde62ebc3533a

diff --git a/sw/source/core/access/accdoc.cxx b/sw/source/core/access/accdoc.cxx
index b525e52e1abc..c4faadebe69c 100644
--- a/sw/source/core/access/accdoc.cxx
+++ b/sw/source/core/access/accdoc.cxx
@@ -834,24 +834,19 @@ css::uno::Sequence< css::uno::Any >
         if ( pCursorShell )
         {
             SwPaM *_pStartCursor = pCursorShell->GetCursor(), *_pStartCursor2 = _pStartCursor;
-            SwContentNode* pPrevNode = nullptr;
-            std::vector<SwFrame*> vFrameList;
+            std::set<SwFrame*> vFrameList;
             do
             {
                 if ( _pStartCursor && _pStartCursor->HasMark() )
                 {
                     SwContentNode* pContentNode = _pStartCursor->GetContentNode();
-                    if ( pContentNode == pPrevNode )
-                    {
-                        continue;
-                    }
-                    SwFrame* pFrame = pContentNode ? pContentNode->getLayoutFrame( pCursorShell->GetLayout() ) : nullptr;
+                    SwFrame *const pFrame = pContentNode
+                        ? pContentNode->getLayoutFrame(pCursorShell->GetLayout(), _pStartCursor->GetPoint())
+                        : nullptr;
                     if ( pFrame )
                     {
-                        vFrameList.push_back( pFrame );
+                        vFrameList.insert( pFrame );
                     }
-
-                    pPrevNode = pContentNode;
                 }
             }
 
@@ -860,7 +855,7 @@ css::uno::Sequence< css::uno::Any >
             if ( vFrameList.size() )
             {
                 uno::Sequence< uno::Any > aRet(vFrameList.size());
-                std::vector<SwFrame*>::iterator aIter = vFrameList.begin();
+                auto aIter = vFrameList.begin();
                 for ( sal_Int32 nIndex = 0; aIter != vFrameList.end(); ++aIter, nIndex++ )
                 {
                     uno::Reference< XAccessible > xAcc = pAccMap->GetContext(*aIter, false);
commit 336316f35d9f2797172d777a8ed2e7ac4742513f
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Oct 10 11:28:22 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: remove SwTextFrame::GetTextNode()
    
    Change-Id: Ie46d8846887e9282ef40d63255f8a70e22f304e9

diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 5a9db1f0634a..0cb3f3defe83 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -416,11 +416,6 @@ public:
 
     /// Returns the text portion we want to edit (for inline see underneath)
     const OUString& GetText() const;
-    // TODO: remove GetTextNode
-    SwTextNode *GetTextNode()
-        { return static_cast<SwTextNode*>(SwFrame::GetDep()); }
-    const SwTextNode *GetTextNode() const
-        { return static_cast<const SwTextNode*>(SwFrame::GetDep()); }
     SwTextNode const* GetTextNodeForParaProps() const;
     SwTextNode      * GetTextNodeFirst()
         { return const_cast<SwTextNode*>(const_cast<SwTextFrame const*>(this)->GetTextNodeFirst()); };
commit 7d0fecf2a33fa8a417484e8a2e0f19ea9ad356b5
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Wed Oct 10 11:26:04 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: minimally convert laycache.cxx
    
    Just fix the TextFrameIndex / GetTextNode usages.
    
    This does not make the layout cache actually work if IsHideRedlines is
    enabled, hence the layout cache remains disabled in that case.
    
    Change-Id: I9aa1fb490c3dd4fd26165f2e60513ec267857d78

diff --git a/sw/source/core/layout/laycache.cxx b/sw/source/core/layout/laycache.cxx
index b507e0933293..f4110461d59a 100644
--- a/sw/source/core/layout/laycache.cxx
+++ b/sw/source/core/layout/laycache.cxx
@@ -201,7 +201,7 @@ void SwLayoutCache::Write( SvStream &rStream, const SwDoc& rDoc )
                             nNdIdx -= nStartOfContent;
                             aIo.GetStream().WriteUInt32( nNdIdx );
                             if( bFollow )
-                                aIo.GetStream().WriteUInt32( static_cast<SwTextFrame*>(pTmp)->GetOfst() );
+                                aIo.GetStream().WriteUInt32( sal_Int32(static_cast<SwTextFrame*>(pTmp)->GetOfst()) );
                             aIo.CloseFlagRec();
                             /*  Close Paragraph Record */
                             aIo.CloseRec();
@@ -357,8 +357,9 @@ bool SwLayoutCache::CompareLayout( const SwDoc& rDoc ) const
                         if( pImpl->GetBreakIndex( nIndex ) != nNdIdx ||
                             SW_LAYCACHE_IO_REC_PARA !=
                             pImpl->GetBreakType( nIndex ) ||
-                            ( bFollow ? static_cast<const SwTextFrame*>(pTmp)->GetOfst()
-                              : COMPLETE_STRING ) != pImpl->GetBreakOfst( nIndex ) )
+                            (bFollow
+                              ? sal_Int32(static_cast<const SwTextFrame*>(pTmp)->GetOfst())
+                              : COMPLETE_STRING) != pImpl->GetBreakOfst(nIndex))
                         {
                             return false;
                         }
@@ -799,7 +800,7 @@ bool SwLayHelper::CheckInsert( sal_uLong nNodeIndex )
                     sal_uInt16 nRepeat( 0 );
                     if( !bLongTab && mrpFrame->IsTextFrame() &&
                         SW_LAYCACHE_IO_REC_PARA == nType &&
-                        nOfst < static_cast<SwTextFrame*>(mrpFrame)->GetTextNode()->GetText().getLength())
+                        nOfst < static_cast<SwTextFrame*>(mrpFrame)->GetText().getLength())
                         bSplit = true;
                     else if( mrpFrame->IsTabFrame() && nRowCount < nOfst &&
                              ( bLongTab || SW_LAYCACHE_IO_REC_TABLE == nType ) )
@@ -873,8 +874,8 @@ bool SwLayHelper::CheckInsert( sal_uLong nNodeIndex )
                         {
                             SwTextFrame *const pNew = static_cast<SwTextFrame*>(
                                 static_cast<SwTextFrame*>(mrpFrame)
-                                    ->GetTextNode()->MakeFrame(mrpFrame));
-                            pNew->ManipOfst( nOfst );
+                                    ->GetTextNodeFirst()->MakeFrame(mrpFrame));
+                            pNew->ManipOfst( TextFrameIndex(nOfst) );
                             pNew->SetFollow( static_cast<SwTextFrame*>(mrpFrame)->GetFollow() );
                             static_cast<SwTextFrame*>(mrpFrame)->SetFollow( pNew );
                             mrpFrame = pNew;
diff --git a/sw/source/core/layout/layhelp.hxx b/sw/source/core/layout/layhelp.hxx
index f4201ccb09b5..87b832321d98 100644
--- a/sw/source/core/layout/layhelp.hxx
+++ b/sw/source/core/layout/layhelp.hxx
@@ -53,6 +53,7 @@ typedef std::vector<SwFlyCache> SwPageFlyCache;
 class SwLayCacheImpl
 {
     std::vector<sal_uLong> mIndices;
+    /// either a textframe character offset, or a row index inside a table
     std::deque<sal_Int32> aOffset;
     std::vector<sal_uInt16> aType;
     SwPageFlyCache m_FlyCache;
commit e0c14b5f74960edaeaf1fabaeff8454e8e6d3b6e
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Oct 9 18:43:44 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: SwXTextViewCursor::getString() without redlines
    
    Change-Id: I734e27c95e20373f8de32f8db2183275c94144e5

diff --git a/sw/inc/unocrsrhelper.hxx b/sw/inc/unocrsrhelper.hxx
index 7624c59afaf3..58cca5fc0618 100644
--- a/sw/inc/unocrsrhelper.hxx
+++ b/sw/inc/unocrsrhelper.hxx
@@ -36,6 +36,7 @@ class SwUnoTableCursor;
 class SwFormatColl;
 struct SwSortOptions;
 class SwDoc;
+class SwRootFrame;
 
 namespace sw { namespace mark { class IMark; } }
 
@@ -135,7 +136,7 @@ namespace SwUnoCursorHelper
     void GetCursorAttr(SwPaM & rPam, SfxItemSet & rSet,
                      const bool bOnlyTextAttr = false,
                      const bool bGetFromChrFormat = true);
-    void GetTextFromPam(SwPaM & rPam, OUString & rBuffer);
+    void GetTextFromPam(SwPaM & rPam, OUString & rBuffer, SwRootFrame const* pLayout = nullptr);
     SwFormatColl * GetCurTextFormatColl(SwPaM & rPam, const bool bConditional);
 
     void SelectPam(SwPaM & rPam, const bool bExpand);
diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx
index d16972e71e3c..da69af11eaf9 100644
--- a/sw/source/core/unocore/unoobj.cxx
+++ b/sw/source/core/unocore/unoobj.cxx
@@ -160,7 +160,8 @@ void SwUnoCursorHelper::SelectPam(SwPaM & rPam, const bool bExpand)
     }
 }
 
-void SwUnoCursorHelper::GetTextFromPam(SwPaM & rPam, OUString & rBuffer)
+void SwUnoCursorHelper::GetTextFromPam(SwPaM & rPam, OUString & rBuffer,
+        SwRootFrame const*const pLayout)
 {
     if (!rPam.HasMark())
     {
@@ -188,6 +189,7 @@ void SwUnoCursorHelper::GetTextFromPam(SwPaM & rPam, OUString & rBuffer)
     // #i68522#
     const bool bOldShowProgress = xWrt->m_bShowProgress;
     xWrt->m_bShowProgress = false;
+    xWrt->m_bHideDeleteRedlines = pLayout && pLayout->IsHideRedlines();
 
     if( ! aWriter.Write( xWrt ).IsError() )
     {
diff --git a/sw/source/uibase/uno/unotxvw.cxx b/sw/source/uibase/uno/unotxvw.cxx
index 1348a5fde2bf..96f2a6de666b 100644
--- a/sw/source/uibase/uno/unotxvw.cxx
+++ b/sw/source/uibase/uno/unotxvw.cxx
@@ -1381,7 +1381,8 @@ OUString SwXTextViewCursor::getString()
             {
                 SwWrtShell& rSh = m_pView->GetWrtShell();
                 SwPaM* pShellCursor = rSh.GetCursor();
-                SwUnoCursorHelper::GetTextFromPam(*pShellCursor, uRet);
+                SwUnoCursorHelper::GetTextFromPam(*pShellCursor, uRet,
+                        rSh.GetLayout());
                 break;
             }
             default:;//prevent warning
commit e0dcbf643ca6ba60435fbe3acb715316b5bec77e
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Oct 9 16:32:33 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: trivial conversions in new code in fntcache.cxx
    
    Change-Id: Id625ee27e69800780c04ea80d888f606cde0f308

diff --git a/sw/source/core/txtnode/fntcache.cxx b/sw/source/core/txtnode/fntcache.cxx
index dd377d0c1090..5288649caaa2 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -1450,7 +1450,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
 
         // get screen array
         std::unique_ptr<long[]> pScrArray(new long[sal_Int32(rInf.GetLen())]);
-        SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), rInf.GetIdx(), rInf.GetLen() };
+        SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) };
         SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
         rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray.get(),
                         sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs);
@@ -1465,7 +1465,7 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
                 if( !m_pPrtFont->IsSameInstance( m_pPrinter->GetFont() ) )
                     m_pPrinter->SetFont( *m_pPrtFont );
             }
-            aGlyphsKey = SwTextGlyphsKey{ m_pPrinter, rInf.GetText(), rInf.GetIdx(), rInf.GetLen() };
+            aGlyphsKey = SwTextGlyphsKey{ m_pPrinter, rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) };
             pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
             m_pPrinter->GetTextArray(rInf.GetText(), pKernArray.get(),
                     sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs);
@@ -2039,7 +2039,7 @@ Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
         }
         else
         {
-            SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), rInf.GetIdx(), nLn };
+            SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(nLn) };
             SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
             aTextSize.setWidth( rInf.GetOut().GetTextWidth( rInf.GetText(),
                                    sal_Int32(rInf.GetIdx()), sal_Int32(nLn),
@@ -2076,7 +2076,7 @@ TextFrameIndex SwFntObj::GetCursorOfst(SwDrawTextInfo &rInf)
     {
         m_pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
         m_pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
-        SwTextGlyphsKey aGlyphsKey{ m_pPrinter, rInf.GetText(), rInf.GetIdx(), rInf.GetLen() };
+        SwTextGlyphsKey aGlyphsKey{ m_pPrinter, rInf.GetText(), sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()) };
         SalLayoutGlyphs* pGlyphs = lcl_CreateLayout(aGlyphsKey, m_aTextGlyphs[aGlyphsKey]);
         m_pPrinter->GetTextArray( rInf.GetText(), pKernArray.get(),
                 sal_Int32(rInf.GetIdx()), sal_Int32(rInf.GetLen()), nullptr, pGlyphs);
@@ -2491,7 +2491,7 @@ TextFrameIndex SwFont::GetTextBreak(SwDrawTextInfo const & rInf, long nTextWidth
         {
             SwFntAccess aFntAccess(m_aSub[m_nActual].m_nFontCacheId, m_aSub[m_nActual].m_nFontIndex,
                                    &m_aSub[m_nActual], rInf.GetShell());
-            SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), *pTmpText, nTmpIdx, nTmpLen };
+            SwTextGlyphsKey aGlyphsKey{ &rInf.GetOut(), *pTmpText, sal_Int32(nTmpIdx), sal_Int32(nTmpLen) };
             SalLayoutGlyphs* pGlyphs
                 = lcl_CreateLayout(aGlyphsKey, aFntAccess.Get()->GetTextGlyphs()[aGlyphsKey]);
             nTextBreak = TextFrameIndex(rInf.GetOut().GetTextBreak(
commit 0e95bf055098103b771ba5360bf0a87c586f8ed9
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Oct 9 16:32:02 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: trivial conversions in new code in xmldump.cxx
    
    Change-Id: I37624c92549b4b3cd4d9616a4952163bf51526ef

diff --git a/sw/source/core/text/xmldump.cxx b/sw/source/core/text/xmldump.cxx
index 6dc0eb71971d..90d73c75dab5 100644
--- a/sw/source/core/text/xmldump.cxx
+++ b/sw/source/core/text/xmldump.cxx
@@ -133,12 +133,12 @@ class XmlPortionDumper:public SwPortionHandler
             xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("nHeight"), "%i", static_cast<int>(nHeight));
         if (nWidth > 0)
             xmlTextWriterWriteFormatAttribute(writer, BAD_CAST("nWidth"), "%i", static_cast<int>(nWidth));
-        if (nLength > 0)
+        if (nLength > TextFrameIndex(0))
             xmlTextWriterWriteAttribute(writer, BAD_CAST("Portion"),
-                                        BAD_CAST(m_rText.copy(ofs, nLength).toUtf8().getStr()));
+                BAD_CAST(m_rText.copy(sal_Int32(ofs), sal_Int32(nLength)).toUtf8().getStr()));
 
         xmlTextWriterEndElement( writer );
-        m_aLine += m_rText.copy(ofs, nLength);
+        m_aLine += m_rText.copy(sal_Int32(ofs), sal_Int32(nLength));
         ofs += nLength;
     }
 
commit 4fadb914260034951d6d25304c52d5c31051a84e
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Oct 9 16:17:03 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: bug in UpdateMergedParaForMove
    
    lcl_SetWrong works on model positions.
    
    Change-Id: I34353a09260e336c15696a7bc48a5922bfd92e4a

diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index af0422aa09ea..5603d7800914 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -1724,7 +1724,7 @@ void UpdateMergedParaForMove(sw::MergedPara & rMerged,
             if(nDeleted)
             {
                 // InvalidateRange/lcl_SetScriptInval was called sufficiently for SwInsText
-                lcl_SetWrong(rTextFrame, rDestNode, nStart, -nDeleted, false);
+                lcl_SetWrong(rTextFrame, rDestNode, nStart, it.first - it.second, false);
                 if (rTextFrame.HasFollow())
                 {
                     TextFrameIndex const nIndex(sw::MapModelToView(rMerged, &rDestNode, nStart));
commit 4aae7fe8c047dcd49519c33a673f417270e42ef7
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Oct 9 14:49:23 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: convert even more SwAccessibleParagraph functions
    
    ... and finally remove GetTextNode().
    
    Change-Id: I7ad91bf709b705afcf7ada79fd2a97335329e8b7

diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx
index 1986a0ee8bd6..f323317d96cf 100644
--- a/sw/source/core/access/accpara.cxx
+++ b/sw/source/core/access/accpara.cxx
@@ -118,17 +118,6 @@ namespace com { namespace sun { namespace star {
 const sal_Char sServiceName[] = "com.sun.star.text.AccessibleParagraphView";
 const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleParagraphView";
 
-const SwTextNode* SwAccessibleParagraph::GetTextNode() const
-{
-    const SwFrame* pFrame = GetFrame();
-    OSL_ENSURE( pFrame->IsTextFrame(), "The text frame has mutated!" );
-
-    const SwTextNode* pNode = static_cast<const SwTextFrame*>(pFrame)->GetTextNode();
-    OSL_ENSURE( pNode != nullptr, "A text frame without a text node." );
-
-    return pNode;
-}
-
 OUString const & SwAccessibleParagraph::GetString()
 {
     return GetPortionData().GetAccessibleString();
@@ -223,7 +212,8 @@ SwPaM* SwAccessibleParagraph::GetCursor( const bool _bForSelection )
 
 bool SwAccessibleParagraph::IsHeading() const
 {
-    const SwTextNode *pTextNd = GetTextNode();
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+    const SwTextNode *pTextNd = pFrame->GetTextNodeForParaProps();
     return pTextNd->IsOutline();
 }
 
@@ -246,9 +236,10 @@ void SwAccessibleParagraph::GetStates(
 
     // FOCUSED (simulates node index of cursor)
     SwPaM* pCaret = GetCursor( false ); // #i27301# - consider adjusted method signature
-    const SwTextNode* pTextNd = GetTextNode();
-    if( pCaret != nullptr && pTextNd != nullptr &&
-        pTextNd->GetIndex() == pCaret->GetPoint()->nNode.GetIndex() &&
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+    assert(pFrame);
+    if (pCaret != nullptr &&
+        sw::FrameContainsNode(*pFrame, pCaret->GetPoint()->nNode.GetIndex()) &&
         m_nOldCaretPos != -1)
     {
         vcl::Window *pWin = GetWindow();
@@ -544,7 +535,9 @@ bool SwAccessibleParagraph::IsValidRange(
 
 SwTOXSortTabBase* SwAccessibleParagraph::GetTOXSortTabBase()
 {
-    const SwTextNode* pTextNd = GetTextNode();
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+    assert(pFrame);
+    const SwTextNode *const pTextNd = pFrame->GetTextNodeFirst();
     if( pTextNd )
     {
         const SwSectionNode * pSectNd = pTextNd->FindSectionNode();
@@ -582,15 +575,7 @@ const SwRangeRedline* SwAccessibleParagraph::GetRedlineAtIndex()
     if ( pCrSr )
     {
         SwPosition* pStart = pCrSr->Start();
-        const SwTextNode* pNode = GetTextNode();
-        if ( pNode )
-        {
-            const SwDoc* pDoc = pNode->GetDoc();
-            if ( pDoc )
-            {
-                pRedline = pDoc->getIDocumentRedlineAccess().GetRedline( *pStart, nullptr );
-            }
-        }
+        pRedline = pStart->GetDoc()->getIDocumentRedlineAccess().GetRedline(*pStart, nullptr);
     }
 
     return pRedline;
@@ -1253,13 +1238,11 @@ OUString SwAccessibleParagraph::GetFieldTypeNameAtIndex(sal_Int32 nIndex)
     sal_Int32 nFieldIndex = GetPortionData().GetFieldIndex(nIndex);
     if (nFieldIndex >= 0)
     {
-        const SwpHints* pSwpHints = GetTextNode()->GetpSwpHints();
-        if (pSwpHints)
+        SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+        sw::MergedAttrIter iter(*pFrame);
+        while (SwTextAttr const*const pHt = iter.NextAttr())
         {
-            const size_t nSize = pSwpHints->Count();
-            for( size_t i = 0; i < nSize; ++i )
             {
-                const SwTextAttr* pHt = pSwpHints->Get(i);
                 if ( ( pHt->Which() == RES_TXTATR_FIELD
                        || pHt->Which() == RES_TXTATR_ANNOTATION
                        || pHt->Which() == RES_TXTATR_INPUTFIELD )
@@ -1539,7 +1522,8 @@ void SwAccessibleParagraph::_getDefaultAttributesImpl(
         const bool bOnlyCharAttrs )
 {
     // retrieve default attributes
-    const SwTextNode* pTextNode( GetTextNode() );
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+    const SwTextNode *const pTextNode(pFrame->GetTextNodeForParaProps());
     std::unique_ptr<SfxItemSet> pSet;
     if ( !bOnlyCharAttrs )
     {
@@ -1876,7 +1860,8 @@ void SwAccessibleParagraph::_getSupplementalAttributesImpl(
         const uno::Sequence< OUString >& aRequestedAttributes,
         tAccParaPropValMap& rSupplementalAttrSeq )
 {
-    const SwTextNode* pTextNode( GetTextNode() );
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+    const SwTextNode *const pTextNode(pFrame->GetTextNodeForParaProps());
     std::unique_ptr<SfxItemSet> pSet;
     pSet.reset(
         new SfxItemSet(
@@ -3062,13 +3047,22 @@ sal_Int32 SAL_CALL SwAccessibleParagraph::getSelectedPortionCount(  )
 {
     SolarMutexGuard g;
 
-    sal_Int32 nSeleted = 0;
+    sal_Int32 nSelected = 0;
     SwPaM* pCursor = GetCursor( true );
     if( pCursor != nullptr )
     {
         // get SwPosition for my node
-        const SwTextNode* pNode = GetTextNode();
-        sal_uLong nHere = pNode->GetIndex();
+        SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+        sal_uLong nFirstNode(pFrame->GetTextNodeFirst()->GetIndex());
+        sal_uLong nLastNode;
+        if (sw::MergedPara const*const pMerged = pFrame->GetMergedPara())
+        {
+            nLastNode = pMerged->pLastNode->GetIndex();
+        }
+        else
+        {
+            nLastNode = nFirstNode;
+        }
 
         // iterate over ring
         for(SwPaM& rTmpCursor : pCursor->GetRingContainer())
@@ -3076,22 +3070,21 @@ sal_Int32 SAL_CALL SwAccessibleParagraph::getSelectedPortionCount(  )
             // ignore, if no mark
             if( rTmpCursor.HasMark() )
             {
-                // check whether nHere is 'inside' pCursor
+                // check whether frame's node(s) are 'inside' pCursor
                 SwPosition* pStart = rTmpCursor.Start();
                 sal_uLong nStartIndex = pStart->nNode.GetIndex();
                 SwPosition* pEnd = rTmpCursor.End();
                 sal_uLong nEndIndex = pEnd->nNode.GetIndex();
-                if( ( nHere >= nStartIndex ) &&
-                    ( nHere <= nEndIndex )      )
+                if ((nStartIndex <= nLastNode) && (nFirstNode <= nEndIndex))
                 {
-                    nSeleted++;
+                    nSelected++;
                 }
                 // else: this PaM doesn't point to this paragraph
             }
             // else: this PaM is collapsed and doesn't select anything
         }
     }
-    return nSeleted;
+    return nSelected;
 
 }
 
@@ -3133,8 +3126,17 @@ sal_Bool SAL_CALL SwAccessibleParagraph::removeSelection( sal_Int32 selectionInd
         bool bRet = false;
 
         // get SwPosition for my node
-        const SwTextNode* pNode = GetTextNode();
-        sal_uLong nHere = pNode->GetIndex();
+        SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+        sal_uLong nFirstNode(pFrame->GetTextNodeFirst()->GetIndex());
+        sal_uLong nLastNode;
+        if (sw::MergedPara const*const pMerged = pFrame->GetMergedPara())
+        {
+            nLastNode = pMerged->pLastNode->GetIndex();
+        }
+        else
+        {
+            nLastNode = nFirstNode;
+        }
 
         // iterate over ring
         SwPaM* pRingStart = pCursor;
@@ -3143,13 +3145,12 @@ sal_Bool SAL_CALL SwAccessibleParagraph::removeSelection( sal_Int32 selectionInd
             // ignore, if no mark
             if( pCursor->HasMark() )
             {
-                // check whether nHere is 'inside' pCursor
+                // check whether frame's node(s) are 'inside' pCursor
                 SwPosition* pStart = pCursor->Start();
                 sal_uLong nStartIndex = pStart->nNode.GetIndex();
                 SwPosition* pEnd = pCursor->End();
                 sal_uLong nEndIndex = pEnd->nNode.GetIndex();
-                if( ( nHere >= nStartIndex ) &&
-                    ( nHere <= nEndIndex )      )
+                if ((nStartIndex <= nLastNode) && (nFirstNode <= nEndIndex))
                 {
                     if( nSelected == 0 )
                     {
diff --git a/sw/source/core/access/accpara.hxx b/sw/source/core/access/accpara.hxx
index 676e99a9023b..26afc0df73eb 100644
--- a/sw/source/core/access/accpara.hxx
+++ b/sw/source/core/access/accpara.hxx
@@ -88,9 +88,6 @@ class SwAccessibleParagraph :
 
     std::unique_ptr<SwParaChangeTrackingInfo> mpParaChangeTrackInfo; // #i108125#
 
-    /// get the SwTextNode (requires frame; check before)
-    const SwTextNode* GetTextNode() const;
-
     /// get the (accessible) text string (requires frame; check before)
     OUString const & GetString();
 
commit a71f0dddb17ac048fe4c51c77b2a82b0f6137f9d
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Oct 9 15:53:17 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: convert SwAccessibleParagraph::_correctValues()
    
    Tricky usage of SwWrongList here, let's hope this works...
    
    Also, there is a similar bug here, the nIndex is in a11y coordinates
    but it was used directly as input to SwWrongList; better to convert
    first.
    
    Change-Id: I9b49b4dc84089c03df0e1302512d13d289d16161

diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx
index b3038c21875a..1986a0ee8bd6 100644
--- a/sw/source/core/access/accpara.cxx
+++ b/sw/source/core/access/accpara.cxx
@@ -2000,7 +2000,20 @@ void SwAccessibleParagraph::_correctValues( const sal_Int32 nIndex,
         }
     }
 
-    const SwTextNode* pTextNode( GetTextNode() );
+    // sw_redlinehide: this function only needs SwWrongList for 1 character,
+    // and the end is excluded by InWrongWord(),
+    // so it ought to work to just pick the wrong-list/node that contains
+    // the character following the given nIndex
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+    TextFrameIndex const nCorePos(GetPortionData().GetCoreViewPosition(nIndex));
+    std::pair<SwTextNode*, sal_Int32> pos(pFrame->MapViewToModel(nCorePos));
+    if (pos.first->Len() == pos.second
+        && nCorePos != TextFrameIndex(pFrame->GetText().getLength()))
+    {
+        pos = pFrame->MapViewToModel(nCorePos + TextFrameIndex(1)); // try this one instead
+        assert(pos.first->Len() != pos.second);
+    }
+    const SwTextNode *const pTextNode(pos.first);
 
     sal_Int32 nValues = rValues.size();
     for (sal_Int32 i = 0;  i < nValues;  ++i)
@@ -2067,7 +2080,7 @@ void SwAccessibleParagraph::_correctValues( const sal_Int32 nIndex,
                 const SwWrongList* pWrongList = pTextNode->GetWrong();
                 if( nullptr != pWrongList )
                 {
-                    sal_Int32 nBegin = nIndex;
+                    sal_Int32 nBegin = pos.second;
                     sal_Int32 nLen = 1;
                     if (pWrongList->InWrongWord(nBegin, nLen) && !pTextNode->IsSymbolAt(nBegin))
                     {
@@ -2088,7 +2101,7 @@ void SwAccessibleParagraph::_correctValues( const sal_Int32 nIndex,
                 const SwWrongList* pWrongList = pTextNode->GetWrong();
                 if( nullptr != pWrongList )
                 {
-                    sal_Int32 nBegin = nIndex;
+                    sal_Int32 nBegin = pos.second;
                     sal_Int32 nLen = 1;
                     if (pWrongList->InWrongWord(nBegin, nLen) && !pTextNode->IsSymbolAt(nBegin))
                     {
commit 6ae737fb16bac7a8cc3260077d48d0c05c486225
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Oct 9 13:59:24 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: convert SwAccessibleParagraph::_getRunAttributesImpl
    
    There appears to be a bug here, in that the nIndex is an index into
    the accessiblity string, but it was used without conversion as a
    model position in SwPosition; let's try to fix that.
    
    Change-Id: I7a43ceacfe59102577f39ab4b8fec3b495db345d

diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx
index caf95ac3a32c..b3038c21875a 100644
--- a/sw/source/core/access/accpara.cxx
+++ b/sw/source/core/access/accpara.cxx
@@ -1751,14 +1751,16 @@ void SwAccessibleParagraph::_getRunAttributesImpl(
 {
     // create PaM for character at position <nIndex>
     std::unique_ptr<SwPaM> pPaM;
+    const TextFrameIndex nCorePos(GetPortionData().GetCoreViewPosition(nIndex));
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+    SwPosition const aModelPos(pFrame->MapViewToModelPos(nCorePos));
+    SwTextNode *const pTextNode(aModelPos.nNode.GetNode().GetTextNode());
     {
-        const SwTextNode* pTextNode( GetTextNode() );
-        std::unique_ptr<SwPosition> pStartPos( new SwPosition( *pTextNode ) );
-        pStartPos->nContent.Assign( const_cast<SwTextNode*>(pTextNode), nIndex );
-        std::unique_ptr<SwPosition> pEndPos( new SwPosition( *pTextNode ) );
-        pEndPos->nContent.Assign( const_cast<SwTextNode*>(pTextNode), nIndex+1 );
-
-        pPaM.reset(new SwPaM( *pStartPos, *pEndPos ));
+        SwPosition const aEndPos(*pTextNode,
+            aModelPos.nContent.GetIndex() == pTextNode->Len()
+                ? pTextNode->Len() // ???
+                : aModelPos.nContent.GetIndex() + 1);
+        pPaM.reset(new SwPaM(aModelPos, aEndPos));
     }
 
     // retrieve character attributes for the created PaM <pPaM>
@@ -1771,7 +1773,6 @@ void SwAccessibleParagraph::_getRunAttributesImpl(
     //    SwXTextCursor::GetCursorAttr( *pPaM, aSet, sal_True, sal_True );
     // get character attributes from automatic paragraph style and merge these into <aSet>
     {
-        const SwTextNode* pTextNode( GetTextNode() );
         if ( pTextNode->HasSwAttrSet() )
         {
             SfxItemSet aAutomaticParaStyleCharAttrs( pPaM->GetDoc()->GetAttrPool(),
commit 8b4d1b202c89461f7fb947c007a0b072852fec68
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Oct 9 12:59:01 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: convert more SwAccessibleParagraph functions
    
    Change-Id: I33079154b4775b1df55693bf6046adbf27b0c1e3

diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx
index f092d6267d8b..caf95ac3a32c 100644
--- a/sw/source/core/access/accpara.cxx
+++ b/sw/source/core/access/accpara.cxx
@@ -149,20 +149,21 @@ sal_Int32 SwAccessibleParagraph::GetCaretPos()
 
     if( pCaret != nullptr )
     {
-        const SwTextNode* pNode = GetTextNode();
+        SwTextFrame const*const pTextFrame(static_cast<SwTextFrame const*>(GetFrame()));
+        assert(pTextFrame);
 
         // check whether the point points into 'our' node
         SwPosition* pPoint = pCaret->GetPoint();
-        if( pNode->GetIndex() == pPoint->nNode.GetIndex() )
+        if (sw::FrameContainsNode(*pTextFrame, pPoint->nNode.GetIndex()))
         {
             // same node? Then check whether it's also within 'our' part
             // of the paragraph
-            const sal_Int32 nIndex = pPoint->nContent.GetIndex();
+            const TextFrameIndex nIndex = pTextFrame->MapModelToViewPos(*pPoint);
             if(!GetPortionData().IsValidCorePosition( nIndex ) ||
-                ( GetPortionData().IsZeroCorePositionData() && nIndex== 0) )
+                (GetPortionData().IsZeroCorePositionData()
+                  && nIndex == TextFrameIndex(0)))
             {
-                const SwTextFrame *pTextFrame = dynamic_cast<const SwTextFrame*>( GetFrame()  );
-                bool bFormat = (pTextFrame && pTextFrame->HasPara());
+                bool bFormat = pTextFrame->HasPara();
                 if(bFormat)
                 {
                     ClearPortionData();
@@ -501,17 +502,17 @@ SwXTextPortion* SwAccessibleParagraph::CreateUnoPortion(
                 IsValidRange(nStartIndex, nEndIndex, GetString().getLength()),
                 "please check parameters before calling this method" );
 
-    const sal_Int32 nStart = GetPortionData().GetCoreViewPosition(nStartIndex);
-    const sal_Int32 nEnd = (nEndIndex == -1) ? (nStart + 1) :
-                        GetPortionData().GetCoreViewPosition(nEndIndex);
+    const TextFrameIndex nStart = GetPortionData().GetCoreViewPosition(nStartIndex);
+    const TextFrameIndex nEnd = (nEndIndex == -1)
+            ? (nStart + TextFrameIndex(1))
+            : GetPortionData().GetCoreViewPosition(nEndIndex);
 
     // create UNO cursor
-    SwTextNode* pTextNode = const_cast<SwTextNode*>( GetTextNode() );
-    SwIndex aIndex( pTextNode, nStart );
-    SwPosition aStartPos( *pTextNode, aIndex );
-    auto pUnoCursor(pTextNode->GetDoc()->CreateUnoCursor( aStartPos ));
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+    SwPosition aStartPos(pFrame->MapViewToModelPos(nStart));
+    auto pUnoCursor(const_cast<SwDoc&>(pFrame->GetDoc()).CreateUnoCursor(aStartPos));
     pUnoCursor->SetMark();
-    pUnoCursor->GetMark()->nContent = nEnd;
+    *pUnoCursor->GetMark() = pFrame->MapViewToModelPos(nEnd);
 
     // create a (dummy) text portion to be returned
     uno::Reference<text::XText> aEmpty;
@@ -618,9 +619,9 @@ bool SwAccessibleParagraph::GetWordBoundary(
     assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
 
     // get locale for this position
-    const sal_Int32 nModelPos = GetPortionData().GetCoreViewPosition(nPos);
-    lang::Locale aLocale = g_pBreakIt->GetLocale(
-                          GetTextNode()->GetLang( nModelPos ) );
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+    const TextFrameIndex nCorePos = GetPortionData().GetCoreViewPosition(nPos);
+    lang::Locale aLocale = g_pBreakIt->GetLocale(pFrame->GetLangOfChar(nCorePos, 0, true));
 
     // which type of word are we interested in?
     // (DICTIONARY_WORD includes punctuation, ANY_WORD doesn't.)
@@ -685,9 +686,9 @@ bool SwAccessibleParagraph::GetGlyphBoundary(
     assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
 
     // get locale for this position
-    const sal_Int32 nModelPos = GetPortionData().GetCoreViewPosition(nPos);
-    lang::Locale aLocale = g_pBreakIt->GetLocale(
-                          GetTextNode()->GetLang( nModelPos ) );
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+    const TextFrameIndex nCorePos = GetPortionData().GetCoreViewPosition(nPos);
+    lang::Locale aLocale = g_pBreakIt->GetLocale(pFrame->GetLangOfChar(nCorePos, 0, true));
 
     // get word boundary, as the Break-Iterator sees fit.
     const sal_Int16 nIterMode = i18n::CharacterIteratorMode::SKIPCELL;
@@ -781,8 +782,7 @@ lang::Locale SAL_CALL SwAccessibleParagraph::getLocale()
         throw uno::RuntimeException("no SwTextFrame", static_cast<cppu::OWeakObject*>(this));
     }
 
-    const SwTextNode *pTextNd = pTextFrame->GetTextNode();
-    lang::Locale aLoc( g_pBreakIt->GetLocale( pTextNd->GetLang( 0 ) ) );
+    lang::Locale aLoc(g_pBreakIt->GetLocale(pTextFrame->GetLangOfChar(TextFrameIndex(0), 0, true)));
 
     return aLoc;
 }
@@ -833,11 +833,10 @@ void SAL_CALL SwAccessibleParagraph::grabFocus()
     SwCursorShell *pCursorSh = GetCursorShell();
     SwPaM *pCursor = GetCursor( false ); // #i27301# - consider new method signature
     const SwTextFrame *pTextFrame = static_cast<const SwTextFrame*>( GetFrame() );
-    const SwTextNode* pTextNd = pTextFrame->GetTextNode();
 
-    if( pCursorSh != nullptr && pTextNd != nullptr &&
+    if (pCursorSh != nullptr &&
         ( pCursor == nullptr ||
-           pCursor->GetPoint()->nNode.GetIndex() != pTextNd->GetIndex() ||
+          !sw::FrameContainsNode(*pTextFrame, pCursor->GetPoint()->nNode.GetIndex()) ||
           !pTextFrame->IsInside(pTextFrame->MapModelToViewPos(*pCursor->GetPoint()))))
     {
         // create pam for selection
@@ -1139,9 +1138,9 @@ sal_Bool SAL_CALL SwAccessibleParagraph::setCaretPosition( sal_Int32 nIndex )
     if( pCursorShell != nullptr )
     {
         // create pam for selection
-        SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() );
-        SwIndex aIndex(pNode, GetPortionData().GetCoreViewPosition(nIndex));
-        SwPosition aStartPos( *pNode, aIndex );
+        SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+        TextFrameIndex const nFrameIndex(GetPortionData().GetCoreViewPosition(nIndex));
+        SwPosition aStartPos(pFrame->MapViewToModelPos(nFrameIndex));
         SwPaM aPaM( aStartPos );
 
         // set PaM at cursor shell
@@ -1188,26 +1187,25 @@ css::uno::Sequence< css::style::TabStop > SwAccessibleParagraph::GetCurrentTabSt
     aMoveState.m_bRealHeight = true;
     aMoveState.m_bRealWidth = true;
     SwSpecialPos aSpecialPos;
-    SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() );
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
 
     /*  #i12332# FillSpecialPos does not accept nIndex ==
          GetString().getLength(). In that case nPos is set to the
          length of the string in the core. This way GetCharRect
          returns the rectangle for a cursor at the end of the
          paragraph. */
-    const sal_Int32 nPos = bBehindText
-        ? pNode->GetText().getLength()
+    const TextFrameIndex nPos = bBehindText
+        ? TextFrameIndex(pFrame->GetText().getLength())
         : GetPortionData().FillSpecialPos(nIndex, aSpecialPos, aMoveState.m_pSpecialPos );
 
     // call GetCharRect
     SwRect aCoreRect;
-    SwIndex aIndex( pNode, nPos );
-    SwPosition aPosition( *pNode, aIndex );
+    SwPosition aPosition(pFrame->MapViewToModelPos(nPos));
     GetFrame()->GetCharRect( aCoreRect, aPosition, &aMoveState );
 
     // already get the caret position
     css::uno::Sequence< css::style::TabStop > tabs;
-    const sal_Int32 nStrLen = GetTextNode()->GetText().getLength();
+    const sal_Int32 nStrLen = pFrame->GetText().getLength();
     if( nStrLen > 0 )
     {
         SwFrame* pTFrame = const_cast<SwFrame*>(GetFrame());
@@ -2172,21 +2170,20 @@ awt::Rectangle SwAccessibleParagraph::getCharacterBounds(
     aMoveState.m_bRealHeight = true;
     aMoveState.m_bRealWidth = true;
     SwSpecialPos aSpecialPos;
-    SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() );
+    SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
 
     /**  #i12332# FillSpecialPos does not accept nIndex ==
          GetString().getLength(). In that case nPos is set to the
          length of the string in the core. This way GetCharRect
          returns the rectangle for a cursor at the end of the
          paragraph. */
-    const sal_Int32 nPos = bBehindText
-        ? pNode->GetText().getLength()
+    const TextFrameIndex nPos = bBehindText
+        ? TextFrameIndex(pFrame->GetText().getLength())
         : GetPortionData().FillSpecialPos(nIndex, aSpecialPos, aMoveState.m_pSpecialPos );
 
     // call GetCharRect
     SwRect aCoreRect;
-    SwIndex aIndex( pNode, nPos );
-    SwPosition aPosition( *pNode, aIndex );
+    SwPosition aPosition(pFrame->MapViewToModelPos(nPos));
     GetFrame()->GetCharRect( aCoreRect, aPosition, &aMoveState );
 
     // translate core coordinates into accessibility coordinates
@@ -2223,11 +2220,6 @@ sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint )
 
     ThrowIfDisposed();
 
-    // construct SwPosition (where GetCursorOfst() will put the result into)
-    SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() );
-    SwIndex aIndex( pNode, 0);
-    SwPosition aPos( *pNode, aIndex );
-
     // construct Point (translate into layout coordinates)
     vcl::Window *pWin = GetWindow();
     if (!pWin)
@@ -2262,14 +2254,17 @@ sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint )
     OSL_ENSURE( GetFrame() != nullptr, "The text frame has vanished!" );
     OSL_ENSURE( GetFrame()->IsTextFrame(), "The text frame has mutated!" );
     const SwTextFrame* pFrame = static_cast<const SwTextFrame*>( GetFrame() );
+    // construct SwPosition (where GetCursorOfst() will put the result into)
+    SwTextNode* pNode = const_cast<SwTextNode*>(pFrame->GetTextNodeFirst());
+    SwPosition aPos(*pNode, 0);
     SwCursorMoveState aMoveState;
     aMoveState.m_bPosMatchesBounds = true;
     const bool bSuccess = pFrame->GetCursorOfst( &aPos, aCorePoint, &aMoveState );
 
-    SwIndex aContentIdx = aPos.nContent;
-    const sal_Int32 nIndex = aContentIdx.GetIndex();
-    if ( nIndex > 0 )
+    TextFrameIndex nIndex = pFrame->MapModelToViewPos(aPos);
+    if (TextFrameIndex(0) < nIndex)
     {
+        assert(bSuccess);
         SwRect aResultRect;
         pFrame->GetCharRect( aResultRect, aPos );
         bool bVert = pFrame->IsVertical();
@@ -2279,19 +2274,20 @@ sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint )
              ( bVert && aResultRect.Pos().getY() > aCorePoint.getY()) ||
              ( bR2L  && aResultRect.Right()   < aCorePoint.getX()) )
         {
-            SwIndex aIdxPrev( pNode, nIndex - 1);
-            SwPosition aPosPrev( *pNode, aIdxPrev );
+            SwPosition aPosPrev(pFrame->MapViewToModelPos(nIndex - TextFrameIndex(1)));
             SwRect aResultRectPrev;
             pFrame->GetCharRect( aResultRectPrev, aPosPrev );
             if ( (!bVert && aResultRectPrev.Pos().getX() < aCorePoint.getX() && aResultRect.Pos().getY() == aResultRectPrev.Pos().getY()) ||
                  ( bVert && aResultRectPrev.Pos().getY() < aCorePoint.getY() && aResultRect.Pos().getX() == aResultRectPrev.Pos().getX()) ||
                  (  bR2L && aResultRectPrev.Right()   > aCorePoint.getX() && aResultRect.Pos().getY() == aResultRectPrev.Pos().getY()) )
-                aPos = aPosPrev;
+            {
+                --nIndex;
+            }
         }
     }
 
-    return bSuccess ?
-        GetPortionData().GetAccessiblePosition( aPos.nContent.GetIndex() )
+    return bSuccess
+        ? GetPortionData().GetAccessiblePosition(nIndex)
         : -1;
 }
 
@@ -2663,29 +2659,26 @@ sal_Bool SwAccessibleParagraph::replaceText(
     if( !IsEditableState() )
         return false;
 
-    SwTextNode* pNode = const_cast<SwTextNode*>( GetTextNode() );
-
     // translate positions
-    sal_Int32 nStart;
-    sal_Int32 nEnd;
+    TextFrameIndex nStart;
+    TextFrameIndex nEnd;
     bool bSuccess = GetPortionData().GetEditableRange(
                                     nStartIndex, nEndIndex, nStart, nEnd );
 
     // edit only if the range is editable
     if( bSuccess )
     {
+        SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
         // create SwPosition for nStartIndex
-        SwIndex aIndex( pNode, nStart );
-        SwPosition aStartPos( *pNode, aIndex );
+        SwPosition aStartPos(pFrame->MapViewToModelPos(nStart));
 
         // create SwPosition for nEndIndex
-        SwPosition aEndPos( aStartPos );
-        aEndPos.nContent = nEnd;
+        SwPosition aEndPos(pFrame->MapViewToModelPos(nEnd));
 
         // now create XTextRange as helper and set string
         const uno::Reference<text::XTextRange> xRange(
             SwXTextRange::CreateXTextRange(
-                *pNode->GetDoc(), aStartPos, &aEndPos));
+                const_cast<SwDoc&>(pFrame->GetDoc()), aStartPos, &aEndPos));
         xRange->setString(sReplacement);
 
         // delete portion data
commit b33e984d49740bf7d8aee99ad832df8c29beab6e
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Oct 9 11:14:05 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: convert SwTextMarkupHelper and related ...
    
    ... functions in SwAccessibleParagraph, with the new WrongListIterator.
    
    Change-Id: Ie401dd867a06a1963e49fa54afa978ad1f1346f5

diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx
index fea50d58ac98..f092d6267d8b 100644
--- a/sw/source/core/access/accpara.cxx
+++ b/sw/source/core/access/accpara.cxx
@@ -3037,7 +3037,8 @@ sal_Int32 SAL_CALL SwAccessibleParagraph::getTextMarkupCount( sal_Int32 nTextMar
         break;
         default:
         {
-            pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTextNode() ) );
+            SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+            pTextMarkupHelper.reset(new SwTextMarkupHelper(GetPortionData(), *pFrame));
         }
     }
 
@@ -3247,7 +3248,8 @@ sal_Int32 SAL_CALL SwAccessibleParagraph::addSelection( sal_Int32, sal_Int32 sta
         break;
         default:
         {
-            pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTextNode() ) );
+            SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+            pTextMarkupHelper.reset(new SwTextMarkupHelper(GetPortionData(), *pFrame));
         }
     }
 
@@ -3281,7 +3283,8 @@ uno::Sequence< /*accessibility::*/TextSegment > SAL_CALL
         break;
         default:
         {
-            pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTextNode() ) );
+            SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(GetFrame()));
+            pTextMarkupHelper.reset(new SwTextMarkupHelper(GetPortionData(), *pFrame));
         }
     }
 
diff --git a/sw/source/core/access/textmarkuphelper.cxx b/sw/source/core/access/textmarkuphelper.cxx
index 2bbc8ab81984..8633789af140 100644
--- a/sw/source/core/access/textmarkuphelper.cxx
+++ b/sw/source/core/access/textmarkuphelper.cxx
@@ -36,27 +36,26 @@ using namespace com::sun::star;
 namespace {
     /// @throws css::lang::IllegalArgumentException
     /// @throws css::uno::RuntimeException
-    const SwWrongList* getTextMarkupList( const SwTextNode& rTextNode,
-                                          const sal_Int32 nTextMarkupType )
+    SwWrongList const* (SwTextNode::*
+        getTextMarkupFunc(const sal_Int32 nTextMarkupType))() const
     {
-        const SwWrongList* pTextMarkupList( nullptr );
         switch ( nTextMarkupType )
         {
             case text::TextMarkupType::SPELLCHECK:
             {
-                pTextMarkupList = rTextNode.GetWrong();
+                return &SwTextNode::GetWrong;
             }
             break;
             case text::TextMarkupType::PROOFREADING:
             {
                 // support not implemented yet
-                pTextMarkupList = nullptr;
+                return nullptr;
             }
             break;
             case text::TextMarkupType::SMARTTAG:
             {
                 // support not implemented yet
-                pTextMarkupList = nullptr;
+                return nullptr;
             }
             break;
             default:
@@ -64,17 +63,14 @@ namespace {
                 throw lang::IllegalArgumentException();
             }
         }
-
-        return pTextMarkupList;
     }
 }
 
 // implementation of class <SwTextMarkupoHelper>
 SwTextMarkupHelper::SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData,
-                                        const SwTextNode& rTextNode )
+                                        const SwTextFrame& rTextFrame)
     : mrPortionData( rPortionData )
-    // #i108125#
-    , mpTextNode( &rTextNode )
+    , m_pTextFrame(&rTextFrame)
     , mpTextMarkupList( nullptr )
 {
 }
@@ -83,7 +79,7 @@ SwTextMarkupHelper::SwTextMarkupHelper( const SwAccessiblePortionData& rPortionD
 SwTextMarkupHelper::SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData,
                                         const SwWrongList& rTextMarkupList )
     : mrPortionData( rPortionData )
-    , mpTextNode( nullptr )
+    , m_pTextFrame( nullptr )
     , mpTextMarkupList( &rTextMarkupList )
 {
 }
@@ -92,14 +88,19 @@ sal_Int32 SwTextMarkupHelper::getTextMarkupCount( const sal_Int32 nTextMarkupTyp
 {
     sal_Int32 nTextMarkupCount( 0 );
 
-    // #i108125#
-    const SwWrongList* pTextMarkupList =
-                            mpTextMarkupList
-                            ? mpTextMarkupList
-                            : getTextMarkupList( *mpTextNode, nTextMarkupType );
-    if ( pTextMarkupList )
+    if (mpTextMarkupList)
+    {
+        nTextMarkupCount = mpTextMarkupList->Count();
+    }
+    else
     {
-        nTextMarkupCount = pTextMarkupList->Count();
+        assert(m_pTextFrame);
+        SwWrongList const* (SwTextNode::*const pGetWrongList)() const = getTextMarkupFunc(nTextMarkupType);
+        if (pGetWrongList)
+        {
+            sw::WrongListIteratorCounter iter(*m_pTextFrame, pGetWrongList);
+            nTextMarkupCount = iter.GetElementCount();
+        }
     }
 
     return nTextMarkupCount;
@@ -119,22 +120,31 @@ css::accessibility::TextSegment
     aTextMarkupSegment.SegmentStart = -1;
     aTextMarkupSegment.SegmentEnd = -1;
 
-    // #i108125#
-    const SwWrongList* pTextMarkupList =
-                            mpTextMarkupList
-                            ? mpTextMarkupList
-                            : getTextMarkupList( *mpTextNode, nTextMarkupType );
-    if ( pTextMarkupList )
+    std::unique_ptr<sw::WrongListIteratorCounter> pIter;
+    if (mpTextMarkupList)
+    {
+        pIter.reset(new sw::WrongListIteratorCounter(*mpTextMarkupList));
+    }
+    else
+    {
+        assert(m_pTextFrame);
+        SwWrongList const* (SwTextNode::*const pGetWrongList)() const = getTextMarkupFunc(nTextMarkupType);
+        if (pGetWrongList)
+        {
+            pIter.reset(new sw::WrongListIteratorCounter(*m_pTextFrame, pGetWrongList));
+        }
+    }
+
+    if (pIter)
     {
-        const SwWrongArea* pTextMarkup =
-                pTextMarkupList->GetElement( static_cast<sal_uInt16>(nTextMarkupIndex) );
-        if ( pTextMarkup )
+        auto const oElement(pIter->GetElementAt(nTextMarkupIndex));
+        if (oElement)
         {
-            const OUString rText = mrPortionData.GetAccessibleString();
+            const OUString& rText = mrPortionData.GetAccessibleString();
             const sal_Int32 nStartPos =
-                            mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos );
+                            mrPortionData.GetAccessiblePosition(oElement->first);
             const sal_Int32 nEndPos =
-                            mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos + pTextMarkup->mnLen );
+                            mrPortionData.GetAccessiblePosition(oElement->second);
             aTextMarkupSegment.SegmentText = rText.copy( nStartPos, nEndPos - nStartPos );
             aTextMarkupSegment.SegmentStart = nStartPos;
             aTextMarkupSegment.SegmentEnd = nEndPos;
@@ -155,7 +165,7 @@ css::uno::Sequence< css::accessibility::TextSegment >
     // assumption:
     // value of <nCharIndex> is in range [0..length of accessible text)
 
-    const sal_Int32 nCoreCharIndex = mrPortionData.GetCoreViewPosition(nCharIndex);
+    const TextFrameIndex nCoreCharIndex = mrPortionData.GetCoreViewPosition(nCharIndex);
     // Handling of portions with core length == 0 at the beginning of the
     // paragraph - e.g. numbering portion.
     if ( mrPortionData.GetAccessiblePosition( nCoreCharIndex ) > nCharIndex )
@@ -163,30 +173,37 @@ css::uno::Sequence< css::accessibility::TextSegment >
         return uno::Sequence< css::accessibility::TextSegment >();
     }
 
-    // #i108125#
-    const SwWrongList* pTextMarkupList =
-                            mpTextMarkupList
-                            ? mpTextMarkupList
-                            : getTextMarkupList( *mpTextNode, nTextMarkupType );
-    std::vector< css::accessibility::TextSegment > aTmpTextMarkups;
-    if ( pTextMarkupList )
+    std::unique_ptr<sw::WrongListIteratorCounter> pIter;
+    if (mpTextMarkupList)
+    {
+        pIter.reset(new sw::WrongListIteratorCounter(*mpTextMarkupList));
+    }
+    else
     {
-        const OUString rText = mrPortionData.GetAccessibleString();
+        assert(m_pTextFrame);
+        SwWrongList const* (SwTextNode::*const pGetWrongList)() const = getTextMarkupFunc(nTextMarkupType);
+        if (pGetWrongList)
+        {
+            pIter.reset(new sw::WrongListIteratorCounter(*m_pTextFrame, pGetWrongList));
+        }
+    }
 
-        const sal_uInt16 nTextMarkupCount = pTextMarkupList->Count();
-        for ( sal_uInt16 nTextMarkupIdx = 0; nTextMarkupIdx < nTextMarkupCount; ++nTextMarkupIdx )
+    std::vector< css::accessibility::TextSegment > aTmpTextMarkups;
+    if (pIter)
+    {
+        const OUString& rText = mrPortionData.GetAccessibleString();
+        sal_uInt16 count(pIter->GetElementCount());
+        for (sal_uInt16 i = 0; i < count; ++i)
         {
-            const SwWrongArea* pTextMarkup = pTextMarkupList->GetElement( nTextMarkupIdx );
-            OSL_ENSURE( pTextMarkup,
-                    "<SwTextMarkupHelper::getTextMarkup(..)> - missing <SwWrongArea> instance" );
-            if ( pTextMarkup &&
-                 pTextMarkup->mnPos <= nCoreCharIndex &&
-                 nCoreCharIndex < ( pTextMarkup->mnPos + pTextMarkup->mnLen ) )
+            auto const oElement(pIter->GetElementAt(i));
+            if (oElement &&
+                oElement->first <= nCoreCharIndex &&
+                nCoreCharIndex < oElement->second)
             {
                 const sal_Int32 nStartPos =
-                    mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos );
+                    mrPortionData.GetAccessiblePosition(oElement->first);
                 const sal_Int32 nEndPos =
-                    mrPortionData.GetAccessiblePosition( pTextMarkup->mnPos + pTextMarkup->mnLen );
+                    mrPortionData.GetAccessiblePosition(oElement->second);
                 css::accessibility::TextSegment aTextMarkupSegment;
                 aTextMarkupSegment.SegmentText = rText.copy( nStartPos, nEndPos - nStartPos );
                 aTextMarkupSegment.SegmentStart = nStartPos;
diff --git a/sw/source/core/access/textmarkuphelper.hxx b/sw/source/core/access/textmarkuphelper.hxx
index de3af6013dc6..56a1cac5f9c4 100644
--- a/sw/source/core/access/textmarkuphelper.hxx
+++ b/sw/source/core/access/textmarkuphelper.hxx
@@ -30,13 +30,14 @@ struct TextSegment;
 } } } }
 
 class SwAccessiblePortionData;
-class SwTextNode;
+class SwTextFrame;
 class SwWrongList; // #i108125#
+
 class SwTextMarkupHelper
 {
     public:
         SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData,
-                            const SwTextNode& rTextNode );
+                            const SwTextFrame& rTextFrame);
         SwTextMarkupHelper( const SwAccessiblePortionData& rPortionData,
                             const SwWrongList& rTextMarkupList ); // #i108125#
 
@@ -64,8 +65,7 @@ class SwTextMarkupHelper
 
         const SwAccessiblePortionData& mrPortionData;
 
-        // #i108125#
-        const SwTextNode* mpTextNode;
+        SwTextFrame const* m_pTextFrame;
         const SwWrongList* mpTextMarkupList;
 };
 #endif
commit 5d5cef6eda22730228a8c479000fbd4cdf39d072
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Tue Oct 9 11:11:07 2018 +0200
Commit:     Michael Stahl <Michael.Stahl at cib.de>
CommitDate: Mon Oct 15 15:25:46 2018 +0200

    sw_redlinehide_3: add another kind of WrongListIterator
    
    This is not very efficient but should be good enough for a11y use.
    
    Change-Id: Ibb00cf4ae18effb09673f3f7d9b9b2e1d72413b1

diff --git a/sw/source/core/inc/wrong.hxx b/sw/source/core/inc/wrong.hxx
index 13f1f50507cf..8340d3337ca4 100644
--- a/sw/source/core/inc/wrong.hxx
+++ b/sw/source/core/inc/wrong.hxx
@@ -29,6 +29,8 @@
 
 #include <vector>
 
+#include <boost/optional.hpp>
+
 #include <tools/color.hxx>
 #include <swtypes.hxx>
 #include <viewopt.hxx>
@@ -346,9 +348,9 @@ namespace sw {
 
 struct MergedPara;
 
-class WrongListIterator
+class WrongListIteratorBase
 {
-private:
+protected:
     SwWrongList const* (SwTextNode::*const m_pGetWrongList)() const;
     sw::MergedPara const*const m_pMergedPara;
     size_t m_CurrentExtent;
@@ -357,6 +359,17 @@ private:
 
 public:
     /// for the text frame
+    WrongListIteratorBase(SwTextFrame const& rFrame,
+        SwWrongList const* (SwTextNode::*pGetWrongList)() const);
+    /// for SwTextSlot
+    WrongListIteratorBase(SwWrongList const& rWrongList);
+};
+
+class WrongListIterator
+    : public WrongListIteratorBase
+{
+public:
+    /// for the text frame
     WrongListIterator(SwTextFrame const& rFrame,
         SwWrongList const* (SwTextNode::*pGetWrongList)() const);
     /// for SwTextSlot
@@ -371,6 +384,18 @@ public:
     }
 };
 
+class WrongListIteratorCounter
+    : public WrongListIteratorBase
+{
+public:
+    WrongListIteratorCounter(SwTextFrame const& rFrame,
+        SwWrongList const* (SwTextNode::*pGetWrongList)() const);
+    WrongListIteratorCounter(SwWrongList const& rWrongList);
+
+    sal_uInt16 GetElementCount();
+    boost::optional<std::pair<TextFrameIndex, TextFrameIndex>> GetElementAt(sal_uInt16 nIndex);
+};
+
 } // namespace sw
 
 #endif
diff --git a/sw/source/core/text/wrong.cxx b/sw/source/core/text/wrong.cxx
index d85cf9a99bdf..1ced790261f7 100644
--- a/sw/source/core/text/wrong.cxx
+++ b/sw/source/core/text/wrong.cxx
@@ -664,7 +664,7 @@ void SwWrongList::Insert( const OUString& rType,
 
 namespace sw {
 
-WrongListIterator::WrongListIterator(SwTextFrame const& rFrame,
+WrongListIteratorBase::WrongListIteratorBase(SwTextFrame const& rFrame,
         SwWrongList const* (SwTextNode::*pGetWrongList)() const)
     : m_pGetWrongList(pGetWrongList)
     , m_pMergedPara(rFrame.GetMergedPara())
@@ -676,7 +676,7 @@ WrongListIterator::WrongListIterator(SwTextFrame const& rFrame,
 {
 }
 
-WrongListIterator::WrongListIterator(SwWrongList const& rWrongList)
+WrongListIteratorBase::WrongListIteratorBase(SwWrongList const& rWrongList)
     : m_pGetWrongList(nullptr)
     , m_pMergedPara(nullptr)
     , m_CurrentExtent(0)
@@ -685,6 +685,17 @@ WrongListIterator::WrongListIterator(SwWrongList const& rWrongList)
 {
 }
 
+WrongListIterator::WrongListIterator(SwTextFrame const& rFrame,
+        SwWrongList const* (SwTextNode::*pGetWrongList)() const)
+    : WrongListIteratorBase(rFrame, pGetWrongList)
+{
+}
+
+WrongListIterator::WrongListIterator(SwWrongList const& rWrongList)
+    : WrongListIteratorBase(rWrongList)
+{
+}
+
 bool WrongListIterator::Check(TextFrameIndex & rStart, TextFrameIndex & rLen)
 {
     if (m_pMergedPara)
@@ -838,6 +849,118 @@ WrongListIterator::GetWrongElement(TextFrameIndex const nStart)
     return nullptr;
 }
 
+WrongListIteratorCounter::WrongListIteratorCounter(SwTextFrame const& rFrame,
+        SwWrongList const* (SwTextNode::*pGetWrongList)() const)
+    : WrongListIteratorBase(rFrame, pGetWrongList)
+{
+}
+
+WrongListIteratorCounter::WrongListIteratorCounter(SwWrongList const& rWrongList)
+    : WrongListIteratorBase(rWrongList)
+{
+}
+
+sal_uInt16 WrongListIteratorCounter::GetElementCount()
+{
+    if (m_pMergedPara)
+    {
+        sal_uInt16 nRet(0);
+        m_CurrentExtent = 0;
+        m_CurrentIndex = TextFrameIndex(0);
+        SwNode const* pNode(nullptr);
+        sal_uInt16 InCurrentNode(0);
+        while (m_CurrentExtent < m_pMergedPara->extents.size())
+        {
+            sw::Extent const& rExtent(m_pMergedPara->extents[m_CurrentExtent]);
+            if (rExtent.pNode != pNode)
+            {
+                InCurrentNode = 0;
+                pNode = rExtent.pNode;
+            }
+            SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)());
+            for (; pWrongList && InCurrentNode < pWrongList->Count(); ++InCurrentNode)
+            {
+                SwWrongArea const*const pWrong(pWrongList->GetElement(InCurrentNode));
+                TextFrameIndex const nExtentEnd(
+                    m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart));
+                if (nExtentEnd <= TextFrameIndex(pWrong->mnPos))
+                {
+                    break; // continue outer loop
+                }
+                if (m_CurrentIndex < TextFrameIndex(pWrong->mnPos + pWrong->mnLen))
+                {
+                    ++nRet;
+                }
+            }
+            m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart);
+            ++m_CurrentExtent;
+        }
+        return nRet;
+    }
+    else if (m_pWrongList)
+    {
+        return m_pWrongList->Count();
+    }
+    return 0;
+}
+
+boost::optional<std::pair<TextFrameIndex, TextFrameIndex>>
+WrongListIteratorCounter::GetElementAt(sal_uInt16 nIndex)
+{
+    if (m_pMergedPara)
+    {
+        m_CurrentExtent = 0;
+        m_CurrentIndex = TextFrameIndex(0);
+        SwNode const* pNode(nullptr);
+        sal_uInt16 InCurrentNode(0);
+        while (m_CurrentExtent < m_pMergedPara->extents.size())
+        {
+            sw::Extent const& rExtent(m_pMergedPara->extents[m_CurrentExtent]);
+            if (rExtent.pNode != pNode)
+            {
+                InCurrentNode = 0;
+                pNode = rExtent.pNode;
+            }
+            SwWrongList const*const pWrongList((rExtent.pNode->*m_pGetWrongList)());
+            for (; pWrongList && InCurrentNode < pWrongList->Count(); ++InCurrentNode)
+            {
+                SwWrongArea const*const pWrong(pWrongList->GetElement(InCurrentNode));
+                TextFrameIndex const nExtentEnd(
+                    m_CurrentIndex + TextFrameIndex(rExtent.nEnd - rExtent.nStart));
+                if (nExtentEnd <= TextFrameIndex(pWrong->mnPos))
+                {
+                    break; // continue outer loop
+                }
+                if (m_CurrentIndex < TextFrameIndex(pWrong->mnPos + pWrong->mnLen))
+                {
+                    if (nIndex == 0)
+                    {
+                        return boost::optional<std::pair<TextFrameIndex, TextFrameIndex>>(
+                            std::pair<TextFrameIndex, TextFrameIndex>(
+                                m_CurrentIndex - TextFrameIndex(rExtent.nStart -
+                                    std::max(rExtent.nStart, pWrong->mnPos)),
+                                m_CurrentIndex - TextFrameIndex(rExtent.nStart -
+                                    std::min(pWrong->mnPos + pWrong->mnLen, rExtent.nEnd))));
+                    }
+                    --nIndex;
+                }
+            }
+            m_CurrentIndex += TextFrameIndex(rExtent.nEnd - rExtent.nStart);
+            ++m_CurrentExtent;
+        }
+        return boost::optional<std::pair<TextFrameIndex, TextFrameIndex>>();
+    }
+    else if (m_pWrongList)
+    {
+        SwWrongArea const*const pWrong(m_pWrongList->GetElement(nIndex));
+        return boost::optional<std::pair<TextFrameIndex, TextFrameIndex>>(
+            std::pair<TextFrameIndex, TextFrameIndex>(
+                    TextFrameIndex(pWrong->mnPos),
+                    TextFrameIndex(pWrong->mnPos + pWrong->mnLen)));
+    }
+    return boost::optional<std::pair<TextFrameIndex, TextFrameIndex>>();
+}
+
 } // namespace sw
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list