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