summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorColomban Wendling <cwendling@hypra.fr>2023-05-02 20:50:52 +0200
committerMichael Weghorn <m.weghorn@posteo.de>2023-05-23 18:39:08 +0200
commitbd5c3582581f37513f45b518e348f443d5d57334 (patch)
tree6e9bce540afb614154d695b6e3280a198254b089 /sw
parentdce8d2dbc48eb1c7597afec236dc51b4b8aede9c (diff)
a11y: Fix returning unpaired surrogates when retrieving characters
Fix implementations of XAccessibleText's getTextAtIndex(), getTextBeforeIndex() and getTextBehindIndex() when called with AccessibleTextType::CHARACTER to return the whole code point rather than an unpaired surrogate. This is still not perfect because XAccessibleText::getCharacterCount() will return an incorrect value (code units rather than code points), but it fixes the most useful case of retrieving the character at e.g. the caret offset. This fixes the GTK3 and Windows backends as well without further changes. Qt6 also mostly works according to Michael Weghorn, but for a bug on Qt's side (https://bugreports.qt.io/browse/QTBUG-113438). MacOS backend doesn't seem to be affected in the first place. Change-Id: I53f07bcba78c6b267939257542a521b106101e96 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151303 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
Diffstat (limited to 'sw')
-rw-r--r--sw/CppunitTest_sw_a11y.mk1
-rw-r--r--sw/qa/extras/accessibility/testdocuments/unicode.fodf135
-rw-r--r--sw/qa/extras/accessibility/unicode.cxx102
-rw-r--r--sw/source/core/access/accpara.cxx19
-rw-r--r--sw/source/core/access/accpara.hxx1
5 files changed, 252 insertions, 6 deletions
diff --git a/sw/CppunitTest_sw_a11y.mk b/sw/CppunitTest_sw_a11y.mk
index 282f580423aa..070f0e402d88 100644
--- a/sw/CppunitTest_sw_a11y.mk
+++ b/sw/CppunitTest_sw_a11y.mk
@@ -12,6 +12,7 @@ $(eval $(call gb_CppunitTest_CppunitTest,sw_a11y))
$(eval $(call gb_CppunitTest_add_exception_objects,sw_a11y, \
sw/qa/extras/accessibility/basics \
sw/qa/extras/accessibility/dialogs \
+ sw/qa/extras/accessibility/unicode \
))
$(eval $(call gb_CppunitTest_use_libraries,sw_a11y, \
diff --git a/sw/qa/extras/accessibility/testdocuments/unicode.fodf b/sw/qa/extras/accessibility/testdocuments/unicode.fodf
new file mode 100644
index 000000000000..9bdccebf03ec
--- /dev/null
+++ b/sw/qa/extras/accessibility/testdocuments/unicode.fodf
@@ -0,0 +1,135 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:meta><meta:creation-date>2022-10-12T18:05:31.408900485</meta:creation-date><dc:date>2023-05-11T10:35:16.229411275</dc:date><meta:editing-duration>PT9M45S</meta:editing-duration><meta:editing-cycles>3</meta:editing-cycles><meta:generator>LibreOfficeDev/7.6.0.0.alpha0$Linux_X86_64 LibreOffice_project/44c4d9ba0d480c8e2f05c9400f310184efc7e40c</meta:generator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="1" meta:paragraph-count="2" meta:word-count="2" meta:character-count="8" meta:non-whitespace-character-count="8"/></office:meta>
+ <office:font-face-decls>
+ <style:font-face style:name="DejaVu Sans" svg:font-family="'DejaVu Sans'" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="FreeSans1" svg:font-family="FreeSans" style:font-family-generic="system" style:font-pitch="variable"/>
+ <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
+ <style:font-face style:name="Quivira" svg:font-family="Quivira" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+ <style:default-style style:family="graphic">
+ <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:writing-mode="lr-tb" style:flow-with-text="false"/>
+ <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" loext:tab-stop-distance="0cm" style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
+ <style:tab-stops/>
+ </style:paragraph-properties>
+ <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="fr" fo:country="FR" style:letter-kerning="true" style:font-name-asian="DejaVu Sans" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="FreeSans1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/>
+ </style:default-style>
+ <style:default-style style:family="paragraph">
+ <style:paragraph-properties fo:orphans="2" fo:widows="2" fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+ <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="fr" fo:country="FR" style:letter-kerning="true" style:font-name-asian="DejaVu Sans" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="FreeSans1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
+ </style:default-style>
+ <style:default-style style:family="table">
+ <style:table-properties table:border-model="collapsing"/>
+ </style:default-style>
+ <style:default-style style:family="table-row">
+ <style:table-row-properties fo:keep-together="auto"/>
+ </style:default-style>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text"/>
+ <text:outline-style style:name="Outline">
+ <text:outline-level-style text:level="1" loext:num-list-format="%1%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="2" loext:num-list-format="%2%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="3" loext:num-list-format="%3%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="4" loext:num-list-format="%4%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="5" loext:num-list-format="%5%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ <text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format="">
+ <style:list-level-properties text:list-level-position-and-space-mode="label-alignment">
+ <style:list-level-label-alignment text:label-followed-by="listtab"/>
+ </style:list-level-properties>
+ </text:outline-level-style>
+ </text:outline-style>
+ <text:notes-configuration text:note-class="footnote" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/>
+ <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/>
+ <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/>
+ <loext:theme loext:name="Office Theme">
+ <loext:color-table loext:name="LibreOffice">
+ <loext:color loext:name="dk1" loext:color="#000000"/>
+ <loext:color loext:name="lt1" loext:color="#ffffff"/>
+ <loext:color loext:name="dk2" loext:color="#000000"/>
+ <loext:color loext:name="lt2" loext:color="#ffffff"/>
+ <loext:color loext:name="accent1" loext:color="#18a303"/>
+ <loext:color loext:name="accent2" loext:color="#0369a3"/>
+ <loext:color loext:name="accent3" loext:color="#a33e03"/>
+ <loext:color loext:name="accent4" loext:color="#8e03a3"/>
+ <loext:color loext:name="accent5" loext:color="#c99c00"/>
+ <loext:color loext:name="accent6" loext:color="#c9211e"/>
+ <loext:color loext:name="hlink" loext:color="#0000ee"/>
+ <loext:color loext:name="folHlink" loext:color="#551a8b"/>
+ </loext:color-table>
+ </loext:theme>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Standard">
+ <style:text-properties style:font-name="Quivira" fo:font-size="24pt" style:font-name-asian="Quivira" style:font-size-asian="24pt" style:font-name-complex="Quivira" style:font-size-complex="24pt"/>
+ </style:style>
+ <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Standard">
+ <style:text-properties style:font-name="Quivira" fo:font-size="24pt" style:font-name-asian="Quivira" style:font-size-asian="24pt" style:font-name-complex="Quivira" style:font-size-complex="24pt"/>
+ </style:style>
+ <style:page-layout style:name="pm1">
+ <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0cm" loext:margin-gutter="0cm">
+ <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/>
+ </style:page-layout-properties>
+ <style:header-style/>
+ <style:footer-style/>
+ </style:page-layout>
+ <style:style style:name="dp1" style:family="drawing-page">
+ <style:drawing-page-properties draw:background-size="full"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:master-styles>
+ <style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"/>
+ </office:master-styles>
+ <office:body>
+ <office:text>
+ <text:sequence-decls>
+ <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
+ <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
+ </text:sequence-decls>
+ <text:p text:style-name="P1">🂡🂮🂬🂫</text:p>
+ <text:p text:style-name="P2">akcj</text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/accessibility/unicode.cxx b/sw/qa/extras/accessibility/unicode.cxx
new file mode 100644
index 000000000000..b4b2b5f6fc84
--- /dev/null
+++ b/sw/qa/extras/accessibility/unicode.cxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <com/sun/star/accessibility/AccessibleTextType.hpp>
+#include <com/sun/star/accessibility/XAccessibleText.hpp>
+#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
+
+#include <test/a11y/swaccessibletestbase.hxx>
+
+using namespace css;
+using namespace accessibility;
+
+// Checks fetching multi-unit characters
+CPPUNIT_TEST_FIXTURE(test::SwAccessibleTestBase, TestUnicodeSP)
+{
+ loadFromSrc(u"/sw/qa/extras/accessibility/testdocuments/unicode.fodf");
+
+ auto xContext = getDocumentAccessibleContext()->getAccessibleChild(0)->getAccessibleContext();
+
+ uno::Reference<XAccessibleText> para(xContext, uno::UNO_QUERY_THROW);
+ auto segment = para->getTextAtIndex(0, AccessibleTextType::CHARACTER);
+ CPPUNIT_ASSERT_EQUAL(OUString(u"\U0001f0a1"), segment.SegmentText);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), segment.SegmentStart);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), segment.SegmentEnd);
+
+ segment = para->getTextBeforeIndex(2, AccessibleTextType::CHARACTER);
+ CPPUNIT_ASSERT_EQUAL(OUString(u"\U0001f0a1"), segment.SegmentText);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(0), segment.SegmentStart);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), segment.SegmentEnd);
+
+ segment = para->getTextBehindIndex(0, AccessibleTextType::CHARACTER);
+ CPPUNIT_ASSERT_EQUAL(OUString(u"\U0001f0ae"), segment.SegmentText);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(2), segment.SegmentStart);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(4), segment.SegmentEnd);
+}
+
+// Checks getTextBehindIndex() with multi-unit characters
+CPPUNIT_TEST_FIXTURE(test::SwAccessibleTestBase, TestUnicodeSPBehindIndex)
+{
+ loadFromSrc(u"/sw/qa/extras/accessibility/testdocuments/unicode.fodf");
+
+ auto xContext = getDocumentAccessibleContext()->getAccessibleChild(0)->getAccessibleContext();
+
+ uno::Reference<XAccessibleText> para(xContext, uno::UNO_QUERY_THROW);
+ auto nChCount = para->getCharacterCount();
+
+ // verify bounds are properly handled
+ CPPUNIT_ASSERT_THROW(para->getTextBehindIndex(-1, AccessibleTextType::CHARACTER),
+ lang::IndexOutOfBoundsException);
+ CPPUNIT_ASSERT_THROW(para->getTextBehindIndex(nChCount + 1, AccessibleTextType::CHARACTER),
+ lang::IndexOutOfBoundsException);
+
+ auto segment = para->getTextBehindIndex(nChCount, AccessibleTextType::CHARACTER);
+ CPPUNIT_ASSERT_EQUAL(OUString(u""), segment.SegmentText);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), segment.SegmentStart);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), segment.SegmentEnd);
+
+ segment = para->getTextBehindIndex(nChCount - 2, AccessibleTextType::CHARACTER);
+ CPPUNIT_ASSERT_EQUAL(OUString(u""), segment.SegmentText);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), segment.SegmentStart);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), segment.SegmentEnd);
+
+ segment = para->getTextBehindIndex(nChCount - 4, AccessibleTextType::CHARACTER);
+ CPPUNIT_ASSERT_EQUAL(OUString(u"\U0001f0ab"), segment.SegmentText);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(6), segment.SegmentStart);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(8), segment.SegmentEnd);
+
+ // verify bounds behave the same with single unit characters, just as a validation
+ xContext = getNextFlowingSibling(xContext);
+ CPPUNIT_ASSERT(xContext.is());
+ para.set(xContext, uno::UNO_QUERY_THROW);
+
+ nChCount = para->getCharacterCount();
+
+ CPPUNIT_ASSERT_THROW(para->getTextBehindIndex(-1, AccessibleTextType::CHARACTER),
+ lang::IndexOutOfBoundsException);
+ CPPUNIT_ASSERT_THROW(para->getTextBehindIndex(nChCount + 1, AccessibleTextType::CHARACTER),
+ lang::IndexOutOfBoundsException);
+
+ segment = para->getTextBehindIndex(nChCount, AccessibleTextType::CHARACTER);
+ CPPUNIT_ASSERT_EQUAL(OUString(u""), segment.SegmentText);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), segment.SegmentStart);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), segment.SegmentEnd);
+
+ segment = para->getTextBehindIndex(nChCount - 1, AccessibleTextType::CHARACTER);
+ CPPUNIT_ASSERT_EQUAL(OUString(u""), segment.SegmentText);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), segment.SegmentStart);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(-1), segment.SegmentEnd);
+
+ segment = para->getTextBehindIndex(nChCount - 2, AccessibleTextType::CHARACTER);
+ CPPUNIT_ASSERT_EQUAL(OUString(u"j"), segment.SegmentText);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(3), segment.SegmentStart);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(4), segment.SegmentEnd);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/sw/source/core/access/accpara.cxx b/sw/source/core/access/accpara.cxx
index d00a49d10227..05bbacfbbd2a 100644
--- a/sw/source/core/access/accpara.cxx
+++ b/sw/source/core/access/accpara.cxx
@@ -536,13 +536,18 @@ const SwRangeRedline* SwAccessibleParagraph::GetRedlineAtIndex()
bool SwAccessibleParagraph::GetCharBoundary(
i18n::Boundary& rBound,
+ std::u16string_view text,
sal_Int32 nPos )
{
if( GetPortionData().FillBoundaryIFDateField( rBound, nPos) )
return true;
+ auto nPosEnd = nPos;
+ o3tl::iterateCodePoints(text, &nPosEnd);
+
rBound.startPos = nPos;
- rBound.endPos = nPos+1;
+ rBound.endPos = nPosEnd;
+
return true;
}
@@ -669,7 +674,7 @@ bool SwAccessibleParagraph::GetTextBoundary(
break;
case AccessibleTextType::CHARACTER:
- bRet = GetCharBoundary( rBound, nPos );
+ bRet = GetCharBoundary( rBound, rText, nPos );
break;
case AccessibleTextType::LINE:
@@ -2331,8 +2336,9 @@ OUString SwAccessibleParagraph::getTextRange(
i18n::Boundary preBound = aBound;
while(preBound.startPos==aBound.startPos && nIndex > 0)
{
- nIndex = min( nIndex, preBound.startPos ) - 1;
- if( nIndex < 0 ) break;
+ nIndex = min(nIndex, preBound.startPos);
+ if (nIndex <= 0) break;
+ rText.iterateCodePoints(&nIndex, -1);
GetTextBoundary( preBound, rText, nIndex, nTextType );
}
//if (nIndex>0)
@@ -2349,9 +2355,10 @@ OUString SwAccessibleParagraph::getTextRange(
bool bWord = false;
while( !bWord )
{
- nIndex = min( nIndex, aBound.startPos ) - 1;
- if( nIndex >= 0 )
+ nIndex = min(nIndex, aBound.startPos);
+ if (nIndex > 0)
{
+ rText.iterateCodePoints(&nIndex, -1);
bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
}
else
diff --git a/sw/source/core/access/accpara.hxx b/sw/source/core/access/accpara.hxx
index eb5825b54fb9..3f6c57231d49 100644
--- a/sw/source/core/access/accpara.hxx
+++ b/sw/source/core/access/accpara.hxx
@@ -195,6 +195,7 @@ protected:
//helpers for word boundaries
bool GetCharBoundary( css::i18n::Boundary& rBound,
+ std::u16string_view text,
sal_Int32 nPos );
bool GetWordBoundary( css::i18n::Boundary& rBound,
const OUString& rText,