diff -r b981a3675282 call/ScintillaCall.cxx
--- a/call/ScintillaCall.cxx	Fri May 13 09:04:05 2022 +1000
+++ b/call/ScintillaCall.cxx	Sat May 14 14:53:27 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());
 }
@@ -1127,10 +1139,18 @@
 	return CallPointer(Message::FindText, static_cast<uintptr_t>(searchFlags), ft);
 }
 
+Position ScintillaCall::FindTextFull(Scintilla::FindOption searchFlags, void *ft) {
+	return CallPointer(Message::FindTextFull, static_cast<uintptr_t>(searchFlags), ft);
+}
+
 Position ScintillaCall::FormatRange(bool draw, void *fr) {
 	return CallPointer(Message::FormatRange, draw, fr);
 }
 
+Position ScintillaCall::FormatRangeFull(bool draw, void *fr) {
+	return CallPointer(Message::FormatRangeFull, draw, fr);
+}
+
 Line ScintillaCall::FirstVisibleLine() {
 	return Call(Message::GetFirstVisibleLine);
 }
@@ -1187,6 +1207,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 b981a3675282 doc/ScintillaDoc.html
--- a/doc/ScintillaDoc.html	Fri May 13 09:04:05 2022 +1000
+++ b/doc/ScintillaDoc.html	Sat May 14 14:53:27 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_GETTEXTRANGEFULL">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 />
@@ -1033,13 +1056,15 @@
     See the documentation of your C++ runtime for details on what is supported.</p>
 
     <code><a class="message" href="#SCI_FINDTEXT">SCI_FINDTEXT(int searchFlags, Sci_TextToFind *ft) &rarr; position</a><br />
+     <a class="message" href="#SCI_FINDTEXTFULL">SCI_FINDTEXTFULL(int searchFlags, Sci_TextToFindFull *ft) &rarr; position</a><br />
      <a class="message" href="#SCI_SEARCHANCHOR">SCI_SEARCHANCHOR</a><br />
      <a class="message" href="#SCI_SEARCHNEXT">SCI_SEARCHNEXT(int searchFlags, const char *text) &rarr; position</a><br />
      <a class="message" href="#SCI_SEARCHPREV">SCI_SEARCHPREV(int searchFlags, const char *text) &rarr; position</a><br />
     </code>
 
     <p><b id="SCI_FINDTEXT">SCI_FINDTEXT(int searchFlags, <a class="jump" href="#Sci_TextToFind">Sci_TextToFind</a> *ft) &rarr; position</b><br />
-     This message searches for text in the document. It does not use or move the current selection.
+     <b id="SCI_FINDTEXT">SCI_FINDTEXTFULL(int searchFlags, <a class="jump" href="#Sci_TextToFindFull">Sci_TextToFindFull</a> *ft) &rarr; position</b><br />
+     These messages search for text in the document. They do not use or move the current selection.
     The <a class="jump" href="#searchFlags"><code class="parameter">searchFlags</code></a> argument controls the
     search type, which includes regular expression searches.</p>
 
@@ -1047,13 +1072,14 @@
     search backwards to find the previous occurrence of a search string by setting the end of the
     search range before the start.</p>
 
-    <p>The <code>Sci_TextToFind</code> structure is defined in <code>Scintilla.h</code>; set
+    <p>The <code>Sci_TextToFind</code> and <code>Sci_TextToFindFull</code> structures are defined in <code>Scintilla.h</code>; set
     <code>chrg.cpMin</code> and <code>chrg.cpMax</code> with the range of positions in the document
     to search. You can search backwards by
     setting <code>chrg.cpMax</code> less than <code>chrg.cpMin</code>.
     Set the <code>lpstrText</code> member of <code>Sci_TextToFind</code> to point at a zero terminated
     text string holding the search pattern. If your language makes the use of <code>Sci_TextToFind</code>
-    difficult, you should consider using <code>SCI_SEARCHINTARGET</code> instead.</p>
+    difficult, you should consider using <code>SCI_SEARCHINTARGET</code> instead.
+    On 64-bit Win32, <code>SCI_FINDTEXT</code> is limited to the first 2G of text and <code>SCI_FINDTEXTFULL</code> removes this limitation.</p>
 
     <p>The return value is -1 if the search fails or the position of the start of the found text if
     it succeeds. The <code>chrgText.cpMin</code> and <code>chrgText.cpMax</code> members of
