From e9280bf01239e81b01899992647766d0c073253b Mon Sep 17 00:00:00 2001 From: Neil Date: Wed, 19 Oct 2022 13:36:08 +1100 Subject: Feature [feature-requests:#1455] Implement GetStyledTextFull as a 64-bit safe version of GetStyledText. --- call/ScintillaCall.cxx | 4 ++++ doc/ScintillaDoc.html | 9 +++++++-- doc/ScintillaHistory.html | 5 +++++ include/Scintilla.h | 1 + include/Scintilla.iface | 4 ++++ include/ScintillaCall.h | 1 + include/ScintillaMessages.h | 1 + scripts/HFacer.py | 27 +++++++++++++++------------ src/Editor.cxx | 33 +++++++++++++++++++++------------ src/Editor.h | 1 + test/ScintillaCallable.py | 10 ++++++++++ test/simpleTests.py | 9 +++++++++ 12 files changed, 79 insertions(+), 26 deletions(-) diff --git a/call/ScintillaCall.cxx b/call/ScintillaCall.cxx index 434e3fdf0..816f25eb9 100644 --- a/call/ScintillaCall.cxx +++ b/call/ScintillaCall.cxx @@ -227,6 +227,10 @@ Position ScintillaCall::GetStyledText(void *tr) { return CallPointer(Message::GetStyledText, 0, tr); } +Position ScintillaCall::GetStyledTextFull(void *tr) { + return CallPointer(Message::GetStyledTextFull, 0, tr); +} + bool ScintillaCall::CanRedo() { return Call(Message::CanRedo); } diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html index fb5d59dfd..f9a973892 100644 --- a/doc/ScintillaDoc.html +++ b/doc/ScintillaDoc.html @@ -536,6 +536,7 @@ SCI_GETSTYLEAT(position pos) → int
SCI_GETSTYLEINDEXAT(position pos) → int
SCI_GETSTYLEDTEXT(<unused>, Sci_TextRange *tr) → position
+ SCI_GETSTYLEDTEXTFULL(<unused>, Sci_TextRangeFull *tr) → position
SCI_RELEASEALLEXTENDEDSTYLES
SCI_ALLOCATEEXTENDEDSTYLES(int numberStyles) → int
SCI_TARGETASUTF8(<unused>, char *s) → position
@@ -623,15 +624,19 @@ SCI_GETSTYLEDTEXT, SCI_GETTEXT

-

SCI_GETSTYLEDTEXT(<unused>, Sci_TextRange *tr) → position
+

+ SCI_GETSTYLEDTEXT(<unused>, Sci_TextRange *tr) → position
+ SCI_GETSTYLEDTEXTFULL(<unused>, Sci_TextRangeFull *tr) → position
This collects styled text into a buffer using two bytes for each cell, with the character at the lower address of each pair and the style byte at the upper address. Characters between the positions cpMin and cpMax are copied to lpstrText (see - struct Sci_TextRange in Scintilla.h). Two 0 bytes are added to the end of + struct Sci_TextRange and struct Sci_TextRangeFull in Scintilla.h). Two 0 bytes are added to the end of the text, so the buffer that lpstrText points at must be at least 2*(cpMax-cpMin)+2 bytes long. No check is made for sensible values of cpMin or cpMax. Positions outside the document return character codes and style bytes of 0.

+

SCI_GETSTYLEDTEXTFULL uses 64-bit positions on all platforms so is safe for documents larger than 2GB. + It should always be used in preference to SCI_GETSTYLEDTEXT which will be deprecated in a future release.

