diff options
Diffstat (limited to 'src/RunStyles.cxx')
| -rw-r--r-- | src/RunStyles.cxx | 187 | 
1 files changed, 187 insertions, 0 deletions
| diff --git a/src/RunStyles.cxx b/src/RunStyles.cxx new file mode 100644 index 000000000..a7cf40e81 --- /dev/null +++ b/src/RunStyles.cxx @@ -0,0 +1,187 @@ +/** @file RunStyles.cxx + ** Data structure used to store sparse styles. + **/ +// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> + +#include "Platform.h" + +#include "Scintilla.h" +#include "SplitVector.h" +#include "Partitioning.h" +#include "RunStyles.h" + +// Find the first run at a position +int RunStyles::RunFromPosition(int position) { +	int run = starts->PartitionFromPosition(position); +	// Go to first element with this position +	while ((run > 0) && (position == starts->PositionFromPartition(run-1))) { +		run--; +	} +	return run; +} + +// If there is no run boundary at position, insert one continuing style. +void RunStyles::SplitRun(int position) { +	int run = RunFromPosition(position); +	int posRun = starts->PositionFromPartition(run); +	if (posRun < position) { +		int runStyle = ValueAt(position); +		starts->InsertPartition(run+1, position); +		styles->InsertValue(run+1, 1, runStyle); +	} +} + +void RunStyles::RemoveRun(int run) { +	starts->RemovePartition(run); +	styles->DeleteRange(run, 1); +} + +void RunStyles::RemoveRunIfEmpty(int run) { +	if ((run < starts->Partitions()) && (starts->Partitions() > 1)) { +		if (starts->PositionFromPartition(run) == starts->PositionFromPartition(run+1)) { +			RemoveRun(run); +		} +	} +} + +void RunStyles::RemoveRunIfSameAsPrevious(int run) { +	if ((run > 0) && (run < starts->Partitions())) { +		if (styles->ValueAt(run-1) == styles->ValueAt(run)) { +			RemoveRun(run); +		} +	} +} + +RunStyles::RunStyles() { +	starts = new Partitioning(8); +	styles = new SplitVector<int>(); +	styles->InsertValue(0, 2, 0); +} + +RunStyles::~RunStyles() { +	delete starts; +	starts = NULL; +	delete styles; +	styles = NULL; +} + +int RunStyles::Length() { +	return starts->PositionFromPartition(starts->Partitions()); +} + +int RunStyles::ValueAt(int position) { +	return styles->ValueAt(starts->PartitionFromPosition(position)); +} + +int RunStyles::FindNextChange(int position, int end) { +	int run = starts->PartitionFromPosition(position); +	if (run < starts->Partitions()) { +		int runChange = starts->PositionFromPartition(run); +		if (runChange > position) +			return runChange; +		int nextChange = starts->PositionFromPartition(run + 1); +		if (nextChange > position) { +			return nextChange; +		} else if (position < end) { +			return end; +		} else { +			return end + 1; +		} +	} else { +		return end + 1; +	} +} + +int RunStyles::StartRun(int position) { +	return starts->PositionFromPartition(starts->PartitionFromPosition(position)); +} + +int RunStyles::EndRun(int position) { +	return starts->PositionFromPartition(starts->PartitionFromPosition(position) + 1); +} + +void RunStyles::FillRange(int position, int value, int fillLength) { +	int end = position + fillLength; +	SplitRun(end); +	int runStart = RunFromPosition(position); +	if (styles->ValueAt(runStart) != value) { +		SplitRun(position); +		runStart = RunFromPosition(position); +		styles->SetValueAt(runStart, value); +	} +	int runEnd = RunFromPosition(end); +	// Remove each old run over the range +	for (int run=runStart+1; run<runEnd; run++) { +		RemoveRun(runStart+1); +	} +	runEnd = RunFromPosition(end); +	RemoveRunIfSameAsPrevious(runEnd); +	RemoveRunIfSameAsPrevious(runStart); +} + +void RunStyles::InsertSpace(int position, int insertLength) { +	int runStart = RunFromPosition(position); +	if (starts->PositionFromPartition(runStart) == position) { +		int runStyle = ValueAt(position); +		// Inserting at start of run so make previous longer +		if (runStart == 0) { +			// Inserting at start of document so ensure 0 +			if (runStyle) { +				styles->SetValueAt(0, 0); +				starts->InsertPartition(1, 0); +				styles->InsertValue(1, 1, runStyle); +				starts->InsertText(0, insertLength); +			} else { +				starts->InsertText(runStart, insertLength); +			} +		} else { +			if (runStyle) { +				starts->InsertText(runStart-1, insertLength); +			} else { +				// Insert at end of run so do not extend style +				starts->InsertText(runStart, insertLength); +			} +		} +	} else { +		starts->InsertText(runStart, insertLength); +	} +} + +void RunStyles::DeleteAll() { +	delete starts; +	starts = NULL; +	delete styles; +	styles = NULL; +	starts = new Partitioning(8); +	styles = new SplitVector<int>(); +	styles->InsertValue(0, 2, 0); +} + +void RunStyles::DeleteRange(int position, int deleteLength) { +	int end = position + deleteLength; +	int runStart = RunFromPosition(position); +	int runEnd = RunFromPosition(end); +	if (runStart == runEnd) { +		// Deleting from inside one run +		starts->InsertText(runStart, -deleteLength); +	} else { +		SplitRun(position); +		SplitRun(end); +		runStart = RunFromPosition(position); +		runEnd = RunFromPosition(end); +		starts->InsertText(runStart, -deleteLength); +		// Remove each old run over the range +		for (int run=runStart; run<runEnd; run++) { +			RemoveRun(runStart); +		} +		RemoveRunIfEmpty(runStart); +		RemoveRunIfSameAsPrevious(runStart); +	} +} + | 
