From 20b58d60c083e55117401bb8816f59f2711fc5b7 Mon Sep 17 00:00:00 2001
From: mitchell <70453897+667e-11@users.noreply.github.com>
Date: Sat, 24 Feb 2018 21:15:15 -0500
Subject: Backported fix for rect and line selection movements from upstream
Scintilla.
---
src/scintilla_backports/6456_eaa6c7fa1a81.patch | 56 +++++
src/scintilla_backports/6458_0a8a766722c0.patch | 297 ++++++++++++++++++++++++
src/scintilla_backports/revs | 2 +
3 files changed, 355 insertions(+)
create mode 100644 src/scintilla_backports/6456_eaa6c7fa1a81.patch
create mode 100644 src/scintilla_backports/6458_0a8a766722c0.patch
(limited to 'src')
diff --git a/src/scintilla_backports/6456_eaa6c7fa1a81.patch b/src/scintilla_backports/6456_eaa6c7fa1a81.patch
new file mode 100644
index 00000000..81032495
--- /dev/null
+++ b/src/scintilla_backports/6456_eaa6c7fa1a81.patch
@@ -0,0 +1,56 @@
+# HG changeset patch
+# User Vicente
+# Date 1518837132 -39600
+# Node ID eaa6c7fa1a811bd10abe19124335e984e50a67e5
+# Parent b9e27867752769a2cb7057cab8942baf4850757b
+For rectangular selections, pressing Home or End now moves the caret to the Home
+or End position instead of the limit of the rectangular selection.
+
+diff -r b9e278677527 -r eaa6c7fa1a81 doc/ScintillaHistory.html
+--- a/doc/ScintillaHistory.html Sat Feb 17 11:28:52 2018 +1100
++++ b/doc/ScintillaHistory.html Sat Feb 17 14:12:12 2018 +1100
+@@ -540,6 +540,10 @@
+ Released 12 February 2018.
+
+
++ For rectangular selections, pressing Home or End now moves the caret to the Home or End
++ position instead of the limit of the rectangular selection.
++
++
+ SciTE on Windows can execute Python scripts directly by name when on path.
+ Feature #1209.
+
+diff -r b9e278677527 -r eaa6c7fa1a81 src/Editor.cxx
+--- a/src/Editor.cxx Sat Feb 17 11:28:52 2018 +1100
++++ b/src/Editor.cxx Sat Feb 17 14:12:12 2018 +1100
+@@ -3359,8 +3359,19 @@
+ SetRectangularRange();
+ } else if (sel.IsRectangular()) {
+ // Not a rectangular extension so switch to stream.
+- const SelectionPosition selAtLimit =
+- (NaturalDirection(iMessage) > 0) ? sel.Limits().end : sel.Limits().start;
++ SelectionPosition selAtLimit = (NaturalDirection(iMessage) > 0) ? sel.Limits().end : sel.Limits().start;
++ switch (iMessage) {
++ case SCI_HOME:
++ selAtLimit = SelectionPosition(
++ static_cast(pdoc->LineStart(pdoc->LineFromPosition(selAtLimit.Position()))));
++ break;
++ case SCI_VCHOME:
++ selAtLimit = SelectionPosition(pdoc->VCHomePosition(selAtLimit.Position()));
++ break;
++ case SCI_LINEEND:
++ selAtLimit = SelectionPosition(pdoc->LineEndPosition(selAtLimit.Position()));
++ break;
++ }
+ sel.selType = Selection::selStream;
+ sel.SetSelection(SelectionRange(selAtLimit));
+ } else {
+@@ -7537,7 +7548,7 @@
+ std::vector().swap(vs.theMultiEdge); // Free vector and memory, C++03 compatible
+ InvalidateStyleRedraw();
+ break;
+-
++
+ case SCI_GETACCESSIBILITY:
+ return SC_ACCESSIBILITY_DISABLED;
+
diff --git a/src/scintilla_backports/6458_0a8a766722c0.patch b/src/scintilla_backports/6458_0a8a766722c0.patch
new file mode 100644
index 00000000..64bcb748
--- /dev/null
+++ b/src/scintilla_backports/6458_0a8a766722c0.patch
@@ -0,0 +1,297 @@
+# HG changeset patch
+# User Mitchell
+# Date 1519447387 -39600
+# Node ID 0a8a766722c0bc91e1e2ecd958927a504cea5cac
+# Parent 26e7749ba67ae8fc994e2f17c760a65c5d0ca479
+Fix move-extends-selection mode for rectangular and line selections.
+
+diff -r 26e7749ba67a -r 0a8a766722c0 doc/ScintillaHistory.html
+--- a/doc/ScintillaHistory.html Thu Feb 22 08:13:37 2018 +1100
++++ b/doc/ScintillaHistory.html Sat Feb 24 15:43:07 2018 +1100
+@@ -548,6 +548,9 @@
+ Bug #1993.
+
+
++ Fix move-extends-selection mode for rectangular and line selections.
++
++
+ SciTE on Windows can execute Python scripts directly by name when on path.
+ Feature #1209.
+
+diff -r 26e7749ba67a -r 0a8a766722c0 src/Editor.cxx
+--- a/src/Editor.cxx Thu Feb 22 08:13:37 2018 +1100
++++ b/src/Editor.cxx Sat Feb 24 15:43:07 2018 +1100
+@@ -626,26 +626,31 @@
+ InvalidateSelection(sel.RangeMain(), true);
+ }
+
++/* For Line selection - the anchor and caret are always
++ at the beginning and end of the region lines. */
++SelectionRange Editor::LineSelectionRange(SelectionPosition currentPos_, SelectionPosition anchor_) const {
++ if (currentPos_ > anchor_) {
++ anchor_ = SelectionPosition(static_cast(
++ pdoc->LineStart(pdoc->LineFromPosition(anchor_.Position()))));
++ currentPos_ = SelectionPosition(static_cast(
++ pdoc->LineEnd(pdoc->LineFromPosition(currentPos_.Position()))));
++ } else {
++ currentPos_ = SelectionPosition(static_cast(
++ pdoc->LineStart(pdoc->LineFromPosition(currentPos_.Position()))));
++ anchor_ = SelectionPosition(static_cast(
++ pdoc->LineEnd(pdoc->LineFromPosition(anchor_.Position()))));
++ }
++ return SelectionRange(currentPos_, anchor_);
++}
++
+ void Editor::SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_) {
+ currentPos_ = ClampPositionIntoDocument(currentPos_);
+ anchor_ = ClampPositionIntoDocument(anchor_);
+ Sci::Line currentLine = static_cast(pdoc->LineFromPosition(currentPos_.Position()));
+- /* For Line selection - ensure the anchor and caret are always
+- at the beginning and end of the region lines. */
++ SelectionRange rangeNew(currentPos_, anchor_);
+ if (sel.selType == Selection::selLines) {
+- if (currentPos_ > anchor_) {
+- anchor_ = SelectionPosition(static_cast(
+- pdoc->LineStart(pdoc->LineFromPosition(anchor_.Position()))));
+- currentPos_ = SelectionPosition(static_cast(
+- pdoc->LineEnd(pdoc->LineFromPosition(currentPos_.Position()))));
+- } else {
+- currentPos_ = SelectionPosition(static_cast(
+- pdoc->LineStart(pdoc->LineFromPosition(currentPos_.Position()))));
+- anchor_ = SelectionPosition(static_cast(
+- pdoc->LineEnd(pdoc->LineFromPosition(anchor_.Position()))));
+- }
+- }
+- SelectionRange rangeNew(currentPos_, anchor_);
++ rangeNew = LineSelectionRange(currentPos_, anchor_);
++ }
+ if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) {
+ InvalidateSelection(rangeNew);
+ }
+@@ -675,6 +680,8 @@
+ sel.Rectangular() =
+ SelectionRange(SelectionPosition(currentPos_), sel.Rectangular().anchor);
+ SetRectangularRange();
++ } else if (sel.selType == Selection::selLines) {
++ sel.RangeMain() = LineSelectionRange(currentPos_, sel.RangeMain().anchor);
+ } else {
+ sel.RangeMain() =
+ SelectionRange(SelectionPosition(currentPos_), sel.RangeMain().anchor);
+@@ -3120,7 +3127,7 @@
+
+ void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) {
+ if ((selt == Selection::noSel) && sel.MoveExtends()) {
+- selt = Selection::selStream;
++ selt = !sel.IsRectangular() ? Selection::selStream : Selection::selRectangle;
+ }
+ SelectionPosition caretToUse = sel.Range(sel.Main()).caret;
+ if (sel.IsRectangular()) {
+@@ -3142,6 +3149,11 @@
+ sel.Rectangular() = SelectionRange(posNew, rangeBase.anchor);
+ SetRectangularRange();
+ MovedCaret(posNew, caretToUse, true);
++ } else if (sel.selType == Selection::selLines && sel.MoveExtends()) {
++ // Calculate new caret position and call SetSelection(), which will ensure whole lines are selected.
++ const SelectionPosition posNew = MovePositionSoVisible(
++ PositionUpOrDown(caretToUse, direction, -1), direction);
++ SetSelection(posNew, sel.Range(sel.Main()).anchor);
+ } else {
+ InvalidateWholeSelection();
+ if (!additionalSelectionTyping || (sel.IsRectangular())) {
+@@ -3263,7 +3275,7 @@
+ }
+ }
+
+-bool IsRectExtend(unsigned int iMessage) {
++bool IsRectExtend(unsigned int iMessage, bool isRectMoveExtends) {
+ switch (iMessage) {
+ case SCI_CHARLEFTRECTEXTEND:
+ case SCI_CHARRIGHTRECTEXTEND:
+@@ -3272,6 +3284,19 @@
+ case SCI_LINEENDRECTEXTEND:
+ return true;
+ default:
++ if (isRectMoveExtends) {
++ // Handle SCI_SETSELECTIONMODE(SC_SEL_RECTANGLE) and subsequent movements.
++ switch (iMessage) {
++ case SCI_CHARLEFTEXTEND:
++ case SCI_CHARRIGHTEXTEND:
++ case SCI_HOMEEXTEND:
++ case SCI_VCHOMEEXTEND:
++ case SCI_LINEENDEXTEND:
++ return true;
++ default:
++ return false;
++ }
++ }
+ return false;
+ }
+ }
+@@ -3307,6 +3332,9 @@
+ }
+
+ int Editor::HorizontalMove(unsigned int iMessage) {
++ if (sel.selType == Selection::selLines) {
++ return 0; // horizontal moves with line selection have no effect
++ }
+ if (sel.MoveExtends()) {
+ iMessage = WithExtends(iMessage);
+ }
+@@ -3319,7 +3347,7 @@
+ // Invalidate each of the current selections
+ InvalidateWholeSelection();
+
+- if (IsRectExtend(iMessage)) {
++ if (IsRectExtend(iMessage, sel.IsRectangular() && sel.MoveExtends())) {
+ const SelectionRange rangeBase = sel.IsRectangular() ? sel.Rectangular() : sel.RangeMain();
+ if (!sel.IsRectangular()) {
+ sel.DropAdditionalRanges();
+@@ -3328,6 +3356,7 @@
+ SelectionPosition spCaret = rangeBase.caret;
+ switch (iMessage) {
+ case SCI_CHARLEFTRECTEXTEND:
++ case SCI_CHARLEFTEXTEND: // only when sel.IsRectangular() && sel.MoveExtends()
+ if (pdoc->IsLineEndPosition(spCaret.Position()) && spCaret.VirtualSpace()) {
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
+ } else if ((virtualSpaceOptions & SCVS_NOWRAPLINESTART) == 0 || pdoc->GetColumn(spCaret.Position()) > 0) {
+@@ -3335,6 +3364,7 @@
+ }
+ break;
+ case SCI_CHARRIGHTRECTEXTEND:
++ case SCI_CHARRIGHTEXTEND: // only when sel.IsRectangular() && sel.MoveExtends()
+ if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) && pdoc->IsLineEndPosition(sel.MainCaret())) {
+ spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
+ } else {
+@@ -3342,13 +3372,16 @@
+ }
+ break;
+ case SCI_HOMERECTEXTEND:
++ case SCI_HOMEEXTEND: // only when sel.IsRectangular() && sel.MoveExtends()
+ spCaret = SelectionPosition(
+ static_cast(pdoc->LineStart(pdoc->LineFromPosition(spCaret.Position()))));
+ break;
+ case SCI_VCHOMERECTEXTEND:
++ case SCI_VCHOMEEXTEND: // only when sel.IsRectangular() && sel.MoveExtends()
+ spCaret = SelectionPosition(pdoc->VCHomePosition(spCaret.Position()));
+ break;
+ case SCI_LINEENDRECTEXTEND:
++ case SCI_LINEENDEXTEND: // only when sel.IsRectangular() && sel.MoveExtends()
+ spCaret = SelectionPosition(pdoc->LineEndPosition(spCaret.Position()));
+ break;
+ }
+@@ -7615,10 +7648,12 @@
+ case SC_SEL_RECTANGLE:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selRectangle));
+ sel.selType = Selection::selRectangle;
++ sel.Rectangular() = sel.RangeMain(); // adjust current selection
+ break;
+ case SC_SEL_LINES:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selLines));
+ sel.selType = Selection::selLines;
++ SetSelection(sel.RangeMain().caret, sel.RangeMain().anchor); // adjust current selection
+ break;
+ case SC_SEL_THIN:
+ sel.SetMoveExtends(!sel.MoveExtends() || (sel.selType != Selection::selThin));
+diff -r 26e7749ba67a -r 0a8a766722c0 src/Editor.h
+--- a/src/Editor.h Thu Feb 22 08:13:37 2018 +1100
++++ b/src/Editor.h Sat Feb 24 15:43:07 2018 +1100
+@@ -312,6 +312,7 @@
+ void ThinRectangularRange();
+ void InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection=false);
+ void InvalidateWholeSelection();
++ SelectionRange LineSelectionRange(SelectionPosition currentPos_, SelectionPosition anchor_) const;
+ void SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_);
+ void SetSelection(Sci::Position currentPos_, Sci::Position anchor_);
+ void SetSelection(SelectionPosition currentPos_);
+diff -r 26e7749ba67a -r 0a8a766722c0 test/simpleTests.py
+--- a/test/simpleTests.py Thu Feb 22 08:13:37 2018 +1100
++++ b/test/simpleTests.py Sat Feb 24 15:43:07 2018 +1100
+@@ -1466,6 +1466,88 @@
+ self.ed.DropSelectionN(0)
+ self.assertEquals(self.ed.MainSelection, 2)
+
++class TestModalSelection(unittest.TestCase):
++
++ def setUp(self):
++ self.xite = Xite.xiteFrame
++ self.ed = self.xite.ed
++ self.ed.ClearAll()
++ self.ed.EmptyUndoBuffer()
++ # 3 lines of 3 characters
++ t = b"xxx\nxxx\nxxx"
++ self.ed.AddText(len(t), t)
++
++ def testCharacterSelection(self):
++ self.ed.SetSelection(1, 1)
++ self.assertEquals(self.ed.Selections, 1)
++ self.assertEquals(self.ed.MainSelection, 0)
++ self.assertEquals(self.ed.GetSelectionNCaret(0), 1)
++ self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
++ self.ed.SelectionMode = self.ed.SC_SEL_STREAM
++ self.assertEquals(self.ed.Selections, 1)
++ self.assertEquals(self.ed.MainSelection, 0)
++ self.assertEquals(self.ed.GetSelectionNCaret(0), 1)
++ self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
++ self.ed.CharRight()
++ self.assertEquals(self.ed.Selections, 1)
++ self.assertEquals(self.ed.MainSelection, 0)
++ self.assertEquals(self.ed.GetSelectionNCaret(0), 2)
++ self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
++ self.ed.LineDown()
++ self.assertEquals(self.ed.Selections, 1)
++ self.assertEquals(self.ed.MainSelection, 0)
++ self.assertEquals(self.ed.GetSelectionNCaret(0), 6)
++ self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
++ self.ed.ClearSelections()
++
++ def testRectangleSelection(self):
++ self.ed.SetSelection(1, 1)
++ self.assertEquals(self.ed.Selections, 1)
++ self.assertEquals(self.ed.MainSelection, 0)
++ self.assertEquals(self.ed.GetSelectionNCaret(0), 1)
++ self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
++ self.ed.SelectionMode = self.ed.SC_SEL_RECTANGLE
++ self.assertEquals(self.ed.Selections, 1)
++ self.assertEquals(self.ed.MainSelection, 0)
++ self.assertEquals(self.ed.GetSelectionNCaret(0), 1)
++ self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
++ self.ed.CharRight()
++ self.assertEquals(self.ed.Selections, 1)
++ self.assertEquals(self.ed.MainSelection, 0)
++ self.assertEquals(self.ed.GetSelectionNCaret(0), 2)
++ self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
++ self.ed.LineDown()
++ self.assertEquals(self.ed.Selections, 2)
++ self.assertEquals(self.ed.MainSelection, 1)
++ self.assertEquals(self.ed.GetSelectionNCaret(0), 2)
++ self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
++ self.assertEquals(self.ed.GetSelectionNCaret(1), 6)
++ self.assertEquals(self.ed.GetSelectionNAnchor(1), 5)
++ self.ed.ClearSelections()
++
++ def testLinesSelection(self):
++ self.ed.SetSelection(1, 1)
++ self.assertEquals(self.ed.Selections, 1)
++ self.assertEquals(self.ed.MainSelection, 0)
++ self.assertEquals(self.ed.GetSelectionNCaret(0), 1)
++ self.assertEquals(self.ed.GetSelectionNAnchor(0), 1)
++ self.ed.SelectionMode = self.ed.SC_SEL_LINES
++ self.assertEquals(self.ed.Selections, 1)
++ self.assertEquals(self.ed.MainSelection, 0)
++ self.assertEquals(self.ed.GetSelectionNCaret(0), 0)
++ self.assertEquals(self.ed.GetSelectionNAnchor(0), 3)
++ self.ed.CharRight()
++ self.assertEquals(self.ed.Selections, 1)
++ self.assertEquals(self.ed.MainSelection, 0)
++ self.assertEquals(self.ed.GetSelectionNCaret(0), 0)
++ self.assertEquals(self.ed.GetSelectionNAnchor(0), 3)
++ self.ed.LineDown()
++ self.assertEquals(self.ed.Selections, 1)
++ self.assertEquals(self.ed.MainSelection, 0)
++ self.assertEquals(self.ed.GetSelectionNCaret(0), 7)
++ self.assertEquals(self.ed.GetSelectionNAnchor(0), 0)
++ self.ed.ClearSelections()
++
+ class TestStyleAttributes(unittest.TestCase):
+ """ These tests are just to ensure that the calls set and retrieve values.
+ They do not check the visual appearance of the style attributes.
diff --git a/src/scintilla_backports/revs b/src/scintilla_backports/revs
index 51649e3e..0f94210f 100644
--- a/src/scintilla_backports/revs
+++ b/src/scintilla_backports/revs
@@ -73,3 +73,5 @@ ed27432729c3 Use std::abs in preference to abs as std::abs is generic and abs ca
89d992f380a1 Templatize RunStyles so it can be over ranges of different types and contain
431b814a54a6 Implement SC_DOCUMENTOPTION_STYLES_NONE.
1280ef150bbb [Bug #1983] Fix double tap word selection on Windows 10 1709 Fall Creators Update.
+eaa6c7fa1a81 For rectangular selections, pressing Home or End now moves the caret to the Home
+0a8a766722c0 Fix move-extends-selection mode for rectangular and line selections.
--
cgit v1.2.3