diff -r 338832737372 call/ScintillaCall.cxx
--- a/call/ScintillaCall.cxx	Sun May 01 14:31:17 2022 +1000
+++ b/call/ScintillaCall.cxx	Sat May 07 12:25:17 2022 +1000
@@ -16,6 +16,7 @@
 #include "ScintillaTypes.h"
 #include "ScintillaMessages.h"
 #include "ScintillaCall.h"
+#include "ScintillaStructures.h"
 
 namespace Scintilla {
 
@@ -110,6 +111,17 @@
 	}
 }
 
+std::string ScintillaCall::StringOfRange(Span span) {
+	if (span.Length() == 0) {
+		return std::string();
+	} else {
+		std::string text(span.Length(), '\0');
+		TextRangeFull tr{ {span.start, span.end}, text.data() };
+		GetTextRangeFull(&tr);
+		return text;
+	}
+}
+
 Position ScintillaCall::ReplaceTarget(std::string_view text) {
 	return ScintillaCall::CallString(Message::ReplaceTarget, text.length(), text.data());
 }
@@ -1187,6 +1199,10 @@
 	return CallPointer(Message::GetTextRange, 0, tr);
 }
 
+Position ScintillaCall::GetTextRangeFull(void *tr) {
+	return CallPointer(Message::GetTextRangeFull, 0, tr);
+}
+
 void ScintillaCall::HideSelection(bool hide) {
 	Call(Message::HideSelection, hide);
 }
diff -r 338832737372 doc/ScintillaDoc.html
--- a/doc/ScintillaDoc.html	Sun May 01 14:31:17 2022 +1000
+++ b/doc/ScintillaDoc.html	Sat May 07 12:25:17 2022 +1000
@@ -531,6 +531,7 @@
      <a class="message" href="#SCI_SETREADONLY">SCI_SETREADONLY(bool readOnly)</a><br />
      <a class="message" href="#SCI_GETREADONLY">SCI_GETREADONLY &rarr; bool</a><br />
      <a class="message" href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE(&lt;unused&gt;, Sci_TextRange *tr) &rarr; position</a><br />
+     <a class="message" href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGEFULL(&lt;unused&gt;, Sci_TextRangeFull *tr) &rarr; position</a><br />
      <a class="message" href="#SCI_ALLOCATE">SCI_ALLOCATE(position bytes)</a><br />
      <a class="message" href="#SCI_ALLOCATELINES">SCI_ALLOCATELINES(line lines)</a><br />
      <a class="message" href="#SCI_ADDTEXT">SCI_ADDTEXT(position length, const char *text)</a><br />
@@ -614,13 +615,17 @@
     only, attempts to modify the text cause the <a class="message"
     href="#SCN_MODIFYATTEMPTRO"><code>SCN_MODIFYATTEMPTRO</code></a> notification.</p>
 
-    <p><b id="SCI_GETTEXTRANGE">SCI_GETTEXTRANGE(&lt;unused&gt;, <a class="jump" href="#Sci_TextRange">Sci_TextRange</a> *tr) &rarr; position</b><br />
+    <p>
+    <b id="SCI_GETTEXTRANGE">SCI_GETTEXTRANGE(&lt;unused&gt;, <a class="jump" href="#Sci_TextRange">Sci_TextRange</a> *tr) &rarr; position</b><br />
+    <b id="SCI_GETTEXTRANGEFULL">SCI_GETTEXTRANGEFULL(&lt;unused&gt;, <a class="jump" href="#Sci_TextRangeFull">Sci_TextRangeFull</a> *tr) &rarr; position</b><br />
      This collects the text between the positions <code>cpMin</code> and <code>cpMax</code> and
     copies it to <code>lpstrText</code> (see <code>struct Sci_TextRange</code> in
     <code>Scintilla.h</code>). If <code>cpMax</code> is -1, text is returned to the end of the
     document. The text is 0 terminated, so you must supply a buffer that is at least 1 character
     longer than the number of characters you wish to read. The return value is the length of the
     returned text not including the terminating 0.</p>
+    <p><code>SCI_GETTEXTRANGEFULL</code> uses 64-bit positions on all platforms so is safe for documents larger than 2GB.
+    It should always be used in preference to <code>SCI_GETTEXTRANGE</code> which will be deprecated in a future release.</p>
 
     <p>See also: <code><a class="seealso" href="#SCI_GETSELTEXT">SCI_GETSELTEXT</a>,
     <a class="seealso" href="#SCI_GETLINE">SCI_GETLINE</a>,
@@ -721,8 +726,9 @@
      These structures are defined to be exactly the same shape as the Win32 <code>TEXTRANGE</code>
     and <code>CHARRANGE</code>, so that older code that treats Scintilla as a RichEdit will
     work.</p>
