sw/source/core/access/textmarkuphelper.cxx |   80 ++++++++++++++++-------------
 sw/source/core/access/textmarkuphelper.hxx |    6 ++
 2 files changed, 51 insertions(+), 35 deletions(-)

New commits:
commit 7f7ccf955fa1138b712233628de4a73b3f845c7e
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Thu Jul 6 13:37:30 2023 +0200
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Sat Jul 8 00:12:08 2023 +0200

    tdf#155705 sw a11y: Only handle paragraph's own spell check data
    
    When a paragraph is split across multiple pages, there
    are multiple accessible paragraphs on the
    accessibility layer, but there's still just a single text
    node in the underlying Writer core model.
    
    The `sw::WrongListIteratorCounter` used in
    `SwTextMarkupHelper` is for the whole text node, i.e.
    iterates over the spell check data from other pages
    (i.e. other accessible paragraphs) as well in that case.
    This caused invalid indices to be used when calculating the
    index within the current accessible paragraph again when
    iterating over all elements, causing a crash.
    
    Fix this by filtering out the elements that are outside
    of the accessible paragraph when handling markup information.
    
    Change-Id: If76cc60cc9ff5614d0bcbaff196ac34ec908936e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154109
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/sw/source/core/access/textmarkuphelper.cxx 
b/sw/source/core/access/textmarkuphelper.cxx
index 34be72fff584..ae221f499831 100644
--- a/sw/source/core/access/textmarkuphelper.cxx
+++ b/sw/source/core/access/textmarkuphelper.cxx
@@ -113,8 +113,15 @@ sal_Int32 SwTextMarkupHelper::getTextMarkupCount( const 
sal_Int32 nTextMarkupTyp
     sal_Int32 nTextMarkupCount( 0 );
 
     std::unique_ptr<sw::WrongListIteratorCounter> pIter = 
getIterator(nTextMarkupType);
-    if (pIter)
-        nTextMarkupCount = pIter->GetElementCount();
+    // iterator may handle all items in the underlying text node in the model, 
which may be more
+    // than what is in the portion data (e.g. if a paragraph is split across 
multiple pages),
+    // only take into account those that are in the portion data
+    for (sal_uInt16 i = 0; i < pIter->GetElementCount(); i++)
+    {
+        std::optional<std::pair<TextFrameIndex, TextFrameIndex>> oIndices = 
pIter->GetElementAt(i);
+        if (oIndices && mrPortionData.IsValidCorePosition(oIndices->first) && 
mrPortionData.IsValidCorePosition(oIndices->second))
+            nTextMarkupCount++;
+    }
 
     return nTextMarkupCount;
 }
@@ -136,7 +143,27 @@ css::accessibility::TextSegment
     std::unique_ptr<sw::WrongListIteratorCounter> pIter = 
