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