diff options
| author | nyamatongwe <devnull@localhost> | 2009-07-03 05:48:47 +0000 | 
|---|---|---|
| committer | nyamatongwe <devnull@localhost> | 2009-07-03 05:48:47 +0000 | 
| commit | ec1bb377e03fe38cdb9a10e387cb8eae408afa8f (patch) | |
| tree | f88ba56f27bd5111e0b9c9aaf12426f33dc992d5 /src/Selection.cxx | |
| parent | 32f0b5c04976e2b24ab4d3e6adc7b438be44b90a (diff) | |
| download | scintilla-mirror-ec1bb377e03fe38cdb9a10e387cb8eae408afa8f.tar.gz | |
Discontiguoues selection and virtual space initial commit.
Diffstat (limited to 'src/Selection.cxx')
| -rw-r--r-- | src/Selection.cxx | 345 | 
1 files changed, 345 insertions, 0 deletions
| diff --git a/src/Selection.cxx b/src/Selection.cxx new file mode 100644 index 000000000..224fafc69 --- /dev/null +++ b/src/Selection.cxx @@ -0,0 +1,345 @@ +// Scintilla source code edit control +/** @file Selection.cxx + ** Classes maintaining the selection. + **/ +// Copyright 2009 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> + +#include "Platform.h" + +#include "Scintilla.h" + +#include "Selection.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int length) { +	if (insertion) { +		if (position > startChange) { +			position += length; +		} +	} else { +		if (position > startChange) { +			int endDeletion = startChange + length; +			if (position > endDeletion) { +				position -= length; +			} else { +				position = startChange; +			} +		} +	} +} + +bool SelectionPosition::operator <(const SelectionPosition &other) const { +	if (position == other.position) +		return virtualSpace < other.virtualSpace; +	else +		return position < other.position; +} + +bool SelectionPosition::operator >(const SelectionPosition &other) const { +	if (position == other.position) +		return virtualSpace > other.virtualSpace; +	else +		return position > other.position; +} + +bool SelectionPosition::operator <=(const SelectionPosition &other) const { +	if (position == other.position && virtualSpace == other.virtualSpace) +		return true; +	else +		return other > *this; +} + +bool SelectionPosition::operator >=(const SelectionPosition &other) const { +	if (position == other.position && virtualSpace == other.virtualSpace) +		return true; +	else +		return *this > other; +} + +int SelectionRange::Length() const { +	if (anchor > caret) { +		return anchor.Position() - caret.Position(); +	} else { +		return caret.Position() - anchor.Position(); +	} +} + +bool SelectionRange::Contains(int pos) const { +	if (anchor > caret) +		return (pos >= caret.Position()) && (pos <= anchor.Position()); +	else +		return (pos >= anchor.Position()) && (pos <= caret.Position()); +} + +bool SelectionRange::Contains(SelectionPosition sp) const { +	if (anchor > caret) +		return (sp >= caret) && (sp <= anchor); +	else +		return (sp >= anchor) && (sp <= caret); +} + +bool SelectionRange::ContainsCharacter(int posCharacter) const { +	if (anchor > caret) +		return (posCharacter >= caret.Position()) && (posCharacter < anchor.Position()); +	else +		return (posCharacter >= anchor.Position()) && (posCharacter < caret.Position()); +} + +bool SelectionRange::Intersect(int start, int end, SelectionPosition &selStart, SelectionPosition &selEnd) const { +	SelectionPosition spEnd(end, 100000);	// Large amount of virtual space +	SelectionPosition first; +	SelectionPosition last; +	if (anchor > caret) { +		first = caret; +		last = anchor; +	} else { +		first = anchor; +		last = caret; +	} +	if ((first < spEnd) && (last.Position() > start)) { +		if (start > first.Position())  +			selStart = SelectionPosition(start); +		else  +			selStart = first; +		if (spEnd < last)  +			selEnd = SelectionPosition(end); +		else  +			selEnd = last; +		return true; +	} else { +		return false; +	} +} + +bool SelectionRange::Trim(SelectionPosition startPos, SelectionPosition endPos) { +	SelectionPosition startRange = startPos; +	SelectionPosition endRange = endPos; +	if (startPos > endPos) { +		startRange = endPos; +		endRange = startPos; +	} +	SelectionPosition start = Start(); +	SelectionPosition end = End(); +	PLATFORM_ASSERT(start <= end); +	PLATFORM_ASSERT(startRange <= endRange); +	if ((startRange <= end) && (endRange >= start)) { +		if ((start > startRange) && (end < endRange)) { +			// Completely covered by range -> empty at start +			end = start; +		} else if ((start < startRange) && (end > endRange)) { +			// Completely covers range -> empty at start +			end = start; +		} else if (start <= startRange) { +			// Trim end +			end = startRange; +		} else { //  +			PLATFORM_ASSERT(end >= endRange); +			// Trim start +			start = endRange; +		} +		if (anchor > caret) { +			caret = start; +			anchor = end; +		} else { +			anchor = start; +			caret = end; +		} +		return Empty(); +	} else { +		return false; +	} +} + +// If range is all virtual collapse to start of virtual space +void SelectionRange::MinimizeVirtualSpace() { +	if (caret.Position() == anchor.Position()) { +		int virtualSpace = caret.VirtualSpace(); +		if (virtualSpace > anchor.VirtualSpace()) +			virtualSpace = anchor.VirtualSpace(); +		caret.SetVirtualSpace(virtualSpace); +		anchor.SetVirtualSpace(virtualSpace); +	} +} + +void Selection::Allocate() { +	if (nRanges >= allocated) { +		size_t allocateNew = (allocated + 1) * 2; +		SelectionRange *rangesNew = new SelectionRange[allocateNew]; +		for (size_t r=0; r<Count(); r++) +			rangesNew[r] = ranges[r]; +		delete []ranges; +		ranges = rangesNew; +		allocated = allocateNew; +	} +} + +Selection::Selection() : ranges(0), allocated(0), nRanges(0), mainRange(0), moveExtends(false), selType(selStream) { +	AddSelection(SelectionPosition(0)); +} + +Selection::~Selection() { +	delete []ranges; +} + +bool Selection::IsRectangular() const { +	return (selType == selRectangle) || (selType == selThin); +} + +int Selection::MainCaret() const { +	return ranges[mainRange].caret.Position(); +} + +int Selection::MainAnchor() const { +	return ranges[mainRange].anchor.Position(); +} + +SelectionRange &Selection::Rectangular() { +	return rangeRectangular; +} + +size_t Selection::Count() const { +	return nRanges; +} + +size_t Selection::Main() const { +	return mainRange; +} + +void Selection::SetMain(size_t r) { +	PLATFORM_ASSERT(r < nRanges); +	mainRange = r; +} + +SelectionRange &Selection::Range(size_t r) { +	return ranges[r]; +} + +SelectionRange &Selection::RangeMain() { +	return ranges[mainRange]; +} + +void Selection::ClearVirtualSpace(size_t r) { +	ranges[r].ClearVirtualSpace(); +} + +bool Selection::MoveExtends() const { +	return moveExtends; +} + +void Selection::SetMoveExtends(bool moveExtends_) { +	moveExtends = moveExtends_; +} + +bool Selection::Empty() const { +	for (size_t i=0; i<nRanges; i++) { +		if (!ranges[i].Empty()) +			return false; +	} +	return true; +} + +SelectionPosition Selection::Last() const { +	SelectionPosition lastPosition; +	for (size_t i=0; i<nRanges; i++) { +		if (lastPosition < ranges[i].caret) +			lastPosition = ranges[i].caret; +		if (lastPosition < ranges[i].anchor) +			lastPosition = ranges[i].anchor; +	} +	return lastPosition; +} + +int Selection::Length() const { +	int len = 0; +	for (size_t i=0; i<nRanges; i++) { +		len += ranges[i].Length(); +	} +	return len; +} + +void Selection::MovePositions(bool insertion, int startChange, int length) { +	for (size_t i=0; i<nRanges; i++) { +		ranges[i].caret.MoveForInsertDelete(insertion, startChange, length); +		ranges[i].anchor.MoveForInsertDelete(insertion, startChange, length); +	} +} + +void Selection::TrimSelection(SelectionPosition startPos, SelectionPosition endPos) { +	for (size_t i=0; i<nRanges;) { +		if ((i != mainRange) && (ranges[i].Trim(startPos, endPos))) { +			// Trimmed to empty so remove +			for (size_t j=i;j<nRanges-1;j++) { +				ranges[j] = ranges[j+1]; +				if (j == mainRange-1) +					mainRange--; +			} +			nRanges--; +		} else { +			i++; +		} +	} +} + +void Selection::AddSelection(SelectionPosition spPos) { +	Allocate(); +	TrimSelection(spPos, spPos); +	ranges[nRanges] = SelectionRange(spPos); +	mainRange = nRanges; +	nRanges++; +} + +void Selection::AddSelection(SelectionPosition spStartPos, SelectionPosition spEndPos, bool anchorLeft) { +	Allocate(); +	TrimSelection(spStartPos, spEndPos); +	ranges[nRanges].caret = anchorLeft ? spEndPos : spStartPos; +	ranges[nRanges].anchor = anchorLeft ? spStartPos : spEndPos; +	mainRange = nRanges; +	nRanges++; +} + +bool Selection::CharacterInSelection(int posCharacter) const { +	for (size_t i=0; i<nRanges; i++) { +		if (ranges[i].ContainsCharacter(posCharacter)) +			return true; +	} +	return false; +} + +bool Selection::InSelectionForEOL(int pos) const { +	for (size_t i=0; i<nRanges; i++) { +		if (!ranges[i].Empty() && (pos > ranges[i].Start().Position()) && (pos <= ranges[i].End().Position())) +			return true; +	} +	return false; +} + +int Selection::VirtualSpaceFor(int pos) const { +	int virtualSpace = 0; +	for (size_t i=0; i<nRanges; i++) { +		if ((ranges[i].caret.Position() == pos) && (virtualSpace < ranges[i].caret.VirtualSpace())) +			virtualSpace = ranges[i].caret.VirtualSpace(); +		if ((ranges[i].anchor.Position() == pos) && (virtualSpace < ranges[i].anchor.VirtualSpace())) +			virtualSpace = ranges[i].anchor.VirtualSpace(); +	} +	return virtualSpace; +} + +void Selection::Clear() { +	nRanges = 1; +	mainRange = 0; +	selType = selStream; +	moveExtends = false; +	ranges[mainRange].Reset(); +	rangeRectangular.Reset(); +} + +void Selection::EmptyRanges() { +	nRanges = 0; +	mainRange = 0; +} | 