-    <p>In a future release the type <code>Sci_PositionCR</code> will be redefined to be 64-bits when Scintilla is
-    built for 64-bits on all platforms.</p>
+    <p>In a future release, these types will be deprecated.
+    <a class="seealso" href="#SCI_MARGINSETSTYLEOFFSET">SCI_GETTEXTRANGEFULL</a>, <code>Sci_TextRangeFull</code>
+    and <code>Sci_CharacterRangeFull</code> should be used instead.</p>
 <pre>
 typedef long Sci_PositionCR;
 
@@ -737,6 +743,23 @@
 };
 </pre>
 
+    <p><b id="Sci_TextRangeFull">Sci_TextRangeFull</b> and <b id="Sci_CharacterRangeFull">Sci_CharacterRangeFull</b><br />
+     These structures are the same as <code>Sci_TextRange</code> and <code>Sci_CharacterRange</code> except that positions are
+     always 64-bit in 64-bit builds so will work on documents larger than 2GB.</p>
+<pre>
+typedef ptrdiff_t Sci_Position;
+
+struct Sci_CharacterRangeFull {
+	Sci_Position cpMin;
+	Sci_Position cpMax;
+};
+
+struct Sci_TextRangeFull {
+	struct Sci_CharacterRangeFull chrg;
+	char *lpstrText;
+};
+</pre>
+
     <h3 id="EncodedAccess">Specific to GTK, Cocoa and Windows only: Access to encoded text</h3>
 
     <p><b id="SCI_TARGETASUTF8">SCI_TARGETASUTF8(&lt;unused&gt;, char *s) &rarr; position</b><br />
diff -r 338832737372 include/Scintilla.h
--- a/include/Scintilla.h	Sun May 01 14:31:17 2022 +1000
+++ b/include/Scintilla.h	Sat May 07 12:25:17 2022 +1000
@@ -487,6 +487,7 @@
 #define SCI_SETSEL 2160
 #define SCI_GETSELTEXT 2161
 #define SCI_GETTEXTRANGE 2162
+#define SCI_GETTEXTRANGEFULL 2039
 #define SCI_HIDESELECTION 2163
 #define SCI_POINTXFROMPOSITION 2164
 #define SCI_POINTYFROMPOSITION 2165
@@ -1267,11 +1268,21 @@
 	Sci_PositionCR cpMax;
 };
 
+struct Sci_CharacterRangeFull {
+	Sci_Position cpMin;
+	Sci_Position cpMax;
+};
+
 struct Sci_TextRange {
 	struct Sci_CharacterRange chrg;
 	char *lpstrText;
 };
 
+struct Sci_TextRangeFull {
+	struct Sci_CharacterRangeFull chrg;
+	char *lpstrText;
+};
+
 struct Sci_TextToFind {
 	struct Sci_CharacterRange chrg;
 	const char *lpstrText;
diff -r 338832737372 include/Scintilla.iface
--- a/include/Scintilla.iface	Sun May 01 14:31:17 2022 +1000
+++ b/include/Scintilla.iface	Sat May 07 12:25:17 2022 +1000
@@ -1255,6 +1255,10 @@
 # Return the length of the text.
 fun position GetTextRange=2162(, textrange tr)
 
+# Retrieve a range of text that can be past 2GB.
+# Return the length of the text.
+fun position GetTextRangeFull=2039(, textrangefull tr)
+
 # Draw the selection either highlighted or in normal (non-highlighted) style.
 fun void HideSelection=2163(bool hide,)
 
diff -r 338832737372 include/ScintillaCall.h
--- a/include/ScintillaCall.h	Sun May 01 14:31:17 2022 +1000
+++ b/include/ScintillaCall.h	Sat May 07 12:25:17 2022 +1000
@@ -68,6 +68,7 @@
 	char CharacterAt(Position position);
 	int UnsignedStyleAt(Position position);
 	std::string StringOfSpan(Span span);
+	std::string StringOfRange(Span span);
 	Position ReplaceTarget(std::string_view text);
 	Position ReplaceTargetRE(std::string_view text);
 	Position SearchInTarget(std::string_view text);
@@ -337,6 +338,7 @@
 	Position GetSelText(char *text);
 	std::string GetSelText();
 	Position GetTextRange(void *tr);
+	Position GetTextRangeFull(void *tr);
 	void HideSelection(bool hide);
 	int PointXFromPosition(Position pos);
 	int PointYFromPosition(Position pos);
diff -r 338832737372 include/ScintillaMessages.h
--- a/include/ScintillaMessages.h	Sun May 01 14:31:17 2022 +1000
+++ b/include/ScintillaMessages.h	Sat May 07 12:25:17 2022 +1000
@@ -271,6 +271,7 @@
 	SetSel = 2160,
 	GetSelText = 2161,
 	GetTextRange = 2162,
+	GetTextRangeFull = 2039,
 	HideSelection = 2163,
 	PointXFromPosition = 2164,
 	PointYFromPosition = 2165,
diff -r 338832737372 include/ScintillaStructures.h
--- a/include/ScintillaStructures.h	Sun May 01 14:31:17 2022 +1000
+++ b/include/ScintillaStructures.h	Sat May 07 12:25:17 2022 +1000
@@ -19,11 +19,21 @@
 	PositionCR cpMax;
 };
 
