Rebased ref, commits from common ancestor:
commit 61ea78e3bb86f3624748758f9038dc99abddaffc
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Fri Oct 12 16:33:00 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 8296be7ce488dbcef65a2332c3cebdeb6e70c06c
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Fri Oct 12 16:31:31 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 99b2a972c189d279e0a9b3462ec7e621d6a60c45
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Fri Oct 12 15:06:35 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 48d6b18f776834478866edd2452771113858b663
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Thu Oct 11 18:03:27 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 8b71c93ab3f887c6d15970951e8684dc936582bc
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Thu Oct 11 12:41:32 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 6f238c0848f0ed247945a95c994ebdad5b617767
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Thu Oct 11 11:17:09 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 8e2baf931139df4f384e9abc5f0a6f4154aa982b
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Wed Oct 10 16:49:58 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 0baf778b8641f24b1a4a76d2d589d2b614d59f8f
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Wed Oct 10 14:44:14 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 57b68f42e55bdd2d97ee980dde60a618b566d443
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Wed Oct 10 12:02:53 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 b27f28c21d92597ba396613d0bbc511d092bceee
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Wed Oct 10 11:28:22 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 f8a6645d03af6011af53095a55aef3006565bd02
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Wed Oct 10 11:26:04 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 a5940751cab8ed6e7fd4565c34b719255e7aaad4
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Tue Oct 9 18:43:44 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 78da7ce12bfc852368ee80be761a6d4e838210ac
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Tue Oct 9 16:32:33 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 38c0557be3aa83463a2c941f76aa3d38385eba40
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Tue Oct 9 16:32:02 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 d62742473897f976d305ba2de498c6a12bb94b51
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Tue Oct 9 16:17:03 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 f26f28e18c449ccc8a7cb962f0a4b3291adebfcb
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Tue Oct 9 14:49:23 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 fa77a90ec51472112badad601c79aa9eb7405c12
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Tue Oct 9 15:53:17 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 d1b654535fd388fd634d868484c0f84889cbefaf
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Tue Oct 9 13:59:24 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 c53c0223cfd8c91dab5fea1cac7d8cf3c53558a8
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Tue Oct 9 12:59:01 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 cbe23baf0599c2e3ac155a0947c58d783c4fc9e2
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Tue Oct 9 11:14:05 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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 e4a049940d6c66919cbd21c727dee5a006041bb6
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Tue Oct 9 11:11:07 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 18:20:19 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..2c9f029537ad 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 (; 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 (; 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: */
commit 7fef2baa3a88ddae70f2306682ec311dc5cd6e49
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Mon Oct 8 15:46:55 2018 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Fri Oct 12 17:21:54 2018 +0200

    sw_redlinehide_3: remove GetSelection/GetSelectionAtIndex duplication
    
    Delicious copypasta!
    
    Change-Id: I95ab5a1ef58b01f775065a970a0d7eb2b6bf6394

diff --git a/sw/source/core/access/accpara.cxx 
b/sw/source/core/access/accpara.cxx
index a95a8b10331e..fea50d58ac98 100644
--- a/sw/source/core/access/accpara.cxx
+++ b/sw/source/core/access/accpara.cxx
@@ -195,137 +195,6 @@ sal_Int32 SwAccessibleParagraph::GetCaretPos()
     return nRet;
 }
 
-bool SwAccessibleParagraph::GetSelection(
-    sal_Int32& nStart, sal_Int32& nEnd)
-{
-    bool bRet = false;
-    nStart = -1;
-    nEnd = -1;
-
-    // get the selection, and test whether it affects our text node
-    SwPaM* pCursor = GetCursor( true ); // #i27301# - consider adjusted method 
signature
-    if( pCursor != nullptr )
-    {
-        // get SwPosition for my node
-        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())
-        {
-            // ignore, if no mark
-            if( rTmpCursor.HasMark() )
-            {
-                // 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 ((nStartIndex <= nLastNode) && (nFirstNode <= nEndIndex))
-                {
-                    // translate start and end positions
-
-                    // start position
-                    sal_Int32 nLocalStart = -1;
-                    if (nStartIndex < nFirstNode)
-                    {
-                        // selection starts in previous node:
-                        // then our local selection starts with the paragraph
-                        nLocalStart = 0;
-                    }
-                    else
-                    {
-                        assert(FrameContainsNode(*pFrame, nStartIndex));
-
-                        // selection starts in this node:
-                        // then check whether it's before or inside our part of
-                        // the paragraph, and if so, get the proper position
-                        const TextFrameIndex nCoreStart =
-                            pFrame->MapModelToViewPos(*pStart);
-                        if( nCoreStart <
-                            GetPortionData().GetFirstValidCorePosition() )
-                        {
-                            nLocalStart = 0;
-                        }
-                        else if( nCoreStart <=
-                                 GetPortionData().GetLastValidCorePosition() )
-                        {
-                            OSL_ENSURE(
-                                GetPortionData().IsValidCorePosition(
-                                                                  nCoreStart ),
-                                 "problem determining valid core position" );
-
-                            nLocalStart =
-                                GetPortionData().GetAccessiblePosition(
-                                                                  nCoreStart );
-                        }

... etc. - the rest is truncated
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to