in ext/scintilla/src/Editor.cxx [3365:3608]
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);
}
if (!multipleSelection && !sel.IsRectangular()) {
// Simplify selection down to 1
sel.SetSelection(sel.RangeMain());
}
// Invalidate each of the current selections
InvalidateWholeSelection();
if (IsRectExtend(iMessage, sel.IsRectangular() && sel.MoveExtends())) {
const SelectionRange rangeBase = sel.IsRectangular() ? sel.Rectangular() : sel.RangeMain();
if (!sel.IsRectangular()) {
sel.DropAdditionalRanges();
}
// Will change to rectangular if not currently rectangular
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) {
spCaret = SelectionPosition(spCaret.Position() - 1);
}
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 {
spCaret = SelectionPosition(spCaret.Position() + 1);
}
break;
case SCI_HOMERECTEXTEND:
case SCI_HOMEEXTEND: // only when sel.IsRectangular() && sel.MoveExtends()
spCaret = SelectionPosition(
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;
}
const int directionMove = (spCaret < rangeBase.caret) ? -1 : 1;
spCaret = MovePositionSoVisible(spCaret, directionMove);
sel.selType = Selection::selRectangle;
sel.Rectangular() = SelectionRange(spCaret, rangeBase.anchor);
SetRectangularRange();
} else if (sel.IsRectangular()) {
// Not a rectangular extension so switch to stream.
SelectionPosition selAtLimit = (NaturalDirection(iMessage) > 0) ? sel.Limits().end : sel.Limits().start;
switch (iMessage) {
case SCI_HOME:
selAtLimit = SelectionPosition(
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 {
if (!additionalSelectionTyping) {
InvalidateWholeSelection();
sel.DropAdditionalRanges();
}
for (size_t r = 0; r < sel.Count(); r++) {
const SelectionPosition spCaretNow = sel.Range(r).caret;
SelectionPosition spCaret = spCaretNow;
switch (iMessage) {
case SCI_CHARLEFT:
case SCI_CHARLEFTEXTEND:
if (spCaret.VirtualSpace()) {
spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1);
} else if ((virtualSpaceOptions & SCVS_NOWRAPLINESTART) == 0 || pdoc->GetColumn(spCaret.Position()) > 0) {
spCaret = SelectionPosition(spCaret.Position() - 1);
}
break;
case SCI_CHARRIGHT:
case SCI_CHARRIGHTEXTEND:
if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(spCaret.Position())) {
spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1);
} else {
spCaret = SelectionPosition(spCaret.Position() + 1);
}
break;
case SCI_WORDLEFT:
case SCI_WORDLEFTEXTEND:
spCaret = SelectionPosition(pdoc->NextWordStart(spCaret.Position(), -1));
break;
case SCI_WORDRIGHT:
case SCI_WORDRIGHTEXTEND:
spCaret = SelectionPosition(pdoc->NextWordStart(spCaret.Position(), 1));
break;
case SCI_WORDLEFTEND:
case SCI_WORDLEFTENDEXTEND:
spCaret = SelectionPosition(pdoc->NextWordEnd(spCaret.Position(), -1));
break;
case SCI_WORDRIGHTEND:
case SCI_WORDRIGHTENDEXTEND:
spCaret = SelectionPosition(pdoc->NextWordEnd(spCaret.Position(), 1));
break;
case SCI_WORDPARTLEFT:
case SCI_WORDPARTLEFTEXTEND:
spCaret = SelectionPosition(pdoc->WordPartLeft(spCaret.Position()));
break;
case SCI_WORDPARTRIGHT:
case SCI_WORDPARTRIGHTEXTEND:
spCaret = SelectionPosition(pdoc->WordPartRight(spCaret.Position()));
break;
case SCI_HOME:
case SCI_HOMEEXTEND:
spCaret = SelectionPosition(
pdoc->LineStart(pdoc->LineFromPosition(spCaret.Position())));
break;
case SCI_HOMEDISPLAY:
case SCI_HOMEDISPLAYEXTEND:
spCaret = SelectionPosition(StartEndDisplayLine(spCaret.Position(), true));
break;
case SCI_HOMEWRAP:
case SCI_HOMEWRAPEXTEND:
spCaret = MovePositionSoVisible(StartEndDisplayLine(spCaret.Position(), true), -1);
if (spCaretNow <= spCaret)
spCaret = SelectionPosition(
pdoc->LineStart(pdoc->LineFromPosition(spCaret.Position())));
break;
case SCI_VCHOME:
case SCI_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 SCI_VCHOMEDISPLAY:
case SCI_VCHOMEDISPLAYEXTEND:
spCaret = SelectionPosition(VCHomeDisplayPosition(spCaret.Position()));
break;
case SCI_VCHOMEWRAP:
case SCI_VCHOMEWRAPEXTEND:
spCaret = SelectionPosition(VCHomeWrapPosition(spCaret.Position()));
break;
case SCI_LINEEND:
case SCI_LINEENDEXTEND:
spCaret = SelectionPosition(pdoc->LineEndPosition(spCaret.Position()));
break;
case SCI_LINEENDDISPLAY:
case SCI_LINEENDDISPLAYEXTEND:
spCaret = SelectionPosition(StartEndDisplayLine(spCaret.Position(), false));
break;
case SCI_LINEENDWRAP:
case SCI_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 SCI_CHARLEFT:
case SCI_CHARRIGHT:
if (sel.Range(r).Empty()) {
sel.Range(r) = SelectionRange(spCaret);
} else {
sel.Range(r) = SelectionRange(
(iMessage == SCI_CHARLEFT) ? sel.Range(r).Start() : sel.Range(r).End());
}
break;
case SCI_WORDLEFT:
case SCI_WORDRIGHT:
case SCI_WORDLEFTEND:
case SCI_WORDRIGHTEND:
case SCI_WORDPARTLEFT:
case SCI_WORDPARTRIGHT:
case SCI_HOME:
case SCI_HOMEDISPLAY:
case SCI_HOMEWRAP:
case SCI_VCHOME:
case SCI_VCHOMEDISPLAY:
case SCI_VCHOMEWRAP:
case SCI_LINEEND:
case SCI_LINEENDDISPLAY:
case SCI_LINEENDWRAP:
sel.Range(r) = SelectionRange(spCaret);
break;
case SCI_CHARLEFTEXTEND:
case SCI_CHARRIGHTEXTEND:
case SCI_WORDLEFTEXTEND:
case SCI_WORDRIGHTEXTEND:
case SCI_WORDLEFTENDEXTEND:
case SCI_WORDRIGHTENDEXTEND:
case SCI_WORDPARTLEFTEXTEND:
case SCI_WORDPARTRIGHTEXTEND:
case SCI_HOMEEXTEND:
case SCI_HOMEDISPLAYEXTEND:
case SCI_HOMEWRAPEXTEND:
case SCI_VCHOMEEXTEND:
case SCI_VCHOMEDISPLAYEXTEND:
case SCI_VCHOMEWRAPEXTEND:
case SCI_LINEENDEXTEND:
case SCI_LINEENDDISPLAYEXTEND:
case SCI_LINEENDWRAPEXTEND: {
SelectionRange rangeNew = SelectionRange(spCaret, sel.Range(r).anchor);
sel.TrimOtherSelections(r, SelectionRange(rangeNew));
sel.Range(r) = rangeNew;
}
break;
default:
PLATFORM_ASSERT(false);
}
}
}
sel.RemoveDuplicates();
MovedCaret(sel.RangeMain().caret, SelectionPosition(INVALID_POSITION), true);
// Invalidate the new state of the selection
InvalidateWholeSelection();
SetLastXChosen();
// Need the line moving and so forth from MovePositionTo
return 0;
}