diff options
author | Neil <nyamatongwe@gmail.com> | 2022-05-17 08:52:34 +1000 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2022-05-17 08:52:34 +1000 |
commit | 475450c76ceef43a7f5b2c68ed5848baee96b6dc (patch) | |
tree | 110ed93d9989eb049ecb0ee2c6fc62692adcefa0 | |
parent | e107ecdf3f5576e90dc90c69fc57f24d1f499b61 (diff) | |
download | scintilla-mirror-475450c76ceef43a7f5b2c68ed5848baee96b6dc.tar.gz |
Duplicate APIs to support 64-bit document positions on Win32:
SCI_GETTEXTRANGEFULL, SCI_FINDTEXTFULL, and SCI_FORMATRANGEFULL.
-rw-r--r-- | call/ScintillaCall.cxx | 24 | ||||
-rw-r--r-- | doc/ScintillaDoc.html | 63 | ||||
-rw-r--r-- | doc/ScintillaHistory.html | 6 | ||||
-rw-r--r-- | include/Scintilla.h | 27 | ||||
-rw-r--r-- | include/Scintilla.iface | 15 | ||||
-rw-r--r-- | include/ScintillaCall.h | 4 | ||||
-rw-r--r-- | include/ScintillaMessages.h | 3 | ||||
-rw-r--r-- | include/ScintillaStructures.h | 24 | ||||
-rw-r--r-- | scripts/ScintillaAPIFacer.py | 3 | ||||
-rw-r--r-- | src/EditView.cxx | 28 | ||||
-rw-r--r-- | src/EditView.h | 2 | ||||
-rw-r--r-- | src/Editor.cxx | 85 | ||||
-rw-r--r-- | src/Editor.h | 3 | ||||
-rw-r--r-- | test/ScintillaCallable.py | 36 | ||||
-rw-r--r-- | test/simpleTests.py | 17 |
15 files changed, 304 insertions, 36 deletions
diff --git a/call/ScintillaCall.cxx b/call/ScintillaCall.cxx index cb0d09365..20fb452da 100644 --- a/call/ScintillaCall.cxx +++ b/call/ScintillaCall.cxx @@ -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::StringOfSpan(Span span) { } } +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 @@ Position ScintillaCall::FindText(Scintilla::FindOption searchFlags, void *ft) { 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 @@ Position ScintillaCall::GetTextRange(void *tr) { 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 --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html index 782f299eb..ea85686aa 100644 --- a/doc/ScintillaDoc.html +++ b/doc/ScintillaDoc.html @@ -129,7 +129,7 @@ <h1>Scintilla Documentation</h1> - <p>Last edited 9 March 2022 NH</p> + <p>Last edited 15 May 2022 NH</p> <p style="background:#90F0C0">Scintilla 5 has moved the lexers from Scintilla into a new <a href="Lexilla.html">Lexilla</a> project.<br /> @@ -531,6 +531,7 @@ <a class="message" href="#SCI_SETREADONLY">SCI_SETREADONLY(bool readOnly)</a><br /> <a class="message" href="#SCI_GETREADONLY">SCI_GETREADONLY → bool</a><br /> <a class="message" href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE(<unused>, Sci_TextRange *tr) → position</a><br /> + <a class="message" href="#SCI_GETTEXTRANGEFULL">SCI_GETTEXTRANGEFULL(<unused>, Sci_TextRangeFull *tr) → 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(<unused>, <a class="jump" href="#Sci_TextRange">Sci_TextRange</a> *tr) → position</b><br /> + <p> + <b id="SCI_GETTEXTRANGE">SCI_GETTEXTRANGE(<unused>, <a class="jump" href="#Sci_TextRange">Sci_TextRange</a> *tr) → position</b><br /> + <b id="SCI_GETTEXTRANGEFULL">SCI_GETTEXTRANGEFULL(<unused>, <a class="jump" href="#Sci_TextRangeFull">Sci_TextRangeFull</a> *tr) → 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 @@ struct Sci_TextRange { }; </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(<unused>, char *s) → position</b><br /> @@ -1033,13 +1056,15 @@ struct Sci_TextRange { 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) → position</a><br /> + <a class="message" href="#SCI_FINDTEXTFULL">SCI_FINDTEXTFULL(int searchFlags, Sci_TextToFindFull *ft) → 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) → position</a><br /> <a class="message" href="#SCI_SEARCHPREV">SCI_SEARCHPREV(int searchFlags, const char *text) → position</a><br /> </code> <p><b id="SCI_FINDTEXT">SCI_FINDTEXT(int searchFlags, <a class="jump" href="#Sci_TextToFind">Sci_TextToFind</a> *ft) → 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) → 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 @@ struct Sci_TextRange { 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 @@ struct Sci_TextToFind { }; </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) → position</b><br /> <b id="SCI_SEARCHPREV">SCI_SEARCHPREV(int searchFlags, const char *text) → position</b><br /> @@ -6633,6 +6669,7 @@ struct Sci_TextToFind { and on Cocoa <code>CGContextRef</code> is used.</p> <code><a class="message" href="#SCI_FORMATRANGE">SCI_FORMATRANGE(bool draw, Sci_RangeToFormat *fr) → position</a><br /> + <a class="message" href="#SCI_FORMATRANGEFULL">SCI_FORMATRANGEFULL(bool draw, Sci_RangeToFormatFull *fr) → position</a><br /> <a class="message" href="#SCI_SETPRINTMAGNIFICATION">SCI_SETPRINTMAGNIFICATION(int magnification)</a><br /> <a class="message" href="#SCI_GETPRINTMAGNIFICATION">SCI_GETPRINTMAGNIFICATION → int</a><br /> @@ -6643,6 +6680,7 @@ struct Sci_TextToFind { </code> <p><b id="SCI_FORMATRANGE">SCI_FORMATRANGE(bool draw, Sci_RangeToFormat *fr) → position</b><br /> + <b id="SCI_FORMATRANGEFULL">SCI_FORMATRANGEFULL(bool draw, Sci_RangeToFormatFull *fr) → 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 @@ struct Sci_TextToFind { <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 @@ struct Sci_RangeToFormat { 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 --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 772fea3d8..e1db2d4ec 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -581,6 +581,12 @@ Released 31 March 2022. </li> <li> + Duplicate APIs to support 64-bit document positions on Win32: + SCI_GETTEXTRANGEFULL, SCI_FINDTEXTFULL, and SCI_FORMATRANGEFULL. + This adds new types to Scintilla.iface which may impact downstream projects. + Applications should move to these APIs from their predecessors as they will be deprecated. + </li> + <li> Improve performance of SCI_FOLDALL(SC_FOLDACTION_EXPAND) by not lexing whole document as it does not depend on folding structure. </li> diff --git a/include/Scintilla.h b/include/Scintilla.h index 14f788eae..0a5c46933 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -474,7 +474,9 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP #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 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP #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 @@ struct Sci_CharacterRange { 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_RangeToFormat { 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 --git a/include/Scintilla.iface b/include/Scintilla.iface index 7c20e9144..be3d78692 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -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 @@ ali SCFIND_CXX11REGEX=CXX11_REG_EX # 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 @@ fun position GetSelText=2161(, stringresult text) # 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 --git a/include/ScintillaCall.h b/include/ScintillaCall.h index 83e62d6da..40cf1e576 100644 --- a/include/ScintillaCall.h +++ b/include/ScintillaCall.h @@ -68,6 +68,7 @@ public: 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 @@ public: 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 @@ public: 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 --git a/include/ScintillaMessages.h b/include/ScintillaMessages.h index d7bec7f75..3b2927472 100644 --- a/include/ScintillaMessages.h +++ b/include/ScintillaMessages.h @@ -258,7 +258,9 @@ enum class Message { SetPrintColourMode = 2148, GetPrintColourMode = 2149, FindText = 2150, + FindTextFull = 2196, FormatRange = 2151, + FormatRangeFull = 2777, GetFirstVisibleLine = 2152, GetLine = 2153, GetLineCount = 2154, @@ -271,6 +273,7 @@ enum class Message { SetSel = 2160, GetSelText = 2161, GetTextRange = 2162, + GetTextRangeFull = 2039, HideSelection = 2163, PointXFromPosition = 2164, PointYFromPosition = 2165, diff --git a/include/ScintillaStructures.h b/include/ScintillaStructures.h index 6bd16e8c1..a3418173f 100644 --- a/include/ScintillaStructures.h +++ b/include/ScintillaStructures.h @@ -19,17 +19,33 @@ struct CharacterRange { 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 @@ struct RangeToFormat { 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 --git a/scripts/ScintillaAPIFacer.py b/scripts/ScintillaAPIFacer.py index 9fe5f56ce..e30f48380 100644 --- a/scripts/ScintillaAPIFacer.py +++ b/scripts/ScintillaAPIFacer.py @@ -19,7 +19,9 @@ typeAliases = { "colour": "Colour", "colouralpha": "ColourAlpha", "findtext": "void *", + "findtextfull": "void *", "formatrange": "void *", + "formatrangefull": "void *", "int": "int", "keymod": "int", "line": "Line", @@ -28,6 +30,7 @@ typeAliases = { "string": "const char *", "stringresult": "char *", "textrange": "void *", + "textrangefull": "void *", } basicTypes = [ diff --git a/src/EditView.cxx b/src/EditView.cxx index d4ab63948..2ba450ab3 100644 --- a/src/EditView.cxx +++ b/src/EditView.cxx @@ -2668,7 +2668,7 @@ static ColourRGBA InvertedLight(ColourRGBA orig) noexcept { 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 @@ Sci::Position EditView::FormatRange(bool draw, const RangeToFormat *pfr, Surface 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 @@ Sci::Position EditView::FormatRange(bool draw, const RangeToFormat *pfr, Surface // 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 @@ Sci::Position EditView::FormatRange(bool draw, const RangeToFormat *pfr, Surface 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 @@ Sci::Position EditView::FormatRange(bool draw, const RangeToFormat *pfr, Surface } 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 @@ Sci::Position EditView::FormatRange(bool draw, const RangeToFormat *pfr, Surface 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 --git a/src/EditView.h b/src/EditView.h index 199a174b9..d65bf0736 100644 --- a/src/EditView.h +++ b/src/EditView.h @@ -160,7 +160,7 @@ public: 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 --git a/src/Editor.cxx b/src/Editor.cxx index 6ec2dea3e..f99914ebd 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -1834,18 +1834,30 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { // 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) - return 0; - - AutoSurface surface(pfr->hdc, this, Technology::Default); - if (!surface) - return 0; - AutoSurface surfaceMeasure(pfr->hdcTarget, this, Technology::Default); - if (!surfaceMeasure) { +Sci::Position Editor::FormatRange(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam) { + if (!lParam) return 0; + 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); } - return view.FormatRange(draw, pfr, surface, surfaceMeasure, *this, vs); } long Editor::TextWidth(uptr_t style, const char *text) { @@ -4121,6 +4133,37 @@ Sci::Position Editor::FindText( } /** + * 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 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { 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 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { 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 --git a/src/Editor.h b/src/Editor.h index 095131c76..a6364be4d 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -406,7 +406,7 @@ protected: // ScintillaBase subclass needs access to much of Editor 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 @@ protected: // ScintillaBase subclass needs access to much of Editor 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 --git a/test/ScintillaCallable.py b/test/ScintillaCallable.py index 1164631ae..d8d16c7e3 100644 --- a/test/ScintillaCallable.py +++ b/test/ScintillaCallable.py @@ -21,6 +21,13 @@ class TEXTRANGE(ctypes.Structure): ('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 @@ class FINDTEXT(ctypes.Structure): ('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 @@ class ScintillaCallable: 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 @@ class ScintillaCallable: 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 --git a/test/simpleTests.py b/test/simpleTests.py index 7b326f8e0..195479eaa 100644 --- a/test/simpleTests.py +++ b/test/simpleTests.py @@ -165,6 +165,17 @@ class TestSimple(unittest.TestCase): 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 @@ class TestSearch(unittest.TestCase): 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) |