Repository: nvaccess/nvda

Issue:
More cursor manager selection bugs #1.
1. paste this into the python console.
api.copyToClip(u"d\n"*30)
2. Paste the result into instantbird (Do it to yourself, not someone else).
3. press enter.
4. Press control+end, and then shift up arrow about 5 times (Any number should work).
5. press shift+home and shift+end. Nothing happens.
Expected: if shift+end is pressed, line n-k is unselected.
Actual: nothing.



Discussion:
Simplified STR:

1. Open this URL in Firefox: `data:text/html,ab`
2. In browse mode, press control+home.
3. Press right arrow to move to "b".
4. Press shift+end.
    * Expected: "b selected"
    * Actual: Nothing.

In short, shift+end does not work if the caret is at the last character of the line.

Not a regression: also fails in 2016.3.

Resolving patch:
diff --git a/source/cursorManager.py b/source/cursorManager.py
--- a/source/cursorManager.py
+++ b/source/cursorManager.py
@@ -334,13 +334,10 @@ def script_selectToBeginningOfLine(self,gesture):
 			self._selectionMovementScriptHelper(unit=textInfos.UNIT_LINE,direction=-1)
 
 	def script_selectToEndOfLine(self,gesture):
-		curInfo=self.makeTextInfo(textInfos.POSITION_SELECTION)
-		curInfo.collapse()
-		tempInfo=curInfo.copy()
-		curInfo.expand(textInfos.UNIT_CHARACTER)
-		tempInfo.expand(textInfos.UNIT_LINE)
-		if curInfo.compareEndPoints(tempInfo,"endToEnd")<0:
-			self._selectionMovementScriptHelper(unit=textInfos.UNIT_LINE,direction=1)
+		# #7157: There isn't necessarily a line ending character or insertion point at the end of a line.
+		# Therefore, always allow select to end of line,
+		# even if the caret is already on the last character of the line.
+		self._selectionMovementScriptHelper(unit=textInfos.UNIT_LINE,direction=1)
 
 	def script_selectToTopOfDocument(self,gesture):
 		self._selectionMovementScriptHelper(toPosition=textInfos.POSITION_FIRST)


Test patch:
diff --git a/tests/unit/test_cursorManager.py b/tests/unit/test_cursorManager.py
--- a/tests/unit/test_cursorManager.py
+++ b/tests/unit/test_cursorManager.py
@@ -27,6 +27,13 @@ def test_prevChar(self):
 		cm.script_moveByCharacter_back(None)
 		self.assertEqual(cm.selectionOffsets, (0, 0)) # Caret at "a"
 
+	def test_endOfLine(self):
+		"""End of line in a CursorManager moves to the last character; there is no "insertion point".
+		"""
+		cm = CursorManager(text="ab") # Caret at "a"
+		cm.script_endOfLine(None)
+		self.assertEqual(cm.selectionOffsets, (1, 1)) # Caret at "b"
+
 class TestSelection(unittest.TestCase):
 
 	def test_selForward(self):
@@ -155,6 +162,15 @@ def test_selToBeginningOfLine(self):
 		cm.script_selectToBeginningOfLine(None)
 		self.assertEqual(cm.selectionOffsets, (3, 4)) # "c" selected
 
+	def test_selToEndOfLineAtEnd(self):
+		"""Test selecting to the end of the line after moving to the end of the line (#7157).
+		End of line in a CursorManager moves to the last character; there is no "insertion point".
+		So, doing this must select the last character.
+		"""
+		cm = CursorManager(text="ab", selection=(1, 1)) # Caret at "b"
+		cm.script_selectToEndOfLine(None)
+		self.assertEqual(cm.selectionOffsets, (1, 2)) # "b" selected
+
 	def test_selToBeginningOfLineAtBeginning(self):
 		"""Test selecting to the beginning of the line when the caret is already at the beginning of the line.
 		In this case, nothing should happen.