diff options
-rw-r--r-- | src/Editor.cxx | 274 | ||||
-rw-r--r-- | src/Editor.h | 3 | ||||
-rw-r--r-- | src/Selection.h | 3 |
3 files changed, 134 insertions, 146 deletions
diff --git a/src/Editor.cxx b/src/Editor.cxx index 7d4417115..ade5094f7 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -3442,6 +3442,14 @@ constexpr bool IsRectExtend(Message iMessage, bool isRectMoveExtends) noexcept { } +Sci::Position Editor::HomeWrapPosition(Sci::Position position) { + const Sci::Position viewLineStart = StartEndDisplayLine(position, true); + const Sci::Position homePos = MovePositionSoVisible(viewLineStart, -1).Position(); + if (position <= homePos) + return pdoc->LineStartPosition(position); + return homePos; +} + Sci::Position Editor::VCHomeDisplayPosition(Sci::Position position) { const Sci::Position homePos = pdoc->VCHomePosition(position); const Sci::Position viewLineStart = StartEndDisplayLine(position, true); @@ -3470,6 +3478,125 @@ Sci::Position Editor::LineEndWrapPosition(Sci::Position position) { return endPos; } +SelectionPosition Editor::PositionMove(Message iMessage, SelectionPosition spCaret) { + switch (iMessage) { + case Message::CharLeft: + case Message::CharLeftExtend: + if (spCaret.VirtualSpace()) { + spCaret.AddVirtualSpace(-1); + } else if (!FlagSet(virtualSpaceOptions, VirtualSpace::NoWrapLineStart) || pdoc->GetColumn(spCaret.Position()) > 0) { + spCaret.Add(-1); + } + return spCaret; + case Message::CharRight: + case Message::CharRightExtend: + if (FlagSet(virtualSpaceOptions, VirtualSpace::UserAccessible) && pdoc->IsLineEndPosition(spCaret.Position())) { + spCaret.AddVirtualSpace(1); + } else { + spCaret.Add(1); + } + return spCaret; + case Message::WordLeft: + case Message::WordLeftExtend: + return SelectionPosition(pdoc->NextWordStart(spCaret.Position(), -1)); + case Message::WordRight: + case Message::WordRightExtend: + return SelectionPosition(pdoc->NextWordStart(spCaret.Position(), 1)); + case Message::WordLeftEnd: + case Message::WordLeftEndExtend: + return SelectionPosition(pdoc->NextWordEnd(spCaret.Position(), -1)); + case Message::WordRightEnd: + case Message::WordRightEndExtend: + return SelectionPosition(pdoc->NextWordEnd(spCaret.Position(), 1)); + case Message::WordPartLeft: + case Message::WordPartLeftExtend: + return SelectionPosition(pdoc->WordPartLeft(spCaret.Position())); + case Message::WordPartRight: + case Message::WordPartRightExtend: + return SelectionPosition(pdoc->WordPartRight(spCaret.Position())); + case Message::Home: + case Message::HomeExtend: + return SelectionPosition(pdoc->LineStartPosition(spCaret.Position())); + case Message::HomeDisplay: + case Message::HomeDisplayExtend: + return SelectionPosition(StartEndDisplayLine(spCaret.Position(), true)); + case Message::HomeWrap: + case Message::HomeWrapExtend: + return SelectionPosition(HomeWrapPosition(spCaret.Position())); + case Message::VCHome: + case Message::VCHomeExtend: + // VCHome alternates between beginning of line and beginning of text so may move back or forwards + return SelectionPosition(pdoc->VCHomePosition(spCaret.Position())); + case Message::VCHomeDisplay: + case Message::VCHomeDisplayExtend: + return SelectionPosition(VCHomeDisplayPosition(spCaret.Position())); + case Message::VCHomeWrap: + case Message::VCHomeWrapExtend: + return SelectionPosition(VCHomeWrapPosition(spCaret.Position())); + case Message::LineEnd: + case Message::LineEndExtend: + return SelectionPosition(pdoc->LineEndPosition(spCaret.Position())); + case Message::LineEndDisplay: + case Message::LineEndDisplayExtend: + return SelectionPosition(StartEndDisplayLine(spCaret.Position(), false)); + case Message::LineEndWrap: + case Message::LineEndWrapExtend: + return SelectionPosition(LineEndWrapPosition(spCaret.Position())); + + default: + break; + } + // Above switch should be exhaustive so this will never be reached. + PLATFORM_ASSERT(false); + return spCaret; +} + +SelectionRange Editor::SelectionMove(Scintilla::Message iMessage, size_t r) { + const SelectionPosition spCaretStart = sel.Range(r).caret; + const SelectionPosition spCaretMoved = PositionMove(iMessage, spCaretStart); + + const int directionMove = (spCaretMoved < spCaretStart) ? -1 : 1; + const SelectionPosition spCaret = MovePositionSoVisible(spCaretMoved, directionMove); + + // Handle move versus extend, and special behaviour for non-empty left/right + switch (iMessage) { + case Message::CharLeft: + case Message::CharRight: + if (sel.Range(r).Empty()) { + return SelectionRange(spCaret); + } + if (iMessage == Message::CharLeft) { + return SelectionRange(sel.Range(r).Start()); + } + return SelectionRange(sel.Range(r).End()); + + case Message::WordLeft: + case Message::WordRight: + case Message::WordLeftEnd: + case Message::WordRightEnd: + case Message::WordPartLeft: + case Message::WordPartRight: + case Message::Home: + case Message::HomeDisplay: + case Message::HomeWrap: + case Message::VCHome: + case Message::VCHomeDisplay: + case Message::VCHomeWrap: + case Message::LineEnd: + case Message::LineEndDisplay: + case Message::LineEndWrap: + return SelectionRange(spCaret); + + default: + break; + } + + // All remaining cases are *Extend + const SelectionRange rangeNew = SelectionRange(spCaret, sel.Range(r).anchor); + sel.TrimOtherSelections(r, rangeNew); + return rangeNew; +} + int Editor::HorizontalMove(Message iMessage) { if (sel.selType == Selection::SelTypes::lines) { return 0; // horizontal moves with line selection have no effect @@ -3554,152 +3681,7 @@ int Editor::HorizontalMove(Message iMessage) { sel.DropAdditionalRanges(); } for (size_t r = 0; r < sel.Count(); r++) { - const SelectionPosition spCaretNow = sel.Range(r).caret; - SelectionPosition spCaret = spCaretNow; - switch (iMessage) { - case Message::CharLeft: - case Message::CharLeftExtend: - if (spCaret.VirtualSpace()) { - spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1); - } else if (!FlagSet(virtualSpaceOptions, VirtualSpace::NoWrapLineStart) || pdoc->GetColumn(spCaret.Position()) > 0) { - spCaret = SelectionPosition(spCaret.Position() - 1); - } - break; - case Message::CharRight: - case Message::CharRightExtend: - if (FlagSet(virtualSpaceOptions, VirtualSpace::UserAccessible) && pdoc->IsLineEndPosition(spCaret.Position())) { - spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1); - } else { - spCaret = SelectionPosition(spCaret.Position() + 1); - } - break; - case Message::WordLeft: - case Message::WordLeftExtend: - spCaret = SelectionPosition(pdoc->NextWordStart(spCaret.Position(), -1)); - break; - case Message::WordRight: - case Message::WordRightExtend: - spCaret = SelectionPosition(pdoc->NextWordStart(spCaret.Position(), 1)); - break; - case Message::WordLeftEnd: - case Message::WordLeftEndExtend: - spCaret = SelectionPosition(pdoc->NextWordEnd(spCaret.Position(), -1)); - break; - case Message::WordRightEnd: - case Message::WordRightEndExtend: - spCaret = SelectionPosition(pdoc->NextWordEnd(spCaret.Position(), 1)); - break; - case Message::WordPartLeft: - case Message::WordPartLeftExtend: - spCaret = SelectionPosition(pdoc->WordPartLeft(spCaret.Position())); - break; - case Message::WordPartRight: - case Message::WordPartRightExtend: - spCaret = SelectionPosition(pdoc->WordPartRight(spCaret.Position())); - break; - case Message::Home: - case Message::HomeExtend: - spCaret = SelectionPosition(pdoc->LineStartPosition(spCaret.Position())); - break; - case Message::HomeDisplay: - case Message::HomeDisplayExtend: - spCaret = SelectionPosition(StartEndDisplayLine(spCaret.Position(), true)); - break; - case Message::HomeWrap: - case Message::HomeWrapExtend: - spCaret = MovePositionSoVisible(StartEndDisplayLine(spCaret.Position(), true), -1); - if (spCaretNow <= spCaret) - spCaret = SelectionPosition(pdoc->LineStartPosition(spCaret.Position())); - break; - case Message::VCHome: - case Message::VCHomeExtend: - // VCHome alternates between beginning of line and beginning of text so may move back or forwards - spCaret = SelectionPosition(pdoc->VCHomePosition(spCaret.Position())); - break; - case Message::VCHomeDisplay: - case Message::VCHomeDisplayExtend: - spCaret = SelectionPosition(VCHomeDisplayPosition(spCaret.Position())); - break; - case Message::VCHomeWrap: - case Message::VCHomeWrapExtend: - spCaret = SelectionPosition(VCHomeWrapPosition(spCaret.Position())); - break; - case Message::LineEnd: - case Message::LineEndExtend: - spCaret = SelectionPosition(pdoc->LineEndPosition(spCaret.Position())); - break; - case Message::LineEndDisplay: - case Message::LineEndDisplayExtend: - spCaret = SelectionPosition(StartEndDisplayLine(spCaret.Position(), false)); - break; - case Message::LineEndWrap: - case Message::LineEndWrapExtend: - spCaret = SelectionPosition(LineEndWrapPosition(spCaret.Position())); - break; - - default: - PLATFORM_ASSERT(false); - } - - const int directionMove = (spCaret < spCaretNow) ? -1 : 1; - spCaret = MovePositionSoVisible(spCaret, directionMove); - - // Handle move versus extend, and special behaviour for non-empty left/right - switch (iMessage) { - case Message::CharLeft: - case Message::CharRight: - if (sel.Range(r).Empty()) { - sel.Range(r) = SelectionRange(spCaret); - } else { - sel.Range(r) = SelectionRange( - (iMessage == Message::CharLeft) ? sel.Range(r).Start() : sel.Range(r).End()); - } - break; - - case Message::WordLeft: - case Message::WordRight: - case Message::WordLeftEnd: - case Message::WordRightEnd: - case Message::WordPartLeft: - case Message::WordPartRight: - case Message::Home: - case Message::HomeDisplay: - case Message::HomeWrap: - case Message::VCHome: - case Message::VCHomeDisplay: - case Message::VCHomeWrap: - case Message::LineEnd: - case Message::LineEndDisplay: - case Message::LineEndWrap: - sel.Range(r) = SelectionRange(spCaret); - break; - - case Message::CharLeftExtend: - case Message::CharRightExtend: - case Message::WordLeftExtend: - case Message::WordRightExtend: - case Message::WordLeftEndExtend: - case Message::WordRightEndExtend: - case Message::WordPartLeftExtend: - case Message::WordPartRightExtend: - case Message::HomeExtend: - case Message::HomeDisplayExtend: - case Message::HomeWrapExtend: - case Message::VCHomeExtend: - case Message::VCHomeDisplayExtend: - case Message::VCHomeWrapExtend: - case Message::LineEndExtend: - case Message::LineEndDisplayExtend: - case Message::LineEndWrapExtend: { - SelectionRange rangeNew = SelectionRange(spCaret, sel.Range(r).anchor); - sel.TrimOtherSelections(r, SelectionRange(rangeNew)); - sel.Range(r) = rangeNew; - } - break; - - default: - PLATFORM_ASSERT(false); - } + sel.Range(r) = SelectionMove(iMessage, r); } } diff --git a/src/Editor.h b/src/Editor.h index 54ca1110f..8c6458879 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -491,9 +491,12 @@ protected: // ScintillaBase subclass needs access to much of Editor void ParaUpOrDown(int direction, Selection::SelTypes selt); Range RangeDisplayLine(Sci::Line lineVisible); Sci::Position StartEndDisplayLine(Sci::Position pos, bool start); + Sci::Position HomeWrapPosition(Sci::Position position); Sci::Position VCHomeDisplayPosition(Sci::Position position); Sci::Position VCHomeWrapPosition(Sci::Position position); Sci::Position LineEndWrapPosition(Sci::Position position); + SelectionPosition PositionMove(Scintilla::Message iMessage, SelectionPosition spCaretNow); + SelectionRange SelectionMove(Scintilla::Message iMessage, size_t r); int HorizontalMove(Scintilla::Message iMessage); int DelWordOrLine(Scintilla::Message iMessage); virtual int KeyCommand(Scintilla::Message iMessage); diff --git a/src/Selection.h b/src/Selection.h index bc0f2208a..30e1e27ad 100644 --- a/src/Selection.h +++ b/src/Selection.h @@ -49,6 +49,9 @@ public: void Add(Sci::Position increment) noexcept { position = position + increment; } + void AddVirtualSpace(Sci::Position increment) noexcept { + SetVirtualSpace(virtualSpace + increment); + } bool IsValid() const noexcept { return position >= 0; } |