See also: SCI_GETSELTEXT, SCI_GETLINE, diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 5a44b84c5..b145692b5 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -587,6 +587,11 @@

  • Draw background colour for EOL annotations with standard and boxed visuals.
  • +
  • + Add SCI_GETSTYLEDTEXTFULL to support 64-bit document positions on Win32 replacing + SCI_GETSTYLEDTEXT which is not safe for huge documents. + Feature #1455. +
  • Release 5.3.1 diff --git a/include/Scintilla.h b/include/Scintilla.h index 03302e293..30760431f 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -63,6 +63,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP #define SCI_SELECTALL 2013 #define SCI_SETSAVEPOINT 2014 #define SCI_GETSTYLEDTEXT 2015 +#define SCI_GETSTYLEDTEXTFULL 2778 #define SCI_CANREDO 2016 #define SCI_MARKERLINEFROMHANDLE 2017 #define SCI_MARKERDELETEHANDLE 2018 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index b03b8c8ca..a527bb9a4 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -154,6 +154,10 @@ fun void SetSavePoint=2014(,) # Returns the number of bytes in the buffer not including terminating NULs. fun position GetStyledText=2015(, textrange tr) +# Retrieve a buffer of cells that can be past 2GB. +# Returns the number of bytes in the buffer not including terminating NULs. +fun position GetStyledTextFull=2778(, textrangefull tr) + # Are there any redoable actions in the undo history? fun bool CanRedo=2016(,) diff --git a/include/ScintillaCall.h b/include/ScintillaCall.h index 4b8e3c732..9f3b7e40a 100644 --- a/include/ScintillaCall.h +++ b/include/ScintillaCall.h @@ -95,6 +95,7 @@ public: void SelectAll(); void SetSavePoint(); Position GetStyledText(void *tr); + Position GetStyledTextFull(void *tr); bool CanRedo(); Line MarkerLineFromHandle(int markerHandle); void MarkerDeleteHandle(int markerHandle); diff --git a/include/ScintillaMessages.h b/include/ScintillaMessages.h index 118655689..9d3034f79 100644 --- a/include/ScintillaMessages.h +++ b/include/ScintillaMessages.h @@ -34,6 +34,7 @@ enum class Message { SelectAll = 2013, SetSavePoint = 2014, GetStyledText = 2015, + GetStyledTextFull = 2778, CanRedo = 2016, MarkerLineFromHandle = 2017, MarkerDeleteHandle = 2018, diff --git a/scripts/HFacer.py b/scripts/HFacer.py index cc8467b2c..0d3062f51 100755 --- a/scripts/HFacer.py +++ b/scripts/HFacer.py @@ -31,6 +31,8 @@ def printHFile(f): out.append("#endif") return out +showUnused = False + def RegenerateAll(root, showMaxID): f = Face.Face() f.ReadFromFile(root / "include/Scintilla.iface") @@ -39,18 +41,19 @@ def RegenerateAll(root, showMaxID): valueSet = set(int(x) for x in f.values if int(x) < 3000) maximumID = max(valueSet) print("Maximum ID is %d" % maximumID) - #~ valuesUnused = sorted(x for x in range(2001,maximumID) if x not in valueSet) - #~ print("\nUnused values") - #~ valueToName = {} - #~ for name, feature in f.features.items(): - #~ try: - #~ value = int(feature["Value"]) - #~ valueToName[value] = name - #~ except ValueError: - #~ pass - #~ for v in valuesUnused: - #~ prev = valueToName.get(v-1, "") - #~ print(v, prev) + if showUnused: + valuesUnused = sorted(x for x in range(2001,maximumID) if x not in valueSet) + print("\nUnused values") + valueToName = {} + for name, feature in f.features.items(): + try: + value = int(feature["Value"]) + valueToName[value] = name + except ValueError: + pass + for v in valuesUnused: + prev = valueToName.get(v-1, "") + print(v, prev) if __name__ == "__main__": RegenerateAll(pathlib.Path(__file__).resolve().parent.parent, True) diff --git a/src/Editor.cxx b/src/Editor.cxx index 35148299e..da52d462c 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -5783,6 +5783,17 @@ void Editor::AddStyledText(const char *buffer, Sci::Position appendLength) { SetEmptySelection(sel.MainCaret() + lengthInserted); } +Sci::Position Editor::GetStyledText(char *buffer, Sci::Position cpMin, Sci::Position cpMax) const noexcept { + Sci::Position iPlace = 0; + for (Sci::Position iChar = cpMin; iChar < cpMax; iChar++) { + buffer[iPlace++] = pdoc->CharAt(iChar); + buffer[iPlace++] = pdoc->StyleAt(iChar); + } + buffer[iPlace] = '\0'; + buffer[iPlace + 1] = '\0'; + return iPlace; +} + bool Editor::ValidMargin(uptr_t wParam) const noexcept { return wParam < vs.ms.size(); } @@ -6588,19 +6599,17 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { pdoc->SetSavePoint(); break; - case Message::GetStyledText: { - if (lParam == 0) - return 0; - TextRange *tr = static_cast(PtrFromSPtr(lParam)); - Sci::Position iPlace = 0; - for (Sci::Position iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) { - tr->lpstrText[iPlace++] = pdoc->CharAt(iChar); - tr->lpstrText[iPlace++] = pdoc->StyleAt(iChar); - } - tr->lpstrText[iPlace] = '\0'; - tr->lpstrText[iPlace + 1] = '\0'; - return iPlace; + case Message::GetStyledText: + if (TextRange *tr = static_cast(PtrFromSPtr(lParam))) { + return GetStyledText(tr->lpstrText, tr->chrg.cpMin, tr->chrg.cpMax); } + return 0; + + case Message::GetStyledTextFull: + if (TextRangeFull *tr = static_cast(PtrFromSPtr(lParam))) { + return GetStyledText(tr->lpstrText, tr->chrg.cpMin, tr->chrg.cpMax); + } + return 0; case Message::CanRedo: return (pdoc->CanRedo() && !pdoc->IsReadOnly()) ? 1 : 0; diff --git a/src/Editor.h b/src/Editor.h index 297590f47..140e15a9c 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -598,6 +598,7 @@ protected: // ScintillaBase subclass needs access to much of Editor Sci::Line WrapCount(Sci::Line line); void AddStyledText(const char *buffer, Sci::Position appendLength); + Sci::Position GetStyledText(char *buffer, Sci::Position cpMin, Sci::Position cpMax) const noexcept; virtual Scintilla::sptr_t DefWndProc(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam) = 0; bool ValidMargin(Scintilla::uptr_t wParam) const noexcept; diff --git a/test/ScintillaCallable.py b/test/ScintillaCallable.py index d8d16c7e3..126281aac 100644 --- a/test/ScintillaCallable.py +++ b/test/ScintillaCallable.py @@ -172,6 +172,16 @@ class ScintillaCallable: styledText = tr.lpstrText[:length] styledText += b"\0" * (length - len(styledText)) return styledText + def StyledTextRangeFull(self, start, end): + tr = TEXTRANGEFULL() + tr.cpMin = start + tr.cpMax = end + length = 2 * (end - start) + tr.lpstrText = ctypes.create_string_buffer(length + 2) + self.GetStyledTextFull(0, ctypes.byref(tr)) + styledText = tr.lpstrText[:length] + styledText += b"\0" * (length - len(styledText)) + return styledText def FindBytes(self, start, end, s, flags): ft = FINDTEXT() ft.cpMin = start diff --git a/test/simpleTests.py b/test/simpleTests.py index 92d6a92a7..2b5d3bc0e 100644 --- a/test/simpleTests.py +++ b/test/simpleTests.py @@ -62,6 +62,15 @@ class TestSimple(unittest.TestCase): self.assertEquals(self.ed.GetStyleAt(0), 0) self.assertEquals(self.ed.StyledTextRange(0, 1), b"x\0") + def testStyledTextRangeFull(self): + self.assertEquals(self.ed.EndStyled, 0) + self.ed.AddStyledText(4, b"x\002y\377") + self.assertEquals(self.ed.StyledTextRangeFull(0, 1), b"x\002") + self.assertEquals(self.ed.StyledTextRangeFull(1, 2), b"y\377") + self.ed.ClearDocumentStyle() + self.assertEquals(self.ed.Length, 2) + self.assertEquals(self.ed.StyledTextRangeFull(0, 1), b"x\0") + def testStyling(self): self.assertEquals(self.ed.EndStyled, 0) self.ed.AddStyledText(4, b"x\002y\003") -- cgit v1.2.3