diff --git a/source/NVDAObjects/window/edit.py b/source/NVDAObjects/window/edit.py index d2c513e33ff..114c584d896 100644 --- a/source/NVDAObjects/window/edit.py +++ b/source/NVDAObjects/window/edit.py @@ -6,6 +6,7 @@ from typing import ( Dict, Optional, + Self, Union, ) @@ -842,6 +843,18 @@ def updateSelection(self): self.obj.ITextSelectionObject.start=self._rangeObj.start self.obj.ITextSelectionObject.end=self._rangeObj.end + def getTextInfoForCodepointMovement(self) -> Self: + # # In PoEdit ITextDocumentTextInfo sometimes cannot access the last character when that character is + # a newline. In this case collapse(True) takes us not to the end of textInfo, but right before + # trailing newline character, which causes adverse side effects in moveToCodepointOffset() function. + # Trimming trailing newline character here to work around. + info = self.copy() + collapsedInfo = info.copy() + collapsedInfo.collapse(end=True) + if collapsedInfo.compareEndPoints(info, "endToEnd") < 0: + info.setEndPoint(collapsedInfo, "endToEnd") + return info + class EditBase(Window): """"Base class for Edit and Rich Edit controls, shared by legacy and UIA implementations.""" diff --git a/source/textInfos/__init__.py b/source/textInfos/__init__.py index fdaa7d502c4..043be02912f 100755 --- a/source/textInfos/__init__.py +++ b/source/textInfos/__init__.py @@ -655,7 +655,10 @@ def getMathMl(self, field): @raise LookupError: If MathML can't be retrieved for this field. """ raise NotImplementedError - + + def getTextInfoForCodepointMovement(self) -> Self: + return self.copy() + def moveToCodepointOffset( self, codepointOffset: int, @@ -748,15 +751,15 @@ def moveToCodepointOffset( we reduce the count of characters in order to make sure the algorithm makes some progress on each iteration. """ - text = self.text + info = self.getTextInfoForCodepointMovement() + text = info.text if codepointOffset < 0 or codepointOffset > len(text): raise ValueError if codepointOffset == 0 or codepointOffset == len(text): - result = self.copy() + result = info.copy() result.collapse(end=codepointOffset > 0) return result - info = self.copy() # Total codepoint Length represents length in python characters of Current TextInfo we're workoing with. # We start with self, and then gradually divide and conquer in order to find desired offset. totalCodepointOffset = len(text)