diff options
| -rw-r--r-- | call/ScintillaCall.cxx | 4 | ||||
| -rw-r--r-- | doc/ScintillaDoc.html | 15 | ||||
| -rw-r--r-- | doc/ScintillaHistory.html | 3 | ||||
| -rw-r--r-- | include/Scintilla.h | 1 | ||||
| -rw-r--r-- | include/Scintilla.iface | 4 | ||||
| -rw-r--r-- | include/ScintillaCall.h | 1 | ||||
| -rw-r--r-- | include/ScintillaMessages.h | 1 | ||||
| -rw-r--r-- | src/Editor.cxx | 70 | ||||
| -rw-r--r-- | src/Editor.h | 1 | ||||
| -rw-r--r-- | test/simpleTests.py | 47 | 
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) → position</a><br />       <a class="message" href="#SCI_SELECTIONISRECTANGLE">SCI_SELECTIONISRECTANGLE → 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 → int</a><br />       <a class="message" href="#SCI_SETMOVEEXTENDSSELECTION">SCI_SETMOVEEXTENDSSELECTION(bool moveExtendsSelection)</a><br />       <a class="message" href="#SCI_GETMOVEEXTENDSSELECTION">SCI_GETMOVEEXTENDSSELECTION → bool</a><br /> @@ -1122,17 +1123,19 @@ struct Sci_TextRangeFull {      <p><b id="SCI_SELECTIONISRECTANGLE">SCI_SELECTIONISRECTANGLE → 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 → 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): | 
