Bug 1445954 - atk: Fix getTextAfter/Before/AtOffset in character boundary case. r=surkov
authorSamuel Thibault <samuel.thibault@ens-lyon.org>
Fri, 16 Mar 2018 05:52:00 -0400
changeset 409396 f2e703f7b735341914c30e440060b8d2c5268d5c
parent 409395 3f714569d3341fe328de828988c04e12792e70b2
child 409397 a8c4f87b7c3d4e049deb5ba637abd9b80dafc995
push id33687
push userapavel@mozilla.com
push dateThu, 22 Mar 2018 09:31:48 +0000
treeherdermozilla-central@7771df14ea18 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssurkov
bugs1445954
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1445954 - atk: Fix getTextAfter/Before/AtOffset in character boundary case. r=surkov
accessible/atk/nsMaiInterfaceText.cpp
--- a/accessible/atk/nsMaiInterfaceText.cpp
+++ b/accessible/atk/nsMaiInterfaceText.cpp
@@ -155,21 +155,54 @@ getTextCB(AtkText *aText, gint aStartOff
   } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
     return DOMtoATK::NewATKString(proxy, aStartOffset, aEndOffset,
          DOMtoATK::AtkStringConvertFlags::None);
   }
 
   return nullptr;
 }
 
+static gint getCharacterCountCB(AtkText* aText);
+
+// Note: this does not support magic offsets, which is fine for its callers
+// which do not implement any.
+static gchar*
+getCharTextAtOffset(AtkText* aText, gint aOffset,
+                    gint* aStartOffset, gint* aEndOffset)
+{
+  gint end = aOffset + 1;
+  gint count = getCharacterCountCB(aText);
+
+  if (aOffset > count) {
+    aOffset = count;
+  }
+  if (end > count) {
+    end = count;
+  }
+  if (aOffset < 0) {
+    aOffset = 0;
+  }
+  if (end < 0) {
+    end = 0;
+  }
+  *aStartOffset = aOffset;
+  *aEndOffset = end;
+
+  return getTextCB(aText, aOffset, end);
+}
+
 static gchar*
 getTextAfterOffsetCB(AtkText *aText, gint aOffset,
                      AtkTextBoundary aBoundaryType,
                      gint *aStartOffset, gint *aEndOffset)
 {
+  if (aBoundaryType == ATK_TEXT_BOUNDARY_CHAR) {
+    return getCharTextAtOffset(aText, aOffset + 1, aStartOffset, aEndOffset);
+  }
+
     nsAutoString autoStr;
   int32_t startOffset = 0, endOffset = 0;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (accWrap) {
     HyperTextAccessible* text = accWrap->AsHyperText();
     if (!text || !text->IsTextRole())
       return nullptr;
 
@@ -187,16 +220,20 @@ getTextAfterOffsetCB(AtkText *aText, gin
   return DOMtoATK::Convert(autoStr);
 }
 
 static gchar*
 getTextAtOffsetCB(AtkText *aText, gint aOffset,
                   AtkTextBoundary aBoundaryType,
                   gint *aStartOffset, gint *aEndOffset)
 {
+  if (aBoundaryType == ATK_TEXT_BOUNDARY_CHAR) {
+    return getCharTextAtOffset(aText, aOffset, aStartOffset, aEndOffset);
+  }
+
   nsAutoString autoStr;
   int32_t startOffset = 0, endOffset = 0;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (accWrap) {
     HyperTextAccessible* text = accWrap->AsHyperText();
     if (!text || !text->IsTextRole())
       return nullptr;
 
@@ -233,16 +270,20 @@ getCharacterAtOffsetCB(AtkText* aText, g
   return 0;
 }
 
 static gchar*
 getTextBeforeOffsetCB(AtkText *aText, gint aOffset,
                       AtkTextBoundary aBoundaryType,
                       gint *aStartOffset, gint *aEndOffset)
 {
+  if (aBoundaryType == ATK_TEXT_BOUNDARY_CHAR) {
+    return getCharTextAtOffset(aText, aOffset - 1, aStartOffset, aEndOffset);
+  }
+
   nsAutoString autoStr;
   int32_t startOffset = 0, endOffset = 0;
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (accWrap) {
     HyperTextAccessible* text = accWrap->AsHyperText();
     if (!text || !text->IsTextRole())
       return nullptr;