@@ -1073,6 +1099,16 @@
 };
 </pre>
 
+    <p><b id="Sci_TextToFindFull">Sci_TextToFindFull</b><br />
+     This structure extends <code>Sci_TextToFind</code> to support huge documents on Win32.</p>
+<pre>
+struct Sci_TextToFindFull {
+    struct <a class="jump" href="#Sci_CharacterRangeFull">Sci_CharacterRangeFull</a> chrg;     // range to search
+    const char *lpstrText;                // the search pattern (zero terminated)
+    struct Sci_CharacterRangeFull chrgText; // returned as position of matching text
+};
+</pre>
+
     <p><b id="SCI_SEARCHANCHOR">SCI_SEARCHANCHOR</b><br />
      <b id="SCI_SEARCHNEXT">SCI_SEARCHNEXT(int searchFlags, const char *text) &rarr; position</b><br />
      <b id="SCI_SEARCHPREV">SCI_SEARCHPREV(int searchFlags, const char *text) &rarr; position</b><br />
@@ -6633,6 +6669,7 @@
     and on Cocoa <code>CGContextRef</code> is used.</p>
 
     <code><a class="message" href="#SCI_FORMATRANGE">SCI_FORMATRANGE(bool draw, Sci_RangeToFormat *fr) &rarr; position</a><br />
+     <a class="message" href="#SCI_FORMATRANGEFULL">SCI_FORMATRANGEFULL(bool draw, Sci_RangeToFormatFull *fr) &rarr; position</a><br />
      <a class="message" href="#SCI_SETPRINTMAGNIFICATION">SCI_SETPRINTMAGNIFICATION(int
     magnification)</a><br />
      <a class="message" href="#SCI_GETPRINTMAGNIFICATION">SCI_GETPRINTMAGNIFICATION &rarr; int</a><br />
@@ -6643,6 +6680,7 @@
     </code>
 
     <p><b id="SCI_FORMATRANGE">SCI_FORMATRANGE(bool draw, Sci_RangeToFormat *fr) &rarr; position</b><br />
+     <b id="SCI_FORMATRANGEFULL">SCI_FORMATRANGEFULL(bool draw, Sci_RangeToFormatFull *fr) &rarr; position</b><br />
      This call renders a range of text into a device context. If you use
     this for printing, you will probably want to arrange a page header and footer; Scintilla does
     not do this for you. See <code>SciTEWin::Print()</code> in <code>SciTEWinDlg.cxx</code> for an
@@ -6651,7 +6689,8 @@
 
     <p><code class="parameter">draw</code> controls if any output is done. Set this to false if you are paginating
     (for example, if you use this with MFC you will need to paginate in
-    <code>OnBeginPrinting()</code> before you output each page.</p>
+    <code>OnBeginPrinting()</code> before you output each page.
+    On 64-bit Win32, <code>SCI_FORMATRANGE</code> is limited to the first 2G of text and <code>SCI_FORMATRANGEFULL</code> removes this limitation.</p>
 <pre>
 struct Sci_Rectangle { int left; int top; int right; int bottom; };
 
@@ -6662,6 +6701,14 @@
     Sci_Rectangle rcPage;     // Physically printable page size
     Sci_CharacterRange chrg;  // Range of characters to print
 };
+
+struct Sci_RangeToFormatFull {
+    Sci_SurfaceID hdc;        // The Surface ID we print to
+    Sci_SurfaceID hdcTarget;  // The Surface ID we use for measuring (may be same as hdc)
+    Sci_Rectangle rc;         // Rectangle in which to print
+    Sci_Rectangle rcPage;     // Physically printable page size
+    Sci_CharacterRangeFull chrg;  // Range of characters to print
+};
 </pre>
 
     <p>On Windows, <code>hdc</code> and <code>hdcTarget</code> should both be set to the device context handle
