Repository: nvaccess/nvda

Issue:
NVDA seems not to support Notepad++ 8.3
### Steps to reproduce:
1. Start Notepad++ 8.3 (downloadable [here](https://notepad-plus-plus.org/downloads/v8.3/)), you should have a blank document.
2. Write some text (just one character is enough).

Alternatively, with an installed version you can just open a file from explorer.

### Actual behavior:
Notepad++ crashes (the app closes), NVDA fails to retrieve file content.

### Expected behavior:
No crash, access to file content.

### System configuration
#### NVDA installed/portable/running from source:
Installed

#### NVDA version:
alpha-24583,61000de2

#### Windows version:
10 21H2

#### Name and version of other software in use when reproducing the issue:
Notepad++ 8.3 (installed and portable versions)

#### Other information about your system:
N/A

### Other questions
#### Does the issue still occur after restarting your computer?
Yes

#### Have you tried any other versions of NVDA? If so, please report their behaviors.
No. But no problem with Notepad++ 8.2.1 and earlier.

#### If add-ons are disabled, is your problem still occurring?
Yes

#### Does the issue still occur after you run the COM Registration Fixing Tool in NVDA's tools menu?
Yes


Discussion:
I can also reproduce this.
@seanbudd 
@feerrenrut 
can you take a look at this?
Out of curiosity, I've just tested with JAWS 2022: also no access to file contents but Notepad++ doesn't crash.
Also does not crash with Narrator, but cannot read file content.

With NVDA, it crashes as soon as you load a field or when typing text in 
an empty file.
@MichelSuch yes but Narrator doesn't work with Notepad++ 8.2 also.
Does this mean we are going to write an issue in the notepad++ repository
I opened an issue before I knew this was related to NVDA actually, https://github.com/notepad-plus-plus/notepad-plus-plus/issues/11133
Today, I downloaded Notepad++ 8.3, and I understood that it is not accessible for us. It means that when I type some Characters and navigate to read what every I typed, but NVDA doesn’t read anything. I don’t have this issue in 8.2, too.


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
@@ -1,19 +1,16 @@
 # -*- coding: UTF-8 -*-
 # A part of NonVisual Desktop Access (NVDA)
-# Copyright (C) 2009-2019 NV Access Limited, Arnold Loubriat, Babbage B.V., Łukasz Golonka
+# Copyright (C) 2007-2022 NV Access Limited, Arnold Loubriat, Babbage B.V., Łukasz Golonka, Joseph Lee,
+# Peter Vágner
 # This file is covered by the GNU General Public License.
 # See the file COPYING for more details.
 
 import ctypes
-import speech
 import textInfos.offsets
 import winKernel
 import winUser
-import globalVars
 import controlTypes
-import config
 from . import Window
-from .. import NVDAObjectTextInfo
 from ..behaviors import EditableTextWithAutoSelectDetection
 import watchdog
 import eventHandler
@@ -67,14 +64,15 @@ class CharacterRangeStruct(ctypes.Structure):
 		('cpMax',ctypes.c_long),
 	]
 
-class TextRangeStruct(ctypes.Structure):
-	_fields_=[
-		('chrg',CharacterRangeStruct),
-		('lpstrText',ctypes.c_char_p),
-	]
 
 class ScintillaTextInfo(textInfos.offsets.OffsetsTextInfo):
 
+	class TextRangeStruct(ctypes.Structure):
+		_fields_ = [
+			('chrg', CharacterRangeStruct),
+			('lpstrText', ctypes.c_char_p),
+		]
+
 	def _get_encoding(self):
 		cp=watchdog.cancellableSendMessage(self.obj.windowHandle,SCI_GETCODEPAGE,0,0)
 		if cp==SC_CP_UTF8:
@@ -171,7 +169,7 @@ def _getLineCount(self):
 
 	def _getTextRange(self,start,end):
 		bufLen = (end - start) + 1
-		textRange = TextRangeStruct()
+		textRange = self.TextRangeStruct()
 		textRange.chrg.cpMin = start
 		textRange.chrg.cpMax = end
 		processHandle = self.obj.processHandle
diff --git a/source/appModules/notepad++.py b/source/appModules/notepad++.py
new file mode 100644
--- /dev/null
+++ b/source/appModules/notepad++.py
@@ -0,0 +1,10 @@
+# A part of NonVisual Desktop Access (NVDA)
+# Copyright (C) 2022 NV Access Limited, Łukasz Golonka
+# This file may be used under the terms of the GNU General Public License, version 2 or later.
+# For more details see: https://www.gnu.org/licenses/gpl-2.0.html
+
+"""This is just an alias which maps the appModule for Notepad++ to the right binary file
+by exposing everything from the real module in its namespace.
+"""
+
+from .notepadPlusPlus import *  # noqa: F401, F403
diff --git a/source/appModules/notepadPlusPlus.py b/source/appModules/notepadPlusPlus.py
new file mode 100644
--- /dev/null
+++ b/source/appModules/notepadPlusPlus.py
@@ -0,0 +1,58 @@
+# A part of NonVisual Desktop Access (NVDA)
+# Copyright (C) 2022 NV Access Limited, Łukasz Golonka
+# This file may be used under the terms of the GNU General Public License, version 2 or later.
+# For more details see: https://www.gnu.org/licenses/gpl-2.0.html
+
+"""AppModule for Notepad++.
+Do not rename! The executable file for Notepad++ is named `notepad++` and `+` is not a valid character
+in Python's import statements.
+This module is mapped to the right binary separately
+and the current name makes it possible to expose it from `nvdaBuiltin` for add-on developers.
+"""
+
+import ctypes
+
+import appModuleHandler
+import NVDAObjects.window.scintilla as ScintillaBase
+
+
+class CharacterRangeStructLongLong(ctypes.Structure):
+	"""By default character ranges in Scintilla are represented by longs.
+	However long is not big enough for files over 2 GB,
+	therefore in 64-bit builds of Notepad++ 8.3 and later
+	these ranges are represented by longlong.
+	"""
+	_fields_ = [
+		('cpMin', ctypes.c_longlong),
+		('cpMax', ctypes.c_longlong),
+	]
+
+
+class ScintillaTextInfoNpp83(ScintillaBase.ScintillaTextInfo):
+	"""Text info for 64-bit builds of Notepad++ 8.3 and later.
+	"""
+
+	class TextRangeStruct(ctypes.Structure):
+		_fields_ = [
+			('chrg', CharacterRangeStructLongLong),
+			('lpstrText', ctypes.c_char_p),
+		]
+
+
+class NppEdit(ScintillaBase.Scintilla):
+
+	name = None  # The name of the editor is not useful.
+
+	def _get_TextInfo(self):
+		if self.appModule.is64BitProcess:
+			appVerMajor, appVerMinor, *__ = self.appModule.productVersion.split(".")
+			if int(appVerMajor) >= 8 and int(appVerMinor) >= 3:
+				return ScintillaTextInfoNpp83
+		return super().TextInfo
+
+
+class AppModule(appModuleHandler.AppModule):
+
+	def chooseNVDAObjectOverlayClasses(self, obj, clsList):
+		if obj.windowClassName == "Scintilla" and obj.windowControlID == 0:
+			clsList.insert(0, NppEdit)


Test patch: