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