diff -r b981a3675282 include/Scintilla.h
--- a/include/Scintilla.h	Fri May 13 09:04:05 2022 +1000
+++ b/include/Scintilla.h	Sat May 14 14:53:27 2022 +1000
@@ -474,7 +474,9 @@
 #define SCFIND_POSIX 0x00400000
 #define SCFIND_CXX11REGEX 0x00800000
 #define SCI_FINDTEXT 2150
+#define SCI_FINDTEXTFULL 2196
 #define SCI_FORMATRANGE 2151
+#define SCI_FORMATRANGEFULL 2777
 #define SCI_GETFIRSTVISIBLELINE 2152
 #define SCI_GETLINE 2153
 #define SCI_GETLINECOUNT 2154
@@ -487,6 +489,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,17 +1270,33 @@
 	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;
 	struct Sci_CharacterRange chrgText;
 };
 
+struct Sci_TextToFindFull {
+	struct Sci_CharacterRangeFull chrg;
+	const char *lpstrText;
+	struct Sci_CharacterRangeFull chrgText;
+};
+
 typedef void *Sci_SurfaceID;
 
 struct Sci_Rectangle {
@@ -1298,6 +1317,14 @@
 	struct Sci_CharacterRange chrg;
 };
 
+struct Sci_RangeToFormatFull {
+	Sci_SurfaceID hdc;
+	Sci_SurfaceID hdcTarget;
+	struct Sci_Rectangle rc;
+	struct Sci_Rectangle rcPage;
+	struct Sci_CharacterRangeFull chrg;
+};
+
 #ifndef __cplusplus
 /* For the GTK+ platform, g-ir-scanner needs to have these typedefs. This
  * is not required in C++ code and actually seems to break ScintillaEditPy */
diff -r b981a3675282 include/Scintilla.iface
--- a/include/Scintilla.iface	Fri May 13 09:04:05 2022 +1000
+++ b/include/Scintilla.iface	Sat May 14 14:53:27 2022 +1000
@@ -60,9 +60,12 @@
 ##     cells -> pointer to array of cells, each cell containing a style byte and character byte
 ##     pointer -> void* pointer that may point to a document, loader, internal text storage or similar
 ##     textrange -> range of a min and a max position with an output string
+##     textrangefull -> range of a min and a max position with an output string - supports 64-bit
 ##     findtext -> searchrange, text -> foundposition
+##     findtextfull -> searchrange, text -> foundposition
 ##     keymod -> integer containing key in low half and modifiers in high half
 ##     formatrange
+##     formatrangefull
 ## Enumeration types always start with a capital letter
 ## Types no longer used:
 ##     findtextex -> searchrange
@@ -1212,9 +1215,15 @@
 # Find some text in the document.
 fun position FindText=2150(FindOption searchFlags, findtext ft)
 
-# On Windows, will draw the document into a display context such as a printer.
+# Find some text in the document.
+fun position FindTextFull=2196(FindOption searchFlags, findtextfull ft)
+
+# Draw the document into a display context such as a printer.
 fun position FormatRange=2151(bool draw, formatrange fr)
 
+# Draw the document into a display context such as a printer.
+fun position FormatRangeFull=2777(bool draw, formatrangefull fr)
+
 # Retrieve the display line at the top of the display.
 get line GetFirstVisibleLine=2152(,)
 
@@ -1255,6 +1264,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 b981a3675282 include/ScintillaCall.h
--- a/include/ScintillaCall.h	Fri May 13 09:04:05 2022 +1000
+++ b/include/ScintillaCall.h	Sat May 14 14:53:27 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);
@@ -322,7 +323,9 @@
 	void SetPrintColourMode(Scintilla::PrintOption mode);
 	Scintilla::PrintOption PrintColourMode();
 	Position FindText(Scintilla::FindOption searchFlags, void *ft);
+	Position FindTextFull(Scintilla::FindOption searchFlags, void *ft);
 	Position FormatRange(bool draw, void *fr);
+	Position FormatRangeFull(bool draw, void *fr);
 	Line FirstVisibleLine();
 	Position GetLine(Line line, char *text);
 	std::string GetLine(Line line);