getIterator(nTextMarkupType);
     if (pIter)
     {
-        auto const oElement(pIter->GetElementAt(nTextMarkupIndex));
+        std::optional<std::pair<TextFrameIndex, TextFrameIndex>> oElement;
+        const sal_uInt16 nIterElementCount = pIter->GetElementCount();
+        sal_Int32 nIndexInPortion = 0;
+        sal_uInt16 nIterIndex = 0;
+        while (!oElement && nIterIndex < nIterElementCount)
+        {
+            // iterator may handle all items in the underlying text node in 
the model, which may be more
+            // than what is in the portion data (e.g. if a paragraph is split 
across multiple pages),
+            // only take into account those that are in the portion data
+            std::optional<std::pair<TextFrameIndex, TextFrameIndex>> oIndices 
= pIter->GetElementAt(nIterIndex);
+            if (oIndices && mrPortionData.IsValidCorePosition(oIndices->first) 
&& mrPortionData.IsValidCorePosition(oIndices->second))
+            {
+                if (nIndexInPortion == nTextMarkupIndex)
+                    oElement = oIndices;
+
+                nIndexInPortion++;
+            }
+
+            nIterIndex++;
+        }
+
         if (oElement)
         {
             const OUString& rText = mrPortionData.GetAccessibleString();
commit 472950414a0fb07d5260b7b6b2d3a5d2dc18a68d
Author:     Michael Weghorn <m.wegh...@posteo.de>
AuthorDate: Thu Jul 6 10:27:37 2023 +0200
Commit:     Michael Weghorn <m.wegh...@posteo.de>
CommitDate: Sat Jul 8 00:12:01 2023 +0200

    tdf#155705 sw a11y: Unify iterator use in SwTextMarkupHelper
    
    Introduce a new helper method `SwTextMarkupHelper::getIterator`
    to get a `sw::WrongListIteratorCounter` and use that to deduplicate
    and unify handling in three methods.
    
    Change-Id: I81790c547f70f0649ce800bc481db70982dfa742
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/154108
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <m.wegh...@posteo.de>

diff --git a/sw/source/core/access/textmarkuphelper.cxx 
b/sw/source/core/access/textmarkuphelper.cxx
index 5329241c6f1b..34be72fff584 100644
--- a/sw/source/core/access/textmarkuphelper.cxx
+++ b/sw/source/core/access/textmarkuphelper.cxx
@@ -86,13 +86,13 @@ SwTextMarkupHelper::SwTextMarkupHelper( const 
SwAccessiblePortionData& rPortionD
 {
 }
 
-sal_Int32 SwTextMarkupHelper::getTextMarkupCount( const sal_Int32 
nTextMarkupType )
-{
-    sal_Int32 nTextMarkupCount( 0 );
 
+std::unique_ptr<sw::WrongListIteratorCounter> 
SwTextMarkupHelper::getIterator(sal_Int32 nTextMarkupType)
+{
+    std::unique_ptr<sw::WrongListIteratorCounter> pIter;
     if (mpTextMarkupList)
     {
-        nTextMarkupCount = mpTextMarkupList->Count();
+        pIter.reset(new sw::WrongListIteratorCounter(*mpTextMarkupList));
     }
     else
     {
@@ -100,11 +100,22 @@ sal_Int32 SwTextMarkupHelper::getTextMarkupCount( const 
sal_Int32 nTextMarkupTyp
         SwWrongList const* (SwTextNode::*const pGetWrongList)() const = 
getTextMarkupFunc(nTextMarkupType);
         if (pGetWrongList)
         {
-            sw::WrongListIteratorCounter iter(*m_pTextFrame, pGetWrongList);
-            nTextMarkupCount = iter.GetElementCount();
+            pIter.reset(new sw::WrongListIteratorCounter(*m_pTextFrame, 
pGetWrongList));
         }
     }
 
+    return pIter;
+}
+
+
+sal_Int32 SwTextMarkupHelper::getTextMarkupCount( const sal_Int32 
nTextMarkupType )
+{
+    sal_Int32 nTextMarkupCount( 0 );
+
+    std::unique_ptr<sw::WrongListIteratorCounter> pIter = 
getIterator(nTextMarkupType);
+    if (pIter)
+        nTextMarkupCount = pIter->GetElementCount();
+
     return nTextMarkupCount;
 }
 
@@ -122,21 +133,7 @@ css::accessibility::TextSegment
     aTextMarkupSegment.SegmentStart = -1;
     aTextMarkupSegment.SegmentEnd = -1;
 
-    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));
-        }
-    }
-
+    std::unique_ptr<sw::WrongListIteratorCounter> pIter = 
getIterator(nTextMarkupType);
     if (pIter)
     {
         auto const oElement(pIter->GetElementAt(nTextMarkupIndex));
@@ -175,21 +172,7 @@ css::uno::Sequence< css::accessibility::TextSegment >
         return uno::Sequence< css::accessibility::TextSegment >();
     }
 
-    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));
-        }
-    }
-
+    std::unique_ptr<sw::WrongListIteratorCounter> pIter = 
getIterator(nTextMarkupType);
     std::vector< css::accessibility::TextSegment > aTmpTextMarkups;
     if (pIter)
     {
diff --git a/sw/source/core/access/textmarkuphelper.hxx 
b/sw/source/core/access/textmarkuphelper.hxx
index 6db3f9bc0e34..daccc0eef4ad 100644
--- a/sw/source/core/access/textmarkuphelper.hxx
+++ b/sw/source/core/access/textmarkuphelper.hxx
@@ -30,6 +30,10 @@ class SwAccessiblePortionData;
 class SwTextFrame;
 class SwWrongList; // #i108125#
 
+namespace sw {
+    class WrongListIteratorCounter;
+}
+
 class SwTextMarkupHelper
 {
     public:
@@ -60,6 +64,8 @@ class SwTextMarkupHelper
         SwTextMarkupHelper( const SwTextMarkupHelper& ) = delete;
         SwTextMarkupHelper& operator=( const SwTextMarkupHelper& ) = delete;
 
+        std::unique_ptr<sw::WrongListIteratorCounter> getIterator(sal_Int32 
nTextMarkupType);
+
         const SwAccessiblePortionData& mrPortionData;
 
         SwTextFrame const* m_pTextFrame;

Reply via email to