Repository: nvaccess/nvda

Issue:
NVDA freezes in Notepad++ 7.7
### Steps to reproduce:
1. Install Notepad++ 7.7 X64
2. Type a line of text.
3. Press home to move the caret to the first character within the document

### Actual behavior:
NVDA seems to freeze for around 10 seconds, then reports blank.

### Expected behavior:
NVDA directly reads the first character.

### System configuration
#### NVDA installed/portable/running from source:
Installed

#### NVDA version:
alpha-17311

#### Windows version:
Windows 10 1903 build 18362.116

#### Name and version of other software in use when reproducing the issue:
Notepad++ 7.7 x64, either installed or portable

#### Other information about your system:
Also tested on another system with the same configuration. Notepad++ 7.6 works just fine.

### Other questions
#### Does the issue still occur after restarting your PC?
Yes

#### Have you tried any other versions of NVDA? If so, please report their behaviors.
No


Discussion:
> 2. Upgrade Scintilla from v3.56 to v4.14.

Sources: [Official announcement](https://notepad-plus-plus.org/news/notepad-7.7-released.html), [Changelog in the thread](https://notepad-plus-plus.org/community/topic/17668/notepad-7-7-release)

I'm still on Notepad++ 7.6.6 (32-Bit). Thanks for the hint.

@leonardder: You interchanged the two behaviors. And could you please test the 32-Bit version as well?
Okay, I already opened "huc6-u+0000-u+ffff.tbi" from the [HUC Braille Tables](https://danielmayr.at/huc/) (1.94 MB, 65,568 lines) with the portable (7z) versions of Notepad++ 7.7 on Win7x64 with NVDA 2018.1. The 32-Bit version loaded the "little" tbi file (= plain/normal text file) immediately and the 64-Bit version required up to 11 seconds on an Intel Core i7 960 (more than 9 years old, but still fast enough) with 6 GB RAM. Okay, both portable Notepad++ versions were extracted on and run from a HDD, not from a SSD, on which Win7 is running. But after the tbi file was fully loaded in Notepad++ 64-Bit, searching for "266f" worked as expected. And it's the same with the navigation within this tbi file.
cc: @DataTriny 
@leonardder I have just moved the text from expected behavior into the actual behavior and vice versa. I hope it is ok. :-)
hello.
i tested with nvda 2017.2 which is the best version for me on windows xp and notepad++ 7.7 32bit.
i tested one book which is 4.19 mb in html format and even i converted it to text and cant reproduce the mentioned issue in html and text format of my book!
notepad++ opened for me these files very fast and nvda did not freeze.
but since my book is very large, (it contained 1307 when i opened it in libreoffice,) navigation in html file especially was a little slower than simple files for me.
@DrSooom wrote:
> ... the 64-Bit version required up to 11 seconds on an Intel Core i7 960 (more than 9 years old, but still fast enough) with 6 GB RAM.

This is exactly where I"m suffering from. I updated the initial description accordingly.

@Adriani90 wrote:
> I have just moved the text from expected behavior into the actual behavior and vice versa. I hope it is ok. :-)

Thanks for that!
I've also found the underlying issue.

When expanding to character, NVDA sends the SCI_POSITIONAFTER message to the control, passing -1 in the case offset is 0. However, in the X64 version of Notepad++, the result of that call is the length of the document, whereas in the X86 version, it returns 0 as expected.

In the case the length of the document is returned, NVDA ends up in a while loop. This code really has to be revisited.

Resolving patch:
diff --git a/source/NVDAObjects/window/scintilla.py b/source/NVDAObjects/window/scintilla.py
--- a/source/NVDAObjects/window/scintilla.py
+++ b/source/NVDAObjects/window/scintilla.py
@@ -14,7 +14,7 @@
 import watchdog
 import eventHandler
 
-#Window messages
+# Window messages
 SCI_POSITIONFROMPOINT=2022
 SCI_POINTXFROMPOSITION=2164
 SCI_POINTYFROMPOSITION=2165
@@ -48,6 +48,8 @@
 SCI_POSITIONAFTER=2418
 
 #constants
+#: Represents an invalid position within a document.
+INVALID_POSITION=-1
 STYLE_DEFAULT=32
 SC_CP_UTF8=65001
 
@@ -218,7 +220,8 @@ def _getCharacterOffsets(self,offset):
 		end=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_POSITIONAFTER,offset,0)
 		start=offset
 		tempOffset=offset-1
-		while True:
+		
+		while tempOffset > INVALID_POSITION:
 			start=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_POSITIONAFTER,tempOffset,0)
 			if start<end:
 				break


Test patch: