diff options
author | Neil <nyamatongwe@gmail.com> | 2025-02-01 14:43:22 +1100 |
---|---|---|
committer | Neil <nyamatongwe@gmail.com> | 2025-02-01 14:43:22 +1100 |
commit | f54fd2019dd648b29a80ec7429833ab546d3a428 (patch) | |
tree | 231bebba7db25fccf798340bdd908f28fd504c26 | |
parent | db6332fa9933244c45c44063afbdcccb462cfc03 (diff) | |
download | scintilla-mirror-f54fd2019dd648b29a80ec7429833ab546d3a428.tar.gz |
Serialize selection type and ranges with SCI_GETSELECTIONSERIALIZED and
SCI_SETSELECTIONSERIALIZED.
-rw-r--r-- | call/ScintillaCall.cxx | 12 | ||||
-rw-r--r-- | doc/ScintillaDoc.html | 12 | ||||
-rw-r--r-- | doc/ScintillaHistory.html | 3 | ||||
-rw-r--r-- | include/Scintilla.h | 2 | ||||
-rw-r--r-- | include/Scintilla.iface | 6 | ||||
-rw-r--r-- | include/ScintillaCall.h | 3 | ||||
-rw-r--r-- | include/ScintillaMessages.h | 2 | ||||
-rw-r--r-- | src/Editor.cxx | 18 | ||||
-rw-r--r-- | src/Editor.h | 1 | ||||
-rw-r--r-- | src/Selection.cxx | 17 | ||||
-rw-r--r-- | src/Selection.h | 2 | ||||
-rw-r--r-- | test/simpleTests.py | 33 |
12 files changed, 110 insertions, 1 deletions
diff --git a/call/ScintillaCall.cxx b/call/ScintillaCall.cxx index 550adc710..57b050805 100644 --- a/call/ScintillaCall.cxx +++ b/call/ScintillaCall.cxx @@ -1267,6 +1267,18 @@ UndoSelectionHistoryOption ScintillaCall::UndoSelectionHistory() { return static_cast<Scintilla::UndoSelectionHistoryOption>(Call(Message::GetUndoSelectionHistory)); } +void ScintillaCall::SetSelectionSerialized(const char *selectionString) { + CallString(Message::SetSelectionSerialized, 0, selectionString); +} + +Position ScintillaCall::SelectionSerialized(char *selectionString) { + return CallPointer(Message::GetSelectionSerialized, 0, selectionString); +} + +std::string ScintillaCall::SelectionSerialized() { + return CallReturnString(Message::GetSelectionSerialized, 0); +} + Line ScintillaCall::FirstVisibleLine() { return Call(Message::GetFirstVisibleLine); } diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html index 886786484..dda900b7c 100644 --- a/doc/ScintillaDoc.html +++ b/doc/ScintillaDoc.html @@ -130,7 +130,7 @@ <h1>Scintilla Documentation</h1> - <p>Last edited 26 October 2024 NH</p> + <p>Last edited 1 February 2025 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 /> @@ -1239,6 +1239,10 @@ struct Sci_TextRangeFull { <a class="message" href="#SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE">SCI_GETRECTANGULARSELECTIONANCHORVIRTUALSPACE → position</a><br /> <br /> + <a class="message" href="#SCI_SETSELECTIONSERIALIZED">SCI_SETSELECTIONSERIALIZED(<unused>, const char *selectionString)</a><br /> + <a class="message" href="#SCI_GETSELECTIONSERIALIZED">SCI_GETSELECTIONSERIALIZED(<unused>, char *selectionString) → position</a><br /> + <br /> + <a class="element" href="#SC_ELEMENT_SELECTION_ADDITIONAL_TEXT">SC_ELEMENT_SELECTION_ADDITIONAL_TEXT : colouralpha</a><br /> <a class="element" href="#SC_ELEMENT_SELECTION_ADDITIONAL_BACK">SC_ELEMENT_SELECTION_ADDITIONAL_BACK : colouralpha</a><br /> <a class="discouraged message" href="#SCI_SETADDITIONALSELALPHA">SCI_SETADDITIONALSELALPHA(alpha alpha)</a><br /> @@ -1405,6 +1409,12 @@ struct Sci_TextRangeFull { After setting the rectangular selection, this is broken down into multiple selections, one for each line.</p> <p> + <b id="SCI_SETSELECTIONSERIALIZED">SCI_SETSELECTIONSERIALIZED(<unused>, const char *selectionString)</b><br /> + <b id="SCI_GETSELECTIONSERIALIZED">SCI_GETSELECTIONSERIALIZED(<unused>, char *selectionString) → position</b><br /> + Set or query the selection type and positions as a serialized string. + The format of this string may change in future versions so should not be persisted beyond the current session.</p> + + <p> <b id="SC_ELEMENT_SELECTION_ADDITIONAL_TEXT">SC_ELEMENT_SELECTION_ADDITIONAL_TEXT : colouralpha</b><br /> <b id="SC_ELEMENT_SELECTION_ADDITIONAL_BACK">SC_ELEMENT_SELECTION_ADDITIONAL_BACK : colouralpha</b><br /> <b id="SCI_SETADDITIONALSELALPHA">SCI_SETADDITIONALSELALPHA(<a class="jump" href="#alpha">alpha</a> alpha)</b><br /> diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 7cb5ebcee..782801b7a 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -601,6 +601,9 @@ <a href="https://sourceforge.net/p/scintilla/bugs/1224/">Bug #1224</a>. </li> <li> + Serialize selection type and ranges with SCI_GETSELECTIONSERIALIZED and SCI_SETSELECTIONSERIALIZED. + </li> + <li> Fix bug on Qt where double-click stopped working when Scintilla instance had been running for weeks. </li> </ul> diff --git a/include/Scintilla.h b/include/Scintilla.h index 736a7e2d5..4de92e1b8 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -536,6 +536,8 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP #define SC_UNDO_SELECTION_HISTORY_ENABLED 1 #define SCI_SETUNDOSELECTIONHISTORY 2782 #define SCI_GETUNDOSELECTIONHISTORY 2783 +#define SCI_SETSELECTIONSERIALIZED 2784 +#define SCI_GETSELECTIONSERIALIZED 2785 #define SCI_GETFIRSTVISIBLELINE 2152 #define SCI_GETLINE 2153 #define SCI_GETLINECOUNT 2154 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 65d3d157b..4ce9d5703 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -1344,6 +1344,12 @@ set void SetUndoSelectionHistory=2782(UndoSelectionHistoryOption undoSelectionHi # Report undo selection history status. get UndoSelectionHistoryOption GetUndoSelectionHistory=2783(,) +# Set selection from serialized form. +set void SetSelectionSerialized=2784(, string selectionString) + +# Retrieve serialized form of selection. +get position GetSelectionSerialized=2785(, stringresult selectionString) + # Retrieve the display line at the top of the display. get line GetFirstVisibleLine=2152(,) diff --git a/include/ScintillaCall.h b/include/ScintillaCall.h index bcd462be9..345d15612 100644 --- a/include/ScintillaCall.h +++ b/include/ScintillaCall.h @@ -362,6 +362,9 @@ public: Scintilla::ChangeHistoryOption ChangeHistory(); void SetUndoSelectionHistory(Scintilla::UndoSelectionHistoryOption undoSelectionHistory); Scintilla::UndoSelectionHistoryOption UndoSelectionHistory(); + void SetSelectionSerialized(const char *selectionString); + Position SelectionSerialized(char *selectionString); + std::string SelectionSerialized(); Line FirstVisibleLine(); Position GetLine(Line line, char *text); std::string GetLine(Line line); diff --git a/include/ScintillaMessages.h b/include/ScintillaMessages.h index f60be4d52..d7ec27c39 100644 --- a/include/ScintillaMessages.h +++ b/include/ScintillaMessages.h @@ -287,6 +287,8 @@ enum class Message { GetChangeHistory = 2781, SetUndoSelectionHistory = 2782, GetUndoSelectionHistory = 2783, + SetSelectionSerialized = 2784, + GetSelectionSerialized = 2785, GetFirstVisibleLine = 2152, GetLine = 2153, GetLineCount = 2154, diff --git a/src/Editor.cxx b/src/Editor.cxx index 10c694990..d85a4c294 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -711,6 +711,15 @@ void Editor::SetEmptySelection(Sci::Position currentPos_) { SetEmptySelection(SelectionPosition(currentPos_)); } +void Editor::SetSelectionFromSerialized(const char *serialized) { + if (serialized) { + sel = Selection(serialized); + sel.Truncate(pdoc->Length()); + SetRectangularRange(); + InvalidateStyleRedraw(); + } +} + void Editor::MultipleSelectAdd(AddNumber addNumber) { if (SelectionEmpty() || !multipleSelection) { // Select word at caret @@ -8695,6 +8704,15 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { case Message::GetUndoSelectionHistory: return static_cast<sptr_t>(undoSelectionHistoryOption); + case Message::SetSelectionSerialized: + SetSelectionFromSerialized(ConstCharPtrFromSPtr(lParam)); + break; + + case Message::GetSelectionSerialized: { + const std::string serialized = sel.ToString(); + return BytesResult(lParam, serialized); + } + case Message::SetExtraAscent: vs.extraAscent = static_cast<int>(wParam); InvalidateStyleRedraw(); diff --git a/src/Editor.h b/src/Editor.h index a6a484ede..ff940bc49 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -352,6 +352,7 @@ protected: // ScintillaBase subclass needs access to much of Editor void SetSelection(SelectionPosition currentPos_); void SetEmptySelection(SelectionPosition currentPos_); void SetEmptySelection(Sci::Position currentPos_); + void SetSelectionFromSerialized(const char *serialized); enum class AddNumber { one, each }; void MultipleSelectAdd(AddNumber addNumber); bool RangeContainsProtected(Sci::Position start, Sci::Position end) const noexcept; diff --git a/src/Selection.cxx b/src/Selection.cxx index 5650d5c7e..7b517cc4a 100644 --- a/src/Selection.cxx +++ b/src/Selection.cxx @@ -225,6 +225,13 @@ bool SelectionRange::Trim(SelectionRange range) noexcept { } } +void SelectionRange::Truncate(Sci::Position length) noexcept { + if (anchor.Position() > length) + anchor.SetPosition(length); + if (caret.Position() > length) + caret.SetPosition(length); +} + // If range is all virtual collapse to start of virtual space void SelectionRange::MinimizeVirtualSpace() noexcept { if (caret.Position() == anchor.Position()) { @@ -568,6 +575,16 @@ void Selection::SetRanges(const Ranges &rangesToSet) { ranges = rangesToSet; } +void Selection::Truncate(Sci::Position length) noexcept { + // This may be needed when applying a persisted selection onto a document that has been shortened. + for (SelectionRange &range : ranges) { + range.Truncate(length); + } + // Above may have made some non-unique empty ranges. + RemoveDuplicates(); + rangeRectangular.Truncate(length); +} + std::string Selection::ToString() const { std::string result; switch (selType) { diff --git a/src/Selection.h b/src/Selection.h index 68e7a4e54..57de92a57 100644 --- a/src/Selection.h +++ b/src/Selection.h @@ -148,6 +148,7 @@ struct SelectionRange { } void Swap() noexcept; bool Trim(SelectionRange range) noexcept; + void Truncate(Sci::Position length) noexcept; // If range is all virtual collapse to start of virtual space void MinimizeVirtualSpace() noexcept; std::string ToString() const; @@ -216,6 +217,7 @@ public: return ranges; } void SetRanges(const Ranges &rangesToSet); + void Truncate(Sci::Position length) noexcept; std::string ToString() const; }; diff --git a/test/simpleTests.py b/test/simpleTests.py index ce67edfde..867c0ebbc 100644 --- a/test/simpleTests.py +++ b/test/simpleTests.py @@ -2242,6 +2242,39 @@ class TestMultiSelection(unittest.TestCase): self.assertEqual(self.ed.Contents(), b'a 1') self.assertEqual(self.textOfSelection(0), b' ') + def testSelectionSerialization(self): + self.ed.SetContents(b"a") + self.ed.SetSelection(0, 1) + self.assertEqual(self.ed.GetSelectionSerialized(), b'1-0') + self.ed.SetSelection(1, 1) + self.assertEqual(self.ed.GetSelectionSerialized(), b'1') + self.ed.SetSelectionNAnchorVirtualSpace(0, 2) + self.ed.SetSelectionNCaretVirtualSpace(0, 3) + self.assertEqual(selectionRepresentation(self.ed, 0), "1+2v-1+3v") + self.assertEqual(self.textOfSelection(0), b'') + self.assertEqual(self.ed.GetSelectionSerialized(), b'1v2-1v3') + self.ed.SetSelectionSerialized(0, b'1-0') + self.assertEqual(self.ed.MainSelection, 0) + self.assertEqual(self.ed.Anchor, 1) + self.assertEqual(self.ed.CurrentPos, 0) + self.assertEqual(self.ed.GetSelectionNAnchor(0), 1) + self.assertEqual(self.ed.GetSelectionNCaret(0), 0) + + def testSelectionSerializationOutOfBounds(self): + # Try setting selections that extend past document end through serialized form + # and check that the selection is limited to the document. + self.ed.SetContents(b"a") + self.ed.SetSelectionSerialized(0, b'200-0') + self.assertEqual(self.ed.GetSelectionSerialized(), b'1-0') + + # Retain virtual space + self.ed.SetSelectionSerialized(0, b'0v1-200') + self.assertEqual(self.ed.GetSelectionSerialized(), b'0v1-1') + + # Drop identical ranges, but touching empty range survives + self.ed.SetSelectionSerialized(0, b'0-200,300-400,500-600') + self.assertEqual(self.ed.GetSelectionSerialized(), b'0-1,1') + class TestModalSelection(unittest.TestCase): |