@@ -337,6 +340,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 b981a3675282 include/ScintillaMessages.h
--- a/include/ScintillaMessages.h	Fri May 13 09:04:05 2022 +1000
+++ b/include/ScintillaMessages.h	Sat May 14 14:53:27 2022 +1000
@@ -258,7 +258,9 @@
 	SetPrintColourMode = 2148,
 	GetPrintColourMode = 2149,
 	FindText = 2150,
+	FindTextFull = 2196,
 	FormatRange = 2151,
+	FormatRangeFull = 2777,
 	GetFirstVisibleLine = 2152,
 	GetLine = 2153,
 	GetLineCount = 2154,
@@ -271,6 +273,7 @@
 	SetSel = 2160,
 	GetSelText = 2161,
 	GetTextRange = 2162,
+	GetTextRangeFull = 2039,
 	HideSelection = 2163,
 	PointXFromPosition = 2164,
 	PointYFromPosition = 2165,
diff -r b981a3675282 include/ScintillaStructures.h
--- a/include/ScintillaStructures.h	Fri May 13 09:04:05 2022 +1000
+++ b/include/ScintillaStructures.h	Sat May 14 14:53:27 2022 +1000
@@ -19,17 +19,33 @@
 	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;
 	CharacterRange chrgText;
 };
 
+struct TextToFindFull {
+	CharacterRangeFull chrg;
+	const char *lpstrText;
+	CharacterRangeFull chrgText;
+};
+
 using SurfaceID = void *;
 
 struct Rectangle {
@@ -49,6 +65,14 @@
 	CharacterRange chrg;
 };
 
