int Editor::HorizontalMove()

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;
}