diff --git a/source/JABHandler.py b/source/JABHandler.py index 8c148c454e..55014603f2 100644 --- a/source/JABHandler.py +++ b/source/JABHandler.py @@ -647,7 +647,13 @@ def getAccessibleTextSelectionInfo(self): bridgeDll.getAccessibleTextSelectionInfo(self.vmID, self.accContext, byref(textSelectionInfo)) return textSelectionInfo - def getAccessibleTextRange(self, start, end): + def _javaGetAccessibleTextRange(self, start: int, end: int) -> str: + """Helper method that performs the Java Access Bridge call to obtain the text of this object based on a (start, end) range. + + :param start: The start index to get from, inclusive. + :param end: The end index to fetch to, exclusive. + :return: the text within the given indices as a string. + """ length = (end + 1) - start if length <= 0: return "" @@ -656,6 +662,32 @@ def getAccessibleTextRange(self, start, end): bridgeDll.getAccessibleTextRange(self.vmID, self.accContext, start, end, buf, length) return textUtils.getTextFromRawBytes(buf.raw, numChars=length, encoding=textUtils.WCHAR_ENCODING) + # Constant gotten from AccessBridgePackages.h, + # minus one to accommodate the null character + MAX_BUFFER_SIZE = 10239 + + def getAccessibleTextRange(self, start: int, end: int) -> str: + """Obtains the text of this object based on a (start, end) range. + If the text is too large to fit in the buffer, this method will split the Java Access Bridge calls in chunks to get the whole text. + + :param start: The start index to get from, inclusive. + :param end: The end index to fetch to, exclusive. + :return: the text within the given indices as a string. + """ + length = (end + 1) - start + if length < self.MAX_BUFFER_SIZE: + # Fast path: perform the Java Access Bridge call directly + return self._javaGetAccessibleTextRange(start, end) + + text = [] + while start <= end: + bufferSize = min(self.MAX_BUFFER_SIZE, length) + text.append(self._javaGetAccessibleTextRange(start, start + bufferSize - 1)) + start += bufferSize + length -= bufferSize + + return "".join(text) + def getAccessibleTextLineBounds(self, index): index = max(index, 0) log.debug("lineBounds: index %s" % index) diff --git a/user_docs/en/changes.md b/user_docs/en/changes.md index 52fefa2bc1..133fe64d97 100644 --- a/user_docs/en/changes.md +++ b/user_docs/en/changes.md @@ -55,6 +55,7 @@ Prefix matching on command line flags, e.g. using `--di` for `--disable-addons` ### Bug Fixes +* NVDA will no longer crash when selecting all text in certain source files in Android Studio or IntelliJ Idea. (#17418, @thgcode) * Math reading has been fixed for some web elements. Specifically, MathML inside of span and other elements that have the attribute `role="math"`. (#15058) * Native support for the Dot Pad tactile graphics device from Dot Inc as a multiline braille display. (#17007)