+struct CharacterRangeFull {
+	Position cpMin;
+	Position cpMax;
+};
+
 struct TextRange {
 	CharacterRange chrg;
 	char *lpstrText;
 };
 
+struct TextRangeFull {
+	CharacterRangeFull chrg;
+	char *lpstrText;
+};
+
 struct TextToFind {
 	CharacterRange chrg;
 	const char *lpstrText;
diff -r 338832737372 scripts/ScintillaAPIFacer.py
--- a/scripts/ScintillaAPIFacer.py	Sun May 01 14:31:17 2022 +1000
+++ b/scripts/ScintillaAPIFacer.py	Sat May 07 12:25:17 2022 +1000
@@ -28,6 +28,7 @@
 	"string": "const char *",
 	"stringresult": "char *",
 	"textrange": "void *",
+	"textrangefull": "void *",
 }
 
 basicTypes = [
diff -r 338832737372 src/Editor.cxx
--- a/src/Editor.cxx	Sun May 01 14:31:17 2022 +1000
+++ b/src/Editor.cxx	Sat May 07 12:25:17 2022 +1000
@@ -6258,6 +6258,22 @@
 			return len; 	// Not including NUL
 		}
 
+	case Message::GetTextRangeFull: {
+			if (lParam == 0)
+				return 0;
+			TextRangeFull *tr = static_cast<TextRangeFull *>(PtrFromSPtr(lParam));
+			Sci::Position cpMax = tr->chrg.cpMax;
+			if (cpMax == -1)
+				cpMax = pdoc->Length();
+			PLATFORM_ASSERT(cpMax <= pdoc->Length());
+			const Sci::Position len = cpMax - tr->chrg.cpMin; 	// No -1 as cpMin and cpMax are referring to inter character positions
+			PLATFORM_ASSERT(len >= 0);
+			pdoc->GetCharRange(tr->lpstrText, tr->chrg.cpMin, len);
+			// Spec says copied text is terminated with a NUL
+			tr->lpstrText[len] = '\0';
+			return len; 	// Not including NUL
+		}
+
 	case Message::HideSelection:
 		view.hideSelection = wParam != 0;
 		Redraw();
diff -r 338832737372 test/ScintillaCallable.py
--- a/test/ScintillaCallable.py	Sun May 01 14:31:17 2022 +1000
+++ b/test/ScintillaCallable.py	Sat May 07 12:25:17 2022 +1000
@@ -21,6 +21,13 @@
 		('lpstrText', ctypes.POINTER(ctypes.c_char)),
 	)
 
+class TEXTRANGEFULL(ctypes.Structure):
+	_fields_= (\
+		('cpMin', c_ssize_t),
+		('cpMax', c_ssize_t),
+		('lpstrText', ctypes.POINTER(ctypes.c_char)),
+	)
+
 class FINDTEXT(ctypes.Structure):
 	_fields_= (\
 		('cpMin', c_long),
@@ -136,6 +143,16 @@
 		text = tr.lpstrText[:length]
 		text += b"\0" * (length - len(text))
 		return text
+	def ByteRangeFull(self, start, end):
+		tr = TEXTRANGEFULL()
+		tr.cpMin = start
+		tr.cpMax = end
+		length = end - start
+		tr.lpstrText = ctypes.create_string_buffer(length + 1)
+		self.GetTextRangeFull(0, ctypes.byref(tr))
+		text = tr.lpstrText[:length]
+		text += b"\0" * (length - len(text))
+		return text
 	def StyledTextRange(self, start, end):
 		tr = TEXTRANGE()
 		tr.cpMin = start
diff -r 338832737372 test/simpleTests.py
--- a/test/simpleTests.py	Sun May 01 14:31:17 2022 +1000
+++ b/test/simpleTests.py	Sat May 07 12:25:17 2022 +1000
@@ -165,6 +165,17 @@
 		self.assertEquals(self.ed.Length, 4)
 		self.assertEquals(b"xxyy", self.ed.ByteRange(0,4))
 
+	def testTextRangeFull(self):
+		data = b"xy"
+		self.ed.InsertText(0, data)
+		self.assertEquals(self.ed.Length, 2)
+		self.assertEquals(data, self.ed.ByteRangeFull(0,2))
+
+		self.ed.InsertText(1, data)
+		# Should now be "xxyy"
+		self.assertEquals(self.ed.Length, 4)
+		self.assertEquals(b"xxyy", self.ed.ByteRangeFull(0,4))
+
 	def testInsertNul(self):
 		data = b"\0"
 		self.ed.AddText(1, data)
