diff options
| author | nyamatongwe <devnull@localhost> | 2007-04-05 10:52:30 +0000 | 
|---|---|---|
| committer | nyamatongwe <devnull@localhost> | 2007-04-05 10:52:30 +0000 | 
| commit | 3cfff9870374cd20607b79429f18be996492ef52 (patch) | |
| tree | f1a8788e6db37e16a63bed84f91b434b7393cb9b | |
| parent | 2a30f053fd7ad4d9dcb8a5a39a3bf4da06f344e8 (diff) | |
| download | scintilla-mirror-3cfff9870374cd20607b79429f18be996492ef52.tar.gz | |
New files that implement decorations.
| -rw-r--r-- | src/Decoration.cxx | 183 | ||||
| -rw-r--r-- | src/Decoration.h | 55 | ||||
| -rw-r--r-- | src/RunStyles.cxx | 187 | ||||
| -rw-r--r-- | src/RunStyles.h | 31 | 
4 files changed, 456 insertions, 0 deletions
| diff --git a/src/Decoration.cxx b/src/Decoration.cxx new file mode 100644 index 000000000..f1c9c5ae3 --- /dev/null +++ b/src/Decoration.cxx @@ -0,0 +1,183 @@ +/** @file Decoration.cxx + ** Visual elements added over text. + **/ +// 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" +#include "Decoration.h" + +Decoration::Decoration(int indicator_) : next(0), indicator(indicator_) { +} + +Decoration::~Decoration() { +} + +bool Decoration::Empty() { +	return rs.starts->Partitions() == 1; +} + +DecorationList::DecorationList() : currentIndicator(0), currentValue(1), current(0), +	lengthDocument(0), root(0), clickNotified(false) { +} + +DecorationList::~DecorationList() { +	Decoration *deco = root; +	while (deco) { +		Decoration *decoNext = deco->next; +		delete deco; +		deco = decoNext; +	} +	root = 0; +	current = 0; +} + +Decoration *DecorationList::DecorationFromIndicator(int indicator) { +	for (Decoration *deco=root; deco; deco = deco->next) { +		if (deco->indicator == indicator) { +			return deco; +		} +	} +	return 0; +} + +Decoration *DecorationList::Create(int indicator, int length) { +	currentIndicator = indicator; +	Decoration *decoNew = new Decoration(indicator); +	decoNew->rs.InsertSpace(0, length); + +	Decoration *decoPrev = 0; +	Decoration *deco = root; + +	while (deco && (deco->indicator < indicator)) { +		decoPrev = deco; +		deco = deco->next; +	} +	if (decoPrev == 0) { +		decoNew->next = root; +		root = decoNew; +	} else { +		decoNew->next = deco; +		decoPrev->next = decoNew; +	} +	return decoNew; +} + +void DecorationList::Delete(int indicator) { +	Decoration *decoToDelete = 0; +	if (root) { +		if (root->indicator == indicator) { +			decoToDelete = root; +			root = root->next; +		} else { +			Decoration *deco=root; +			while (deco->next && !decoToDelete) { +				if (deco->next && deco->next->indicator == indicator) { +					decoToDelete = deco->next; +					deco->next = decoToDelete->next; +				} else { +					deco = deco->next; +				} +			} +		} +	} +	if (decoToDelete) { +		delete decoToDelete; +		current = 0; +	} +} + +void DecorationList::SetCurrentIndicator(int indicator) { +	currentIndicator = indicator; +	current = DecorationFromIndicator(indicator); +	currentValue = 1; +} + +void DecorationList::SetCurrentValue(int value) { +	currentValue = value; +} + +void DecorationList::FillRange(int position, int value, int fillLength) { +	if (!current) { +		current = DecorationFromIndicator(currentIndicator); +		if (!current) { +			current = Create(currentIndicator, lengthDocument); +		} +	} +	current->rs.FillRange(position, value, fillLength); +	if (current->Empty()) { +		Delete(currentIndicator); +	} +} + +void DecorationList::InsertSpace(int position, int insertLength) { +	lengthDocument += insertLength; +	for (Decoration *deco=root; deco; deco = deco->next) { +		deco->rs.InsertSpace(position, insertLength); +	} +} + +void DecorationList::DeleteRange(int position, int deleteLength) { +	lengthDocument -= deleteLength; +	Decoration *deco; +	for (deco=root; deco; deco = deco->next) { +		deco->rs.DeleteRange(position, deleteLength); +	} +	DeleteAnyEmpty(); +} + +void DecorationList::DeleteAnyEmpty() { +	Decoration *deco = root; +	while (deco) { +		if (deco->Empty()) { +			Delete(deco->indicator); +			deco = root; +		} else { +			deco = deco->next; +		} +	} +} + +int DecorationList::AllOnFor(int position) { +	int mask = 0; +	for (Decoration *deco=root; deco; deco = deco->next) { +		if (deco->rs.ValueAt(position)) { +			mask |= 1 << deco->indicator; +		} +	} +	return mask; +} + +int DecorationList::ValueAt(int indicator, int position) { +	Decoration *deco = DecorationFromIndicator(indicator); +	if (deco) { +		return deco->rs.ValueAt(position); +	} +	return 0; +} + +int DecorationList::Start(int indicator, int position) { +	Decoration *deco = DecorationFromIndicator(indicator); +	if (deco) { +		return deco->rs.StartRun(position); +	} +	return 0; +} + +int DecorationList::End(int indicator, int position) { +	Decoration *deco = DecorationFromIndicator(indicator); +	if (deco) { +		return deco->rs.EndRun(position); +	} +	return 0; +} diff --git a/src/Decoration.h b/src/Decoration.h new file mode 100644 index 000000000..1810b0fb3 --- /dev/null +++ b/src/Decoration.h @@ -0,0 +1,55 @@ +/** @file Decoration.h + ** Visual elements added over text. + **/ +// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef DECORATION_H +#define DECORATION_H + +class Decoration { +public: +	Decoration *next; +	RunStyles rs; +	int indicator; + +	Decoration(int indicator_); +	~Decoration(); + +	bool Empty(); +}; + +class DecorationList { +	int currentIndicator; +	int currentValue; +	Decoration *current; +	int lengthDocument; +	Decoration *DecorationFromIndicator(int indicator); +	Decoration *Create(int indicator, int length); +	void Delete(int indicator); +	void DeleteAnyEmpty(); +public: +	Decoration *root; +	bool clickNotified; + +	DecorationList(); +	~DecorationList(); + +	void SetCurrentIndicator(int indicator); +	int GetCurrentIndicator() { return currentIndicator; } + +	void SetCurrentValue(int value); +	int GetCurrentValue() { return currentValue; } + +	void FillRange(int position, int value, int fillLength); + +	void InsertSpace(int position, int insertLength); +	void DeleteRange(int position, int deleteLength); + +	int AllOnFor(int position); +	int ValueAt(int indicator, int position); +	int Start(int indicator, int position); +	int End(int indicator, int position); +}; + +#endif 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); +	} +} + diff --git a/src/RunStyles.h b/src/RunStyles.h new file mode 100644 index 000000000..539e5de47 --- /dev/null +++ b/src/RunStyles.h @@ -0,0 +1,31 @@ +/** @file RunStyles.h + ** 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. + +/// Styling buffer using one element for each run rather than using +/// a filled buffer. + +class RunStyles { +public: +	Partitioning *starts; +	SplitVector<int> *styles; +	int RunFromPosition(int position); +	void SplitRun(int position); +	void RemoveRun(int run); +	void RemoveRunIfEmpty(int run); +	void RemoveRunIfSameAsPrevious(int run); +public: +	RunStyles(); +	~RunStyles(); +	int Length(); +	int ValueAt(int position); +	int FindNextChange(int position, int end); +	int StartRun(int position); +	int EndRun(int position); +	void FillRange(int position, int value, int fillLength); +	void InsertSpace(int position, int insertLength); +	void DeleteAll(); +	void DeleteRange(int position, int deleteLength); +}; | 
