aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--call/ScintillaCall.cxx4
-rw-r--r--doc/ScintillaDoc.html15
-rw-r--r--doc/ScintillaHistory.html3
-rw-r--r--include/Scintilla.h1
-rw-r--r--include/Scintilla.iface4
-rw-r--r--include/ScintillaCall.h1
-rw-r--r--include/ScintillaMessages.h1
-rw-r--r--src/Editor.cxx70
-rw-r--r--src/Editor.h1
-rw-r--r--test/simpleTests.py47
10 files changed, 91 insertions, 56 deletions
diff --git a/call/ScintillaCall.cxx b/call/ScintillaCall.cxx
index 4981d6299..6935eacbd 100644
--- a/call/ScintillaCall.cxx
+++ b/call/ScintillaCall.cxx
@@ -2363,6 +2363,10 @@ void ScintillaCall::SetSelectionMode(Scintilla::SelectionMode selectionMode) {
Call(Message::SetSelectionMode, static_cast<uintptr_t>(selectionMode));
}
+void ScintillaCall::ChangeSelectionMode(Scintilla::SelectionMode selectionMode) {
+ Call(Message::ChangeSelectionMode, static_cast<uintptr_t>(selectionMode));
+}
+
SelectionMode ScintillaCall::SelectionMode() {
return static_cast<Scintilla::SelectionMode>(Call(Message::GetSelectionMode));
}
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html
index 43407a40b..dcabdd9ee 100644
--- a/doc/ScintillaDoc.html
+++ b/doc/ScintillaDoc.html
@@ -979,6 +979,7 @@ struct Sci_TextRangeFull {
<a class="message" href="#SCI_GETCURLINE">SCI_GETCURLINE(position length, char *text) &rarr; position</a><br />
<a class="message" href="#SCI_SELECTIONISRECTANGLE">SCI_SELECTIONISRECTANGLE &rarr; bool</a><br />
<a class="message" href="#SCI_SETSELECTIONMODE">SCI_SETSELECTIONMODE(int selectionMode)</a><br />
+ <a class="message" href="#SCI_CHANGESELECTIONMODE">SCI_CHANGESELECTIONMODE(int selectionMode)</a><br />
<a class="message" href="#SCI_GETSELECTIONMODE">SCI_GETSELECTIONMODE &rarr; int</a><br />
<a class="message" href="#SCI_SETMOVEEXTENDSSELECTION">SCI_SETMOVEEXTENDSSELECTION(bool moveExtendsSelection)</a><br />
<a class="message" href="#SCI_GETMOVEEXTENDSSELECTION">SCI_GETMOVEEXTENDSSELECTION &rarr; bool</a><br />
@@ -1122,17 +1123,19 @@ struct Sci_TextRangeFull {
<p><b id="SCI_SELECTIONISRECTANGLE">SCI_SELECTIONISRECTANGLE &rarr; bool</b><br />
This returns 1 if the current selection is in rectangle mode, 0 if not.</p>
- <p><b id="SCI_SETSELECTIONMODE">SCI_SETSELECTIONMODE(int selectionMode)</b><br />
+ <p>
+ <b id="SCI_SETSELECTIONMODE">SCI_SETSELECTIONMODE(int selectionMode)</b><br />
+ <b id="SCI_CHANGESELECTIONMODE">SCI_CHANGESELECTIONMODE(int selectionMode)</b><br />
<b id="SCI_GETSELECTIONMODE">SCI_GETSELECTIONMODE &rarr; int</b><br />
- The two functions set and get the selection mode, which can be
+ The functions set, change, and get the selection mode, which can be
stream (<code>SC_SEL_STREAM</code>=0) or
rectangular (<code>SC_SEL_RECTANGLE</code>=1) or
by lines (<code>SC_SEL_LINES</code>=2)
or thin rectangular (<code>SC_SEL_THIN</code>=3).
- When set in these modes, regular caret moves will extend or reduce the selection,
- until the mode is cancelled by a call with same value or with <code>SCI_CANCEL</code>.
- The get function returns the current mode even if the selection was made by mouse
- or with regular extended moves.
+ When <code>SCI_SETSELECTIONMODE</code> sets these modes, regular caret moves will extend or reduce the selection,
+ until the mode is cancelled by a call with same value, or with <code>SCI_CANCEL</code>, or with <code>SCI_SETMOVEEXTENDSSELECTION</code>.
+ <code>SCI_CHANGESELECTIONMODE</code> sets the mode but does not make regular caret moves extend or reduce the selection.</p>
+ <p>The get function returns the current mode even if the selection was made by mouse or with regular extended moves.
<code>SC_SEL_THIN</code> is the mode after a rectangular selection has been typed into and ensures
that no characters are selected.</p>
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index f823ee0ef..b808bd4b8 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -591,7 +591,8 @@
Released 18 November 2023.
</li>
<li>
- Add SCI_SETMOVEEXTENDSSELECTION to simplify selection mode manipulation.
+ Add SCI_SETMOVEEXTENDSSELECTION and SCI_CHANGESELECTIONMODE to
+ simplify selection mode manipulation.
</li>
<li>
Improve performance of global replace by reducing cache invalidation overhead.
diff --git a/include/Scintilla.h b/include/Scintilla.h
index 5b85dac47..64238a5a3 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -874,6 +874,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SC_SEL_LINES 2
#define SC_SEL_THIN 3
#define SCI_SETSELECTIONMODE 2422
+#define SCI_CHANGESELECTIONMODE 2659
#define SCI_GETSELECTIONMODE 2423
#define SCI_SETMOVEEXTENDSSELECTION 2719
#define SCI_GETMOVEEXTENDSSELECTION 2706
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index b15606af0..c393d6179 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -2359,6 +2359,10 @@ val SC_SEL_THIN=3
# by lines (SC_SEL_LINES).
set void SetSelectionMode=2422(SelectionMode selectionMode,)
+# Set the selection mode to stream (SC_SEL_STREAM) or rectangular (SC_SEL_RECTANGLE/SC_SEL_THIN) or
+# by lines (SC_SEL_LINES) without changing MoveExtendsSelection.
+fun void ChangeSelectionMode=2659(SelectionMode selectionMode,)
+
# Get the mode of the current selection.
get SelectionMode GetSelectionMode=2423(,)
diff --git a/include/ScintillaCall.h b/include/ScintillaCall.h
index 0c95ef9e7..7f8088748 100644
--- a/include/ScintillaCall.h
+++ b/include/ScintillaCall.h
@@ -634,6 +634,7 @@ public:
void CopyRange(Position start, Position end);
void CopyText(Position length, const char *text);
void SetSelectionMode(Scintilla::SelectionMode selectionMode);
+ void ChangeSelectionMode(Scintilla::SelectionMode selectionMode);
Scintilla::SelectionMode SelectionMode();
void SetMoveExtendsSelection(bool moveExtendsSelection);
bool MoveExtendsSelection();
diff --git a/include/ScintillaMessages.h b/include/ScintillaMessages.h
index e45398d72..eaf162ae5 100644
--- a/include/ScintillaMessages.h
+++ b/include/ScintillaMessages.h
@@ -556,6 +556,7 @@ enum class Message {
CopyRange = 2419,
CopyText = 2420,
SetSelectionMode = 2422,
+ ChangeSelectionMode = 2659,
GetSelectionMode = 2423,
SetMoveExtendsSelection = 2719,
GetMoveExtendsSelection = 2706,
diff --git a/src/Editor.cxx b/src/Editor.cxx
index ca7fe2e88..627179876 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -6009,6 +6009,43 @@ void Editor::SetSelectionNMessage(Message iMessage, uptr_t wParam, sptr_t lParam
ContainerNeedsUpdate(Update::Selection);
}
+namespace {
+
+constexpr Selection::SelTypes SelTypeFromMode(SelectionMode mode) {
+ switch (mode) {
+ case SelectionMode::Rectangle:
+ return Selection::SelTypes::rectangle;
+ case SelectionMode::Lines:
+ return Selection::SelTypes::lines;
+ case SelectionMode::Thin:
+ return Selection::SelTypes::thin;
+ case SelectionMode::Stream:
+ default:
+ return Selection::SelTypes::stream;
+ }
+}
+
+}
+
+void Editor::SetSelectionMode(uptr_t wParam, bool setMoveExtends) {
+ const Selection::SelTypes newSelType = SelTypeFromMode(static_cast<SelectionMode>(wParam));
+ if (setMoveExtends) {
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != newSelType));
+ }
+ sel.selType = newSelType;
+ switch (sel.selType) {
+ case Selection::SelTypes::rectangle:
+ sel.Rectangular() = sel.RangeMain(); // adjust current selection
+ break;
+ case Selection::SelTypes::lines:
+ SetSelection(sel.RangeMain().caret, sel.RangeMain().anchor); // adjust current selection
+ break;
+ default:
+ ;
+ }
+ InvalidateWholeSelection();
+}
+
sptr_t Editor::StringResult(sptr_t lParam, const char *val) noexcept {
const size_t len = val ? strlen(val) : 0;
if (lParam) {
@@ -8186,33 +8223,12 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
case Message::SelectionIsRectangle:
return sel.selType == Selection::SelTypes::rectangle ? 1 : 0;
- case Message::SetSelectionMode: {
- switch (static_cast<SelectionMode>(wParam)) {
- case SelectionMode::Stream:
- sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::SelTypes::stream));
- sel.selType = Selection::SelTypes::stream;
- break;
- case SelectionMode::Rectangle:
- sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::SelTypes::rectangle));
- sel.selType = Selection::SelTypes::rectangle;
- sel.Rectangular() = sel.RangeMain(); // adjust current selection
- break;
- case SelectionMode::Lines:
- sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::SelTypes::lines));
- sel.selType = Selection::SelTypes::lines;
- SetSelection(sel.RangeMain().caret, sel.RangeMain().anchor); // adjust current selection
- break;
- case SelectionMode::Thin:
- sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::SelTypes::thin));
- sel.selType = Selection::SelTypes::thin;
- break;
- default:
- sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::SelTypes::stream));
- sel.selType = Selection::SelTypes::stream;
- }
- InvalidateWholeSelection();
- break;
- }
+ case Message::SetSelectionMode:
+ SetSelectionMode(wParam, true);
+ break;
+ case Message::ChangeSelectionMode:
+ SetSelectionMode(wParam, false);
+ break;
case Message::GetSelectionMode:
switch (sel.selType) {
case Selection::SelTypes::stream:
diff --git a/src/Editor.h b/src/Editor.h
index 8c6458879..e7e198aec 100644
--- a/src/Editor.h
+++ b/src/Editor.h
@@ -612,6 +612,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
void StyleSetMessage(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam);
Scintilla::sptr_t StyleGetMessage(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam);
void SetSelectionNMessage(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam);
+ void SetSelectionMode(uptr_t wParam, bool setMoveExtends);
// Coercion functions for transforming WndProc parameters into pointers
static void *PtrFromSPtr(Scintilla::sptr_t lParam) noexcept {
diff --git a/test/simpleTests.py b/test/simpleTests.py
index 6f82c4004..fd1f7423a 100644
--- a/test/simpleTests.py
+++ b/test/simpleTests.py
@@ -1747,6 +1747,10 @@ def selectionRepresentation(ed, n):
caret = (ed.GetSelectionNCaret(n), ed.GetSelectionNCaretVirtualSpace(n))
return selectionRangeRepresentation((anchor, caret))
+def allSelectionsRepresentation(ed):
+ reps = [selectionRepresentation(ed, i) for i in range(ed.Selections)]
+ return ';'.join(reps)
+
class TestMultiSelection(unittest.TestCase):
def setUp(self):
@@ -2051,29 +2055,32 @@ class TestModalSelection(unittest.TestCase):
def testCharacterSelection(self):
self.ed.SetSelection(1, 1)
- self.assertEqual(self.ed.Selections, 1)
self.assertEqual(self.ed.MainSelection, 0)
- self.assertEqual(self.ed.GetSelectionNCaret(0), 1)
- self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
+ self.assertEqual(allSelectionsRepresentation(self.ed), "1-1")
self.ed.SelectionMode = self.ed.SC_SEL_STREAM
self.assertEqual(self.ed.GetSelectionMode(), self.ed.SC_SEL_STREAM)
self.assertEqual(self.ed.MoveExtendsSelection, True)
- self.assertEqual(self.ed.Selections, 1)
- self.assertEqual(self.ed.MainSelection, 0)
- self.assertEqual(self.ed.GetSelectionNCaret(0), 1)
- self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
+ self.assertEqual(allSelectionsRepresentation(self.ed), "1-1")
self.ed.CharRight()
- self.assertEqual(self.ed.Selections, 1)
- self.assertEqual(self.ed.MainSelection, 0)
- self.assertEqual(self.ed.GetSelectionNCaret(0), 2)
- self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
+ self.assertEqual(allSelectionsRepresentation(self.ed), "1-2")
self.ed.LineDown()
- self.assertEqual(self.ed.Selections, 1)
- self.assertEqual(self.ed.MainSelection, 0)
- self.assertEqual(self.ed.GetSelectionNCaret(0), 6)
- self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
+ self.assertEqual(allSelectionsRepresentation(self.ed), "1-6")
self.ed.ClearSelections()
-
+
+ def testChangeSelectionMode(self):
+ # Like testCharacterSelection but calling ChangeSelectionMode instead of SetSelectionMode
+ self.ed.SetSelection(1, 1)
+ self.assertEqual(allSelectionsRepresentation(self.ed), "1-1")
+ self.ed.ChangeSelectionMode(self.ed.SC_SEL_STREAM)
+ self.assertEqual(self.ed.GetSelectionMode(), self.ed.SC_SEL_STREAM)
+ self.assertEqual(self.ed.MoveExtendsSelection, False)
+ self.assertEqual(allSelectionsRepresentation(self.ed), "1-1")
+ self.ed.CharRight()
+ self.assertEqual(allSelectionsRepresentation(self.ed), "2-2")
+ self.ed.LineDown()
+ self.assertEqual(allSelectionsRepresentation(self.ed), "6-6")
+ self.ed.ClearSelections()
+
def testTurningOffMoveExtendsSelection(self):
self.ed.SetSelection(1, 1)
self.ed.SelectionMode = self.ed.SC_SEL_STREAM
@@ -2083,13 +2090,9 @@ class TestModalSelection(unittest.TestCase):
self.ed.MoveExtendsSelection = False
self.assertEqual(self.ed.MoveExtendsSelection, False)
self.ed.CharRight()
- self.assertEqual(self.ed.Selections, 1)
- self.assertEqual(self.ed.MainSelection, 0)
- self.assertEqual(selectionRepresentation(self.ed, 0), "6-6")
+ self.assertEqual(allSelectionsRepresentation(self.ed), "6-6")
self.ed.CharRight()
- self.assertEqual(self.ed.Selections, 1)
- self.assertEqual(self.ed.MainSelection, 0)
- self.assertEqual(selectionRepresentation(self.ed, 0), "7-7")
+ self.assertEqual(allSelectionsRepresentation(self.ed), "7-7")
self.ed.ClearSelections()
def testRectangleSelection(self):