+struct RangeToFormatFull {
+	SurfaceID hdc;
+	SurfaceID hdcTarget;
+	Rectangle rc;
+	Rectangle rcPage;
+	CharacterRangeFull chrg;
+};
+
 struct NotifyHeader {
 	/* Compatible with Windows NMHDR.
 	 * hwndFrom is really an environment specific window handle or pointer
diff -r b981a3675282 scripts/ScintillaAPIFacer.py
--- a/scripts/ScintillaAPIFacer.py	Fri May 13 09:04:05 2022 +1000
+++ b/scripts/ScintillaAPIFacer.py	Sat May 14 14:53:27 2022 +1000
@@ -19,7 +19,9 @@
 	"colour": "Colour",
 	"colouralpha": "ColourAlpha",
 	"findtext": "void *",
+	"findtextfull": "void *",
 	"formatrange": "void *",
+	"formatrangefull": "void *",
 	"int": "int",
 	"keymod": "int",
 	"line": "Line",
@@ -28,6 +30,7 @@
 	"string": "const char *",
 	"stringresult": "char *",
 	"textrange": "void *",
+	"textrangefull": "void *",
 }
 
 basicTypes = [
diff -r b981a3675282 src/EditView.cxx
--- a/src/EditView.cxx	Fri May 13 09:04:05 2022 +1000
+++ b/src/EditView.cxx	Sat May 14 14:53:27 2022 +1000
@@ -2668,7 +2668,7 @@
 	return ColourRGBA(std::min(r, 0xffu), std::min(g, 0xffu), std::min(b, 0xffu));
 }
 
-Sci::Position EditView::FormatRange(bool draw, const RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure,
+Sci::Position EditView::FormatRange(bool draw, CharacterRangeFull chrg, Rectangle rc, Surface *surface, Surface *surfaceMeasure,
 	const EditModel &model, const ViewStyle &vs) {
 	// Can't use measurements cached for screen
 	posCache->Clear();
@@ -2733,15 +2733,15 @@
 		vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars);	// Recalculate fixedColumnWidth
 	}
 
-	const Sci::Line linePrintStart = model.pdoc->SciLineFromPosition(pfr->chrg.cpMin);
-	Sci::Line linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1;
+	const Sci::Line linePrintStart = model.pdoc->SciLineFromPosition(chrg.cpMin);
+	Sci::Line linePrintLast = linePrintStart + (rc.bottom - rc.top) / vsPrint.lineHeight - 1;
 	if (linePrintLast < linePrintStart)
 		linePrintLast = linePrintStart;
-	const Sci::Line linePrintMax = model.pdoc->SciLineFromPosition(pfr->chrg.cpMax);
+	const Sci::Line linePrintMax = model.pdoc->SciLineFromPosition(chrg.cpMax);
 	if (linePrintLast > linePrintMax)
 		linePrintLast = linePrintMax;
 	//Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
-	//      linePrintStart, linePrintLast, linePrintMax, pfr->rc.top, pfr->rc.bottom, vsPrint.lineHeight,
+	//      linePrintStart, linePrintLast, linePrintMax, rc.top, rc.bottom, vsPrint.lineHeight,
 	//      surfaceMeasure->Height(vsPrint.styles[StyleLineNumber].font));
 	Sci::Position endPosPrint = model.pdoc->Length();
 	if (linePrintLast < model.pdoc->LinesTotal())
@@ -2750,18 +2750,18 @@
 	// Ensure we are styled to where we are formatting.
 	model.pdoc->EnsureStyledTo(endPosPrint);
 
-	const int xStart = vsPrint.fixedColumnWidth + pfr->rc.left;
-	int ypos = pfr->rc.top;
+	const int xStart = vsPrint.fixedColumnWidth + rc.left;
+	int ypos = rc.top;
 
 	Sci::Line lineDoc = linePrintStart;
 
-	Sci::Position nPrintPos = pfr->chrg.cpMin;
+	Sci::Position nPrintPos = chrg.cpMin;
 	int visibleLine = 0;
-	int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth;
+	int widthPrint = rc.right - rc.left - vsPrint.fixedColumnWidth;
 	if (printParameters.wrapState == Wrap::None)
 		widthPrint = LineLayout::wrapWidthInfinite;
 
-	while (lineDoc <= linePrintLast && ypos < pfr->rc.bottom) {
+	while (lineDoc <= linePrintLast && ypos < rc.bottom) {
 
 		// When printing, the hdc and hdcTarget may be the same, so
 		// changing the state of surfaceMeasure may change the underlying
@@ -2777,9 +2777,9 @@
 		ll.containsCaret = false;
 
 		PRectangle rcLine = PRectangle::FromInts(
-			pfr->rc.left,
+			rc.left,
 			ypos,
-			pfr->rc.right - 1,
+			rc.right - 1,
 			ypos + vsPrint.lineHeight);
 
 		// When document line is wrapped over multiple display lines, find where
@@ -2800,7 +2800,7 @@
 		}
 
 		if (draw && lineNumberWidth &&
-			(ypos + vsPrint.lineHeight <= pfr->rc.bottom) &&
+			(ypos + vsPrint.lineHeight <= rc.bottom) &&
 			(visibleLine >= 0)) {
 			const std::string number = std::to_string(lineDoc + 1) + lineNumberPrintSpace;
 			PRectangle rcNumber = rcLine;
@@ -2819,7 +2819,7 @@
 		surface->FlushCachedState();
 
 		for (int iwl = 0; iwl < ll.lines; iwl++) {
-			if (ypos + vsPrint.lineHeight <= pfr->rc.bottom) {
+			if (ypos + vsPrint.lineHeight <= rc.bottom) {
 				if (visibleLine >= 0) {
 					if (draw) {
 						rcLine.top = static_cast<XYPOSITION>(ypos);
diff -r b981a3675282 src/EditView.h
--- a/src/EditView.h	Fri May 13 09:04:05 2022 +1000
+++ b/src/EditView.h	Sat May 14 14:53:27 2022 +1000
@@ -160,7 +160,7 @@
 		const ViewStyle &vsDraw);
 	void FillLineRemainder(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
 		Sci::Line line, PRectangle rcArea, int subLine) const;
-	Sci::Position FormatRange(bool draw, const Scintilla::RangeToFormat *pfr, Surface *surface, Surface *surfaceMeasure,
+	Sci::Position FormatRange(bool draw, CharacterRangeFull chrg, Rectangle rc, Surface *surface, Surface *surfaceMeasure,
 		const EditModel &model, const ViewStyle &vs);
 };
 
diff -r b981a3675282 src/Editor.cxx
--- a/src/Editor.cxx	Fri May 13 09:04:05 2022 +1000
+++ b/src/Editor.cxx	Sat May 14 14:53:27 2022 +1000
@@ -1834,18 +1834,30 @@
 // This is mostly copied from the Paint method but with some things omitted
 // such as the margin markers, line numbers, selection and caret
 // Should be merged back into a combined Draw method.
-Sci::Position Editor::FormatRange(bool draw, const RangeToFormat *pfr) {
-	if (!pfr)
+Sci::Position Editor::FormatRange(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam) {
+	if (!lParam)
 		return 0;
-
-	AutoSurface surface(pfr->hdc, this, Technology::Default);
-	if (!surface)
-		return 0;
-	AutoSurface surfaceMeasure(pfr->hdcTarget, this, Technology::Default);
-	if (!surfaceMeasure) {
-		return 0;
-	}
-	return view.FormatRange(draw, pfr, surface, surfaceMeasure, *this, vs);
+	const bool draw = wParam != 0;
+	void *ptr = PtrFromSPtr(lParam);
+	if (iMessage == Message::FormatRange) {
+		RangeToFormat *pfr = static_cast<RangeToFormat *>(ptr);
+		CharacterRangeFull chrg{ pfr->chrg.cpMin,pfr->chrg.cpMax };
+		AutoSurface surface(pfr->hdc, this, Technology::Default);
+		AutoSurface surfaceMeasure(pfr->hdcTarget, this, Technology::Default);
+		if (!surface || !surfaceMeasure) {
+			return 0;
+		}
+		return view.FormatRange(draw, chrg, pfr->rc, surface, surfaceMeasure, *this, vs);
+	} else {
+		// FormatRangeFull
+		RangeToFormatFull *pfr = static_cast<RangeToFormatFull *>(ptr);
+		AutoSurface surface(pfr->hdc, this, Technology::Default);
+		AutoSurface surfaceMeasure(pfr->hdcTarget, this, Technology::Default);
+		if (!surface || !surfaceMeasure) {
+			return 0;
+		}
+		return view.FormatRange(draw, pfr->chrg, pfr->rc, surface, surfaceMeasure, *this, vs);
+	}
 }
 
 long Editor::TextWidth(uptr_t style, const char *text) {
@@ -4121,6 +4133,37 @@
 }
 
 /**
+ * Search of a text in the document, in the given range.
+ * @return The position of the found text, -1 if not found.
+ */
+Sci::Position Editor::FindTextFull(
+    uptr_t wParam,		///< Search modes : @c FindOption::MatchCase, @c FindOption::WholeWord,
+    ///< @c FindOption::WordStart, @c FindOption::RegExp or @c FindOption::Posix.
+    sptr_t lParam) {	///< @c Sci_TextToFindFull structure: The text to search for in the given range.
+
+	TextToFindFull *ft = static_cast<TextToFindFull *>(PtrFromSPtr(lParam));
+	Sci::Position lengthFound = strlen(ft->lpstrText);
+	if (!pdoc->HasCaseFolder())
+		pdoc->SetCaseFolder(CaseFolderForEncoding());
+	try {
+		const Sci::Position pos = pdoc->FindText(
+			static_cast<Sci::Position>(ft->chrg.cpMin),
+			static_cast<Sci::Position>(ft->chrg.cpMax),
+			ft->lpstrText,
+			static_cast<FindOption>(wParam),
+			&lengthFound);
+		if (pos != -1) {
+			ft->chrgText.cpMin = static_cast<Sci_PositionCR>(pos);
+			ft->chrgText.cpMax = static_cast<Sci_PositionCR>(pos + lengthFound);
+		}
+		return pos;
+	} catch (RegexError &) {
+		errorStatus = Status::RegEx;
+		return -1;
+	}
+}
+
+/**
  * Relocatable search support : Searches relative to current selection
  * point and sets the selection to the found text range with
  * each search.
@@ -6244,6 +6287,9 @@
 	case Message::FindText:
 		return FindText(wParam, lParam);
 
+	case Message::FindTextFull:
+		return FindTextFull(wParam, lParam);
+
 	case Message::GetTextRange: {
 			if (lParam == 0)
 				return 0;
@@ -6259,13 +6305,30 @@
 			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();
 		break;
 
 	case Message::FormatRange:
-		return FormatRange(wParam != 0, static_cast<RangeToFormat *>(PtrFromSPtr(lParam)));
+	case Message::FormatRangeFull:
+		return FormatRange(iMessage, wParam, lParam);
 
 	case Message::GetMarginLeft:
 		return vs.leftMarginWidth;
diff -r b981a3675282 src/Editor.h
--- a/src/Editor.h	Fri May 13 09:04:05 2022 +1000
+++ b/src/Editor.h	Sat May 14 14:53:27 2022 +1000
@@ -406,7 +406,7 @@
 	void PaintSelMargin(Surface *surfaceWindow, const PRectangle &rc);
 	void RefreshPixMaps(Surface *surfaceWindow);
 	void Paint(Surface *surfaceWindow, PRectangle rcArea);
-	Sci::Position FormatRange(bool draw, const Scintilla::RangeToFormat *pfr);
+	Sci::Position FormatRange(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam);
 	long TextWidth(Scintilla::uptr_t style, const char *text);
 
 	virtual void SetVerticalScrollPos() = 0;
@@ -503,6 +503,7 @@
 
 	virtual std::unique_ptr<CaseFolder> CaseFolderForEncoding();
 	Sci::Position FindText(Scintilla::uptr_t wParam, Scintilla::sptr_t lParam);
+	Sci::Position FindTextFull(Scintilla::uptr_t wParam, Scintilla::sptr_t lParam);
 	void SearchAnchor();
 	Sci::Position SearchText(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam);
 	Sci::Position SearchInTarget(const char *text, Sci::Position length);
diff -r b981a3675282 test/ScintillaCallable.py
--- a/test/ScintillaCallable.py	Fri May 13 09:04:05 2022 +1000
+++ b/test/ScintillaCallable.py	Sat May 14 14:53:27 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),
@@ -30,6 +37,15 @@
 		('cpMaxText', c_long),
 	)
 
+class FINDTEXTFULL(ctypes.Structure):
+	_fields_= (\
+		('cpMin', c_ssize_t),
+		('cpMax', c_ssize_t),
+		('lpstrText', c_char_p),
+		('cpMinText', c_ssize_t),
+		('cpMaxText', c_ssize_t),
+	)
+
 class SciCall:
 	def __init__(self, fn, ptr, msg, stringResult=False):
 		self._fn = fn
@@ -136,6 +152,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
@@ -156,6 +182,16 @@
 		pos = self.FindText(flags, ctypes.byref(ft))
 		#~ print(start, end, ft.cpMinText, ft.cpMaxText)
 		return pos
+	def FindBytesFull(self, start, end, s, flags):
+		ft = FINDTEXTFULL()
+		ft.cpMin = start
+		ft.cpMax = end
+		ft.lpstrText = s
+		ft.cpMinText = 0
+		ft.cpMaxText = 0
+		pos = self.FindTextFull(flags, ctypes.byref(ft))
+		#~ print(start, end, ft.cpMinText, ft.cpMaxText)
+		return pos
 
 	def Contents(self):
 		return self.ByteRange(0, self.Length)
diff -r b981a3675282 test/simpleTests.py
--- a/test/simpleTests.py	Fri May 13 09:04:05 2022 +1000
+++ b/test/simpleTests.py	Sat May 14 14:53:27 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)
@@ -1187,6 +1198,12 @@
 		pos = self.ed.FindBytes(0, self.ed.Length, b"big", 0)
 		self.assertEquals(pos, 2)
 
+	def testFindFull(self):
+		pos = self.ed.FindBytesFull(0, self.ed.Length, b"zzz", 0)
+		self.assertEquals(pos, -1)
+		pos = self.ed.FindBytesFull(0, self.ed.Length, b"big", 0)
+		self.assertEquals(pos, 2)
+
 	def testFindEmpty(self):
 		pos = self.ed.FindBytes(0, self.ed.Length, b"", 0)
 		self.assertEquals(pos, 0)
