diff options
| -rw-r--r-- | doc/ScintillaDoc.html | 11 | ||||
| -rw-r--r-- | doc/ScintillaHistory.html | 15 | ||||
| -rw-r--r-- | src/Editor.cxx | 873 | ||||
| -rw-r--r-- | src/Editor.h | 7 | ||||
| -rw-r--r-- | src/Selection.cxx | 8 | ||||
| -rw-r--r-- | src/Selection.h | 1 | 
6 files changed, 577 insertions, 338 deletions
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html index 080cea361..154747cc5 100644 --- a/doc/ScintillaDoc.html +++ b/doc/ScintillaDoc.html @@ -1646,6 +1646,9 @@ struct Sci_TextToFind {      Any selection apart from the main selection is called an additional selection.      The calls in the previous section operate on the main selection.      There is always at least one selection. +    The selection can be simplified down to just the main selection by +    <a class="message" href="#SCI_CANCEL"><code>SCI_CANCEL</code></a> +    which is normally mapped to the Esc key.      </p>      <p> @@ -1673,7 +1676,9 @@ struct Sci_TextToFind {      <p>      <b id="SCI_SETADDITIONALSELECTIONTYPING">SCI_SETADDITIONALSELECTIONTYPING(bool additionalSelectionTyping)</b><br />      <b id="SCI_GETADDITIONALSELECTIONTYPING">SCI_GETADDITIONALSELECTIONTYPING</b><br /> -     Whether typing, backspace, or delete works with multiple selections simultaneously.</p> +     Whether typing, new line, cursor left/right/up/down, backspace, delete, home, and end work +     with multiple selections simultaneously. +     Also allows selection and word and line deletion commands.</p>      <p>      <b id="SCI_SETMULTIPASTE">SCI_SETMULTIPASTE(int multiPaste)</b><br /> @@ -4967,6 +4972,10 @@ struct Sci_TextToFind {      by binding the <code>home</code> and <code>end</code> keys to these commands.       </p> +    <p class="message" id="SCI_CANCEL">The <code>SCI_CANCEL</code> command cancels autocompletion and +    calltip display and drops any additional selections. +     </p> +      <h2 id="KeyBindings">Key bindings</h2>      <p>There is a default binding of keys to commands that is defined in the Scintilla source in diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html index 3529c188b..bf198b900 100644 --- a/doc/ScintillaHistory.html +++ b/doc/ScintillaHistory.html @@ -484,6 +484,21 @@        </li>      </ul>      <h3> +       <a href="http://prdownloads.sourceforge.net/scintilla/scite360.zip?download">Release 3.6.0</a> +    </h3> +    <ul> +	<li> +	Released 20 June 2015. +	</li> +	<li> +	Multiple selection now works over more key commands. +	The new multiple-selection handling commands include horizontal movement and selection commands, +	line up and down movement and selection commands, word and line deletion commands, and +	line end insertion. +	This change in behaviours is conditional on setting the SCI_SETADDITIONALSELECTIONTYPING property. +	</li> +    </ul> +    <h3>         <a href="http://prdownloads.sourceforge.net/scintilla/scite357.zip?download">Release 3.5.7</a>      </h3>      <ul> diff --git a/src/Editor.cxx b/src/Editor.cxx index 9e57cb0bc..a3f9e1845 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -803,9 +803,37 @@ SelectionPosition Editor::MovePositionOutsideChar(SelectionPosition pos, int mov  	return pos;  } +void Editor::MovedCaret(SelectionPosition newPos, SelectionPosition previousPos, bool ensureVisible) { +	const int currentLine = pdoc->LineFromPosition(newPos.Position()); +	if (ensureVisible) { +		// In case in need of wrapping to ensure DisplayFromDoc works. +		if (currentLine >= wrapPending.start) +			WrapLines(wsAll); +		XYScrollPosition newXY = XYScrollToMakeVisible( +			SelectionRange(posDrag.IsValid() ? posDrag : newPos), xysDefault); +		if (previousPos.IsValid() && (newXY.xOffset == xOffset)) { +			// simple vertical scroll then invalidate +			ScrollTo(newXY.topLine); +			InvalidateSelection(SelectionRange(previousPos), true); +		} else { +			SetXYScroll(newXY); +		} +	} + +	ShowCaretAtCurrentPosition(); + +	ClaimSelection(); +	SetHoverIndicatorPosition(sel.MainCaret()); +	QueueIdleWork(WorkNeeded::workUpdateUI); + +	if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { +		RedrawSelMargin(); +	} +} +  void Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, bool ensureVisible) { -	const bool simpleCaret = (sel.Count() == 1) && sel.Empty(); -	const SelectionPosition spCaret = sel.Last(); +	const SelectionPosition spCaret = ((sel.Count() == 1) && sel.Empty()) ? +		sel.Last() : SelectionPosition(INVALID_POSITION);  	int delta = newPos.Position() - sel.MainCaret();  	newPos = ClampPositionIntoDocument(newPos); @@ -830,27 +858,8 @@ void Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt,  	} else {  		SetEmptySelection(newPos);  	} -	ShowCaretAtCurrentPosition(); -	const int currentLine = pdoc->LineFromPosition(newPos.Position()); -	if (ensureVisible) { -		// In case in need of wrapping to ensure DisplayFromDoc works. -		if (currentLine >= wrapPending.start) -			WrapLines(wsAll); -		XYScrollPosition newXY = XYScrollToMakeVisible( -			SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), xysDefault); -		if (simpleCaret && (newXY.xOffset == xOffset)) { -			// simple vertical scroll then invalidate -			ScrollTo(newXY.topLine); -			InvalidateSelection(SelectionRange(spCaret), true); -		} else { -			SetXYScroll(newXY); -		} -	} - -	if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { -		RedrawSelMargin(); -	} +	MovedCaret(newPos, spCaret, ensureVisible);  }  void Editor::MovePositionTo(int newPos, Selection::selTypes selt, bool ensureVisible) { @@ -2952,30 +2961,36 @@ void Editor::CancelModes() {  }  void Editor::NewLine() { -	// Remove non-main ranges  	InvalidateWholeSelection(); -	sel.DropAdditionalRanges(); -	sel.RangeMain().ClearVirtualSpace(); +	if (sel.IsRectangular() || !additionalSelectionTyping) { +		// Remove non-main ranges +		sel.DropAdditionalRanges(); +	} -	// Clear main range and insert line end -	bool needGroupUndo = !sel.Empty(); -	if (needGroupUndo) -		pdoc->BeginUndoAction(); +	UndoGroup ug(pdoc, !sel.Empty() || (sel.Count() > 1)); -	if (!sel.Empty()) +	// Clear each range +	if (!sel.Empty()) {  		ClearSelection(); -	const char *eol = "\n"; -	if (pdoc->eolMode == SC_EOL_CRLF) { -		eol = "\r\n"; -	} else if (pdoc->eolMode == SC_EOL_CR) { -		eol = "\r"; -	} // else SC_EOL_LF -> "\n" already set -	const int insertLength = pdoc->InsertString(sel.MainCaret(), eol, istrlen(eol)); -	// Want to end undo group before NotifyChar as applications often modify text here -	if (needGroupUndo) -		pdoc->EndUndoAction(); -	if (insertLength > 0) { -		SetEmptySelection(sel.MainCaret() + insertLength); +	} + +	// Insert each line end +	size_t countInsertions = 0; +	for (size_t r = 0; r < sel.Count(); r++) { +		sel.Range(r).ClearVirtualSpace(); +		const char *eol = StringFromEOLMode(pdoc->eolMode); +		const int positionInsert = sel.Range(r).caret.Position(); +		const int insertLength = pdoc->InsertString(positionInsert, eol, istrlen(eol)); +		if (insertLength > 0) { +			sel.Range(r) = SelectionRange(positionInsert + insertLength); +			countInsertions++; +		} +	} + +	// Perform notifications after all the changes as the application may change the +	// selections in response to the characters. +	for (size_t i = 0; i < countInsertions; i++) { +		const char *eol = StringFromEOLMode(pdoc->eolMode);  		while (*eol) {  			NotifyChar(*eol);  			if (recordingMacro) { @@ -2987,6 +3002,7 @@ void Editor::NewLine() {  			eol++;  		}  	} +  	SetLastXChosen();  	SetScrollBars();  	EnsureCaretVisible(); @@ -2994,26 +3010,17 @@ void Editor::NewLine() {  	ShowCaretAtCurrentPosition();  } -void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) { -	SelectionPosition caretToUse = sel.Range(sel.Main()).caret; -	if (sel.IsRectangular()) { -		if (selt ==  Selection::noSel) { -			caretToUse = (direction > 0) ? sel.Limits().end : sel.Limits().start; -		} else { -			caretToUse = sel.Rectangular().caret; -		} -	} - -	Point pt = LocationFromPosition(caretToUse); +SelectionPosition Editor::PositionUpOrDown(SelectionPosition spStart, int direction, int lastX) { +	const Point pt = LocationFromPosition(spStart);  	int skipLines = 0;  	if (vs.annotationVisible) { -		int lineDoc = pdoc->LineFromPosition(caretToUse.Position()); -		Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc)); -		int subLine = static_cast<int>(pt.y - ptStartLine.y) / vs.lineHeight; +		const int lineDoc = pdoc->LineFromPosition(spStart.Position()); +		const Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc)); +		const int subLine = static_cast<int>(pt.y - ptStartLine.y) / vs.lineHeight;  		if (direction < 0 && subLine == 0) { -			int lineDisplay = cs.DisplayFromDoc(lineDoc); +			const int lineDisplay = cs.DisplayFromDoc(lineDoc);  			if (lineDisplay > 0) {  				skipLines = pdoc->AnnotationLines(cs.DocFromDisplay(lineDisplay - 1));  			} @@ -3022,9 +3029,12 @@ void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) {  		}  	} -	int newY = static_cast<int>(pt.y) + (1 + skipLines) * direction * vs.lineHeight; +	const int newY = static_cast<int>(pt.y) + (1 + skipLines) * direction * vs.lineHeight; +	if (lastX < 0) { +		lastX = static_cast<int>(pt.x) + xOffset; +	}  	SelectionPosition posNew = SPositionFromLocation( -	            Point::FromInts(lastXChosen - xOffset, newY), false, false, UserVirtualSpace()); +		Point::FromInts(lastX - xOffset, newY), false, false, UserVirtualSpace());  	if (direction < 0) {  		// Line wrapping may lead to a location on the same line, so @@ -3039,14 +3049,53 @@ void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) {  		// There is an equivalent case when moving down which skips  		// over a line.  		Point ptNew = LocationFromPosition(posNew.Position()); -		while ((posNew.Position() > caretToUse.Position()) && (ptNew.y > newY)) { +		while ((posNew.Position() > spStart.Position()) && (ptNew.y > newY)) {  			posNew.Add(-1);  			posNew.SetVirtualSpace(0);  			ptNew = LocationFromPosition(posNew.Position());  		}  	} +	return posNew; +} -	MovePositionTo(MovePositionSoVisible(posNew, direction), selt); +void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) { +	SelectionPosition caretToUse = sel.Range(sel.Main()).caret; +	if (sel.IsRectangular()) { +		if (selt ==  Selection::noSel) { +			caretToUse = (direction > 0) ? sel.Limits().end : sel.Limits().start; +		} else { +			caretToUse = sel.Rectangular().caret; +		} +	} +	if (selt == Selection::selRectangle) { +		const SelectionRange rangeBase = sel.IsRectangular() ? sel.Rectangular() : sel.RangeMain(); +		if (!sel.IsRectangular()) { +			InvalidateWholeSelection(); +			sel.DropAdditionalRanges(); +		} +		const SelectionPosition posNew = MovePositionSoVisible( +			PositionUpOrDown(caretToUse, direction, lastXChosen), direction); +		sel.selType = Selection::selRectangle; +		sel.Rectangular() = SelectionRange(posNew, rangeBase.anchor); +		SetRectangularRange(); +		MovedCaret(posNew, caretToUse, true); +	} else { +		if (!additionalSelectionTyping || (sel.IsRectangular())) { +			InvalidateWholeSelection(); +			sel.DropAdditionalRanges(); +		} +		sel.selType = Selection::selStream; +		for (size_t r = 0; r < sel.Count(); r++) { +			const int lastX = (r == sel.Main()) ? lastXChosen : -1; +			const SelectionPosition spCaretNow = sel.Range(r).caret; +			const SelectionPosition posNew = MovePositionSoVisible( +				PositionUpOrDown(spCaretNow, direction, lastX), direction); +			sel.Range(r) = selt == Selection::selStream ?  +				SelectionRange(posNew, sel.Range(r).anchor) : SelectionRange(posNew); +		} +		sel.RemoveDuplicates(); +		MovedCaret(sel.RangeMain().caret, caretToUse, true); +	}  }  void Editor::ParaUpOrDown(int direction, Selection::selTypes selt) { @@ -3076,6 +3125,402 @@ int Editor::StartEndDisplayLine(int pos, bool start) {  	}  } +namespace { + +unsigned int WithExtends(unsigned int iMessage) { +	switch (iMessage) { +	case SCI_CHARLEFT: return SCI_CHARLEFTEXTEND; +	case SCI_CHARRIGHT: return SCI_CHARRIGHTEXTEND; + +	case SCI_WORDLEFT: return SCI_WORDLEFTEXTEND; +	case SCI_WORDRIGHT: return SCI_WORDRIGHTEXTEND; +	case SCI_WORDLEFTEND: return SCI_WORDLEFTENDEXTEND; +	case SCI_WORDRIGHTEND: return SCI_WORDRIGHTENDEXTEND; +	case SCI_WORDPARTLEFT: return SCI_WORDPARTLEFTEXTEND; +	case SCI_WORDPARTRIGHT: return SCI_WORDPARTRIGHTEXTEND; + +	case SCI_HOME: return SCI_HOMEEXTEND; +	case SCI_HOMEDISPLAY: return SCI_HOMEDISPLAYEXTEND; +	case SCI_HOMEWRAP: return SCI_HOMEWRAPEXTEND; +	case SCI_VCHOME: return SCI_VCHOMEEXTEND; +	case SCI_VCHOMEDISPLAY: return SCI_VCHOMEDISPLAYEXTEND; +	case SCI_VCHOMEWRAP: return SCI_VCHOMEWRAPEXTEND; + +	case SCI_LINEEND: return SCI_LINEENDEXTEND; +	case SCI_LINEENDDISPLAY: return SCI_LINEENDDISPLAYEXTEND; +	case SCI_LINEENDWRAP: return SCI_LINEENDWRAPEXTEND; + +	default:	return iMessage; +	} +} + +int NaturalDirection(unsigned int iMessage) { +	switch (iMessage) { +	case SCI_CHARLEFT: +	case SCI_CHARLEFTEXTEND: +	case SCI_CHARLEFTRECTEXTEND: +	case SCI_WORDLEFT: +	case SCI_WORDLEFTEXTEND: +	case SCI_WORDLEFTEND: +	case SCI_WORDLEFTENDEXTEND: +	case SCI_WORDPARTLEFT: +	case SCI_WORDPARTLEFTEXTEND: +	case SCI_HOME: +	case SCI_HOMEEXTEND: +	case SCI_HOMEDISPLAY: +	case SCI_HOMEDISPLAYEXTEND: +	case SCI_HOMEWRAP: +	case SCI_HOMEWRAPEXTEND: +		// VC_HOME* mostly goes back +	case SCI_VCHOME: +	case SCI_VCHOMEEXTEND: +	case SCI_VCHOMEDISPLAY: +	case SCI_VCHOMEDISPLAYEXTEND: +	case SCI_VCHOMEWRAP: +	case SCI_VCHOMEWRAPEXTEND: +		return -1; + +	default: +		return 1; +	} +} + +bool IsRectExtend(unsigned int iMessage) { +	switch (iMessage) { +	case SCI_CHARLEFTRECTEXTEND: +	case SCI_CHARRIGHTRECTEXTEND: +	case SCI_HOMERECTEXTEND: +	case SCI_VCHOMERECTEXTEND: +	case SCI_LINEENDRECTEXTEND: +		return true; +	default: +		return false; +	} +} + +} + +int Editor::VCHomeDisplayPosition(int position) { +	const int homePos = pdoc->VCHomePosition(position); +	const int viewLineStart = StartEndDisplayLine(position, true); +	if (viewLineStart > homePos) +		return viewLineStart; +	else +		return homePos; +} + +int Editor::VCHomeWrapPosition(int position) { +	const int homePos = pdoc->VCHomePosition(position); +	const int viewLineStart = StartEndDisplayLine(position, true); +	if ((viewLineStart < position) && (viewLineStart > homePos)) +		return viewLineStart; +	else +		return homePos; +} + +int Editor::LineEndWrapPosition(int position) { +	const int endPos = StartEndDisplayLine(position, false); +	const int realEndPos = pdoc->LineEndPosition(position); +	if (endPos > realEndPos      // if moved past visible EOLs +		|| position >= endPos) // if at end of display line already +		return realEndPos; +	else +		return endPos; +} + +int Editor::HorizontalMove(unsigned int iMessage) { +	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)) { +		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: +			if (pdoc->IsLineEndPosition(spCaret.Position()) && spCaret.VirtualSpace()) { +				spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1); +			} else { +				spCaret = SelectionPosition(spCaret.Position() - 1); +			} +			break; +		case SCI_CHARRIGHTRECTEXTEND: +			if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) && pdoc->IsLineEndPosition(sel.MainCaret())) { +				spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1); +			} else { +				spCaret = SelectionPosition(spCaret.Position() + 1); +			} +			break; +		case SCI_HOMERECTEXTEND: +			spCaret = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(spCaret.Position()))); +			break; +		case SCI_VCHOMERECTEXTEND: +			spCaret = SelectionPosition(pdoc->VCHomePosition(spCaret.Position())); +			break; +		case SCI_LINEENDRECTEXTEND: +			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; +			sel.selType = Selection::selStream; +			sel.SetSelection(SelectionRange(selAtLimit)); +		} +		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 { +					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-emoty 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; +} + +int Editor::DelWordOrLine(unsigned int iMessage) { +	// Virtual space may be realised for SCI_DELWORDRIGHT or SCI_DELWORDRIGHTEND +	// which means 2 actions so wrap in an undo group. + +	// Rightwards and leftwards deletions differ in treatment of virtual space. +	// Clear virtual space for leftwards, realise for rightwards.  +	const bool leftwards = (iMessage == SCI_DELWORDLEFT) || (iMessage == SCI_DELLINELEFT); + +	if (!additionalSelectionTyping) { +		InvalidateWholeSelection(); +		sel.DropAdditionalRanges(); +	} + +	UndoGroup ug0(pdoc, (sel.Count() > 1) || !leftwards); + +	for (size_t r = 0; r < sel.Count(); r++) { +		if (leftwards) { +			// Delete to the left so first clear the virtual space. +			sel.Range(r).ClearVirtualSpace(); +		} else { +			// Delete to the right so first realise the virtual space. +			sel.Range(r) = SelectionRange( +				InsertSpace(sel.Range(r).caret.Position(), sel.Range(r).caret.VirtualSpace())); +		} +		 +		Range rangeDelete; +		switch (iMessage) { +		case SCI_DELWORDLEFT: +			rangeDelete = Range( +				pdoc->NextWordStart(sel.Range(r).caret.Position(), -1), +				sel.Range(r).caret.Position()); +			break; +		case SCI_DELWORDRIGHT: +			rangeDelete = Range( +				sel.Range(r).caret.Position(), +				pdoc->NextWordStart(sel.Range(r).caret.Position(), 1)); +			break; +		case SCI_DELWORDRIGHTEND: +			rangeDelete = Range( +				sel.Range(r).caret.Position(), +				pdoc->NextWordEnd(sel.Range(r).caret.Position(), 1)); +			break; +		case SCI_DELLINELEFT: +			rangeDelete = Range( +				pdoc->LineStart(pdoc->LineFromPosition(sel.Range(r).caret.Position())), +				sel.Range(r).caret.Position()); +			break; +		case SCI_DELLINERIGHT: +			rangeDelete = Range( +				sel.Range(r).caret.Position(), +				pdoc->LineEnd(pdoc->LineFromPosition(sel.Range(r).caret.Position()))); +			break; +		} +		if (!RangeContainsProtected(rangeDelete.start, rangeDelete.end)) { +			pdoc->DeleteChars(rangeDelete.start, rangeDelete.end - rangeDelete.start); +		} +	} + +	// May need something stronger here: can selections overlap at this point? +	sel.RemoveDuplicates(); + +	MovedCaret(sel.RangeMain().caret, SelectionPosition(INVALID_POSITION), true); + +	// Invalidate the new state of the selection +	InvalidateWholeSelection(); + +	SetLastXChosen(); +	return 0; +} +  int Editor::KeyCommand(unsigned int iMessage) {  	switch (iMessage) {  	case SCI_LINEDOWN: @@ -3116,174 +3561,48 @@ int Editor::KeyCommand(unsigned int iMessage) {  		ScrollTo(topLine - 1);  		MoveCaretInsideView(false);  		break; +  	case SCI_CHARLEFT: -		if (SelectionEmpty() || sel.MoveExtends()) { -			if ((sel.Count() == 1) && pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) { -				SelectionPosition spCaret = sel.RangeMain().caret; -				spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1); -				MovePositionTo(spCaret); -			} else if (sel.MoveExtends() && sel.selType == Selection::selStream) { -				MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1)); -			} else { -				MovePositionTo(MovePositionSoVisible( -					SelectionPosition((sel.LimitsForRectangularElseMain().start).Position() - 1), -1)); -			} -		} else { -			MovePositionTo(sel.LimitsForRectangularElseMain().start); -		} -		SetLastXChosen(); -		break;  	case SCI_CHARLEFTEXTEND: -		if (pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) { -			SelectionPosition spCaret = sel.RangeMain().caret; -			spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1); -			MovePositionTo(spCaret, Selection::selStream); -		} else { -			MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1), Selection::selStream); -		} -		SetLastXChosen(); -		break;  	case SCI_CHARLEFTRECTEXTEND: -		if (pdoc->IsLineEndPosition(sel.MainCaret()) && sel.RangeMain().caret.VirtualSpace()) { -			SelectionPosition spCaret = sel.RangeMain().caret; -			spCaret.SetVirtualSpace(spCaret.VirtualSpace() - 1); -			MovePositionTo(spCaret, Selection::selRectangle); -		} else { -			MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() - 1), -1), Selection::selRectangle); -		} -		SetLastXChosen(); -		break;  	case SCI_CHARRIGHT: -		if (SelectionEmpty() || sel.MoveExtends()) { -			if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(sel.MainCaret())) { -				SelectionPosition spCaret = sel.RangeMain().caret; -				spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1); -				MovePositionTo(spCaret); -			} else if (sel.MoveExtends() && sel.selType == Selection::selStream) { -				MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1)); -			} else { -				MovePositionTo(MovePositionSoVisible( -					SelectionPosition((sel.LimitsForRectangularElseMain().end).Position() + 1), 1)); -			} -		} else { -			MovePositionTo(sel.LimitsForRectangularElseMain().end); -		} -		SetLastXChosen(); -		break;  	case SCI_CHARRIGHTEXTEND: -		if ((virtualSpaceOptions & SCVS_USERACCESSIBLE) && pdoc->IsLineEndPosition(sel.MainCaret())) { -			SelectionPosition spCaret = sel.RangeMain().caret; -			spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1); -			MovePositionTo(spCaret, Selection::selStream); -		} else { -			MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1), Selection::selStream); -		} -		SetLastXChosen(); -		break;  	case SCI_CHARRIGHTRECTEXTEND: -		if ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) && pdoc->IsLineEndPosition(sel.MainCaret())) { -			SelectionPosition spCaret = sel.RangeMain().caret; -			spCaret.SetVirtualSpace(spCaret.VirtualSpace() + 1); -			MovePositionTo(spCaret, Selection::selRectangle); -		} else { -			MovePositionTo(MovePositionSoVisible(SelectionPosition(sel.MainCaret() + 1), 1), Selection::selRectangle); -		} -		SetLastXChosen(); -		break;  	case SCI_WORDLEFT: -		MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), -1), -1)); -		SetLastXChosen(); -		break;  	case SCI_WORDLEFTEXTEND: -		MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), -1), -1), Selection::selStream); -		SetLastXChosen(); -		break;  	case SCI_WORDRIGHT: -		MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), 1), 1)); -		SetLastXChosen(); -		break;  	case SCI_WORDRIGHTEXTEND: -		MovePositionTo(MovePositionSoVisible(pdoc->NextWordStart(sel.MainCaret(), 1), 1), Selection::selStream); -		SetLastXChosen(); -		break; -  	case SCI_WORDLEFTEND: -		MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), -1), -1)); -		SetLastXChosen(); -		break;  	case SCI_WORDLEFTENDEXTEND: -		MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), -1), -1), Selection::selStream); -		SetLastXChosen(); -		break;  	case SCI_WORDRIGHTEND: -		MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), 1), 1)); -		SetLastXChosen(); -		break;  	case SCI_WORDRIGHTENDEXTEND: -		MovePositionTo(MovePositionSoVisible(pdoc->NextWordEnd(sel.MainCaret(), 1), 1), Selection::selStream); -		SetLastXChosen(); -		break; - +	case SCI_WORDPARTLEFT: +	case SCI_WORDPARTLEFTEXTEND: +	case SCI_WORDPARTRIGHT: +	case SCI_WORDPARTRIGHTEXTEND:  	case SCI_HOME: -		MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret()))); -		SetLastXChosen(); -		break;  	case SCI_HOMEEXTEND: -		MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())), Selection::selStream); -		SetLastXChosen(); -		break;  	case SCI_HOMERECTEXTEND: -		MovePositionTo(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret())), Selection::selRectangle); -		SetLastXChosen(); -		break; +	case SCI_HOMEDISPLAY: +	case SCI_HOMEDISPLAYEXTEND: +	case SCI_HOMEWRAP: +	case SCI_HOMEWRAPEXTEND: +	case SCI_VCHOME: +	case SCI_VCHOMEEXTEND: +	case SCI_VCHOMERECTEXTEND: +	case SCI_VCHOMEDISPLAY: +	case SCI_VCHOMEDISPLAYEXTEND: +	case SCI_VCHOMEWRAP: +	case SCI_VCHOMEWRAPEXTEND:  	case SCI_LINEEND: -		MovePositionTo(pdoc->LineEndPosition(sel.MainCaret())); -		SetLastXChosen(); -		break;  	case SCI_LINEENDEXTEND: -		MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()), Selection::selStream); -		SetLastXChosen(); -		break;  	case SCI_LINEENDRECTEXTEND: -		MovePositionTo(pdoc->LineEndPosition(sel.MainCaret()), Selection::selRectangle); -		SetLastXChosen(); -		break; -	case SCI_HOMEWRAP: { -			SelectionPosition homePos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1); -			if (sel.RangeMain().caret <= homePos) -				homePos = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret()))); -			MovePositionTo(homePos); -			SetLastXChosen(); -		} -		break; -	case SCI_HOMEWRAPEXTEND: { -			SelectionPosition homePos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1); -			if (sel.RangeMain().caret <= homePos) -				homePos = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(sel.MainCaret()))); -			MovePositionTo(homePos, Selection::selStream); -			SetLastXChosen(); -		} -		break; -	case SCI_LINEENDWRAP: { -			SelectionPosition endPos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), false), 1); -			SelectionPosition realEndPos = SelectionPosition(pdoc->LineEndPosition(sel.MainCaret())); -			if (endPos > realEndPos      // if moved past visible EOLs -			        || sel.RangeMain().caret >= endPos) // if at end of display line already -				endPos = realEndPos; -			MovePositionTo(endPos); -			SetLastXChosen(); -		} -		break; -	case SCI_LINEENDWRAPEXTEND: { -			SelectionPosition endPos = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), false), 1); -			SelectionPosition realEndPos = SelectionPosition(pdoc->LineEndPosition(sel.MainCaret())); -			if (endPos > realEndPos      // if moved past visible EOLs -			        || sel.RangeMain().caret >= endPos) // if at end of display line already -				endPos = realEndPos; -			MovePositionTo(endPos, Selection::selStream); -			SetLastXChosen(); -		} -		break; +	case SCI_LINEENDDISPLAY: +	case SCI_LINEENDDISPLAYEXTEND: +	case SCI_LINEENDWRAP: +	case SCI_LINEENDWRAPEXTEND: +		return HorizontalMove(iMessage); +  	case SCI_DOCUMENTSTART:  		MovePositionTo(0);  		SetLastXChosen(); @@ -3381,38 +3700,6 @@ int Editor::KeyCommand(unsigned int iMessage) {  	case SCI_FORMFEED:  		AddChar('\f');  		break; -	case SCI_VCHOME: -		MovePositionTo(pdoc->VCHomePosition(sel.MainCaret())); -		SetLastXChosen(); -		break; -	case SCI_VCHOMEEXTEND: -		MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()), Selection::selStream); -		SetLastXChosen(); -		break; -	case SCI_VCHOMERECTEXTEND: -		MovePositionTo(pdoc->VCHomePosition(sel.MainCaret()), Selection::selRectangle); -		SetLastXChosen(); -		break; -	case SCI_VCHOMEWRAP: { -			SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret())); -			SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1); -			if ((viewLineStart < sel.RangeMain().caret) && (viewLineStart > homePos)) -				homePos = viewLineStart; - -			MovePositionTo(homePos); -			SetLastXChosen(); -		} -		break; -	case SCI_VCHOMEWRAPEXTEND: { -			SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret())); -			SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1); -			if ((viewLineStart < sel.RangeMain().caret) && (viewLineStart > homePos)) -				homePos = viewLineStart; - -			MovePositionTo(homePos, Selection::selStream); -			SetLastXChosen(); -		} -		break;  	case SCI_ZOOMIN:  		if (vs.zoomLevel < 20) {  			vs.zoomLevel++; @@ -3427,46 +3714,14 @@ int Editor::KeyCommand(unsigned int iMessage) {  			NotifyZoom();  		}  		break; -	case SCI_DELWORDLEFT: { -			int startWord = pdoc->NextWordStart(sel.MainCaret(), -1); -			pdoc->DeleteChars(startWord, sel.MainCaret() - startWord); -			sel.RangeMain().ClearVirtualSpace(); -			SetLastXChosen(); -		} -		break; -	case SCI_DELWORDRIGHT: { -			UndoGroup ug(pdoc); -			InvalidateWholeSelection(); -			sel.RangeMain().caret = SelectionPosition( -				InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace())); -			sel.RangeMain().anchor = sel.RangeMain().caret; -			int endWord = pdoc->NextWordStart(sel.MainCaret(), 1); -			pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret()); -		} -		break; -	case SCI_DELWORDRIGHTEND: { -			UndoGroup ug(pdoc); -			InvalidateWholeSelection(); -			sel.RangeMain().caret = SelectionPosition( -				InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace())); -			int endWord = pdoc->NextWordEnd(sel.MainCaret(), 1); -			pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret()); -		} -		break; -	case SCI_DELLINELEFT: { -			int line = pdoc->LineFromPosition(sel.MainCaret()); -			int start = pdoc->LineStart(line); -			pdoc->DeleteChars(start, sel.MainCaret() - start); -			sel.RangeMain().ClearVirtualSpace(); -			SetLastXChosen(); -		} -		break; -	case SCI_DELLINERIGHT: { -			int line = pdoc->LineFromPosition(sel.MainCaret()); -			int end = pdoc->LineEnd(line); -			pdoc->DeleteChars(sel.MainCaret(), end - sel.MainCaret()); -		} -		break; + +	case SCI_DELWORDLEFT: +	case SCI_DELWORDRIGHT: +	case SCI_DELWORDRIGHTEND: +	case SCI_DELLINELEFT: +	case SCI_DELLINERIGHT: +		return DelWordOrLine(iMessage); +  	case SCI_LINECOPY: {  			int lineStart = pdoc->LineFromPosition(SelectionStart().Position());  			int lineEnd = pdoc->LineFromPosition(SelectionEnd().Position()); @@ -3506,62 +3761,6 @@ int Editor::KeyCommand(unsigned int iMessage) {  	case SCI_UPPERCASE:  		ChangeCaseOfSelection(cmUpper);  		break; -	case SCI_WORDPARTLEFT: -		MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1)); -		SetLastXChosen(); -		break; -	case SCI_WORDPARTLEFTEXTEND: -		MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1), Selection::selStream); -		SetLastXChosen(); -		break; -	case SCI_WORDPARTRIGHT: -		MovePositionTo(MovePositionSoVisible(pdoc->WordPartRight(sel.MainCaret()), 1)); -		SetLastXChosen(); -		break; -	case SCI_WORDPARTRIGHTEXTEND: -		MovePositionTo(MovePositionSoVisible(pdoc->WordPartRight(sel.MainCaret()), 1), Selection::selStream); -		SetLastXChosen(); -		break; -	case SCI_HOMEDISPLAY: -		MovePositionTo(MovePositionSoVisible( -		            StartEndDisplayLine(sel.MainCaret(), true), -1)); -		SetLastXChosen(); -		break; -	case SCI_VCHOMEDISPLAY: { -			SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret())); -			SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1); -			if (viewLineStart > homePos) -				homePos = viewLineStart; - -			MovePositionTo(homePos); -			SetLastXChosen(); -		} -		break; -	case SCI_HOMEDISPLAYEXTEND: -		MovePositionTo(MovePositionSoVisible( -		            StartEndDisplayLine(sel.MainCaret(), true), -1), Selection::selStream); -		SetLastXChosen(); -		break; -	case SCI_VCHOMEDISPLAYEXTEND: { -			SelectionPosition homePos = SelectionPosition(pdoc->VCHomePosition(sel.MainCaret())); -			SelectionPosition viewLineStart = MovePositionSoVisible(StartEndDisplayLine(sel.MainCaret(), true), -1); -			if (viewLineStart > homePos) -				homePos = viewLineStart; - -			MovePositionTo(homePos, Selection::selStream); -			SetLastXChosen(); -		} -		break; -	case SCI_LINEENDDISPLAY: -		MovePositionTo(MovePositionSoVisible( -		            StartEndDisplayLine(sel.MainCaret(), false), 1)); -		SetLastXChosen(); -		break; -	case SCI_LINEENDDISPLAYEXTEND: -		MovePositionTo(MovePositionSoVisible( -		            StartEndDisplayLine(sel.MainCaret(), false), 1), Selection::selStream); -		SetLastXChosen(); -		break;  	case SCI_SCROLLTOSTART:  		ScrollTo(0);  		break; diff --git a/src/Editor.h b/src/Editor.h index 3301c4b05..fdc86f9f6 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -326,6 +326,7 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	bool SelectionContainsProtected();  	int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true) const;  	SelectionPosition MovePositionOutsideChar(SelectionPosition pos, int moveDir, bool checkLineEnd=true) const; +	void MovedCaret(SelectionPosition newPos, SelectionPosition previousPos, bool ensureVisible);  	void MovePositionTo(SelectionPosition newPos, Selection::selTypes selt=Selection::noSel, bool ensureVisible=true);  	void MovePositionTo(int newPos, Selection::selTypes selt=Selection::noSel, bool ensureVisible=true);  	SelectionPosition MovePositionSoVisible(SelectionPosition pos, int moveDir); @@ -458,9 +459,15 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	void Duplicate(bool forLine);  	virtual void CancelModes();  	void NewLine(); +	SelectionPosition PositionUpOrDown(SelectionPosition spStart, int direction, int lastX);  	void CursorUpOrDown(int direction, Selection::selTypes selt);  	void ParaUpOrDown(int direction, Selection::selTypes selt);  	int StartEndDisplayLine(int pos, bool start); +	int VCHomeDisplayPosition(int position); +	int VCHomeWrapPosition(int position); +	int LineEndWrapPosition(int position); +	int HorizontalMove(unsigned int iMessage); +	int DelWordOrLine(unsigned int iMessage);  	virtual int KeyCommand(unsigned int iMessage);  	virtual int KeyDefault(int /* key */, int /*modifiers*/);  	int KeyDownWithModifiers(int key, int modifiers, bool *consumed); diff --git a/src/Selection.cxx b/src/Selection.cxx index f4308b130..0a7c15c1a 100644 --- a/src/Selection.cxx +++ b/src/Selection.cxx @@ -311,6 +311,14 @@ void Selection::TrimSelection(SelectionRange range) {  	}  } +void Selection::TrimOtherSelections(size_t r, SelectionRange range) { +	for (size_t i = 0; i<ranges.size(); ++i) { +		if (i != r) { +			ranges[i].Trim(range); +		} +	} +} +  void Selection::SetSelection(SelectionRange range) {  	ranges.clear();  	ranges.push_back(range); diff --git a/src/Selection.h b/src/Selection.h index 166e3fa71..22c01beff 100644 --- a/src/Selection.h +++ b/src/Selection.h @@ -168,6 +168,7 @@ public:  	int Length() const;  	void MovePositions(bool insertion, int startChange, int length);  	void TrimSelection(SelectionRange range); +	void TrimOtherSelections(size_t r, SelectionRange range);  	void SetSelection(SelectionRange range);  	void AddSelection(SelectionRange range);  	void AddSelectionWithoutTrim(SelectionRange range);  | 
