1
/** @file RunStyles.cxx
2
** Data structure used to store sparse styles.
4
// Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org>
5
// The License.txt file describes the conditions under which this software may be distributed.
14
#include "Scintilla.h"
15
#include "SplitVector.h"
16
#include "Partitioning.h"
17
#include "RunStyles.h"
20
using namespace Scintilla;
23
// Find the first run at a position
24
int RunStyles::RunFromPosition(int position) {
25
int run = starts->PartitionFromPosition(position);
26
// Go to first element with this position
27
while ((run > 0) && (position == starts->PositionFromPartition(run-1))) {
33
// If there is no run boundary at position, insert one continuing style.
34
int RunStyles::SplitRun(int position) {
35
int run = RunFromPosition(position);
36
int posRun = starts->PositionFromPartition(run);
37
if (posRun < position) {
38
int runStyle = ValueAt(position);
40
starts->InsertPartition(run, position);
41
styles->InsertValue(run, 1, runStyle);
46
void RunStyles::RemoveRun(int run) {
47
starts->RemovePartition(run);
48
styles->DeleteRange(run, 1);
51
void RunStyles::RemoveRunIfEmpty(int run) {
52
if ((run < starts->Partitions()) && (starts->Partitions() > 1)) {
53
if (starts->PositionFromPartition(run) == starts->PositionFromPartition(run+1)) {
59
void RunStyles::RemoveRunIfSameAsPrevious(int run) {
60
if ((run > 0) && (run < starts->Partitions())) {
61
if (styles->ValueAt(run-1) == styles->ValueAt(run)) {
67
RunStyles::RunStyles() {
68
starts = new Partitioning(8);
69
styles = new SplitVector<int>();
70
styles->InsertValue(0, 2, 0);
73
RunStyles::~RunStyles() {
80
int RunStyles::Length() const {
81
return starts->PositionFromPartition(starts->Partitions());
84
int RunStyles::ValueAt(int position) const {
85
return styles->ValueAt(starts->PartitionFromPosition(position));
88
int RunStyles::FindNextChange(int position, int end) {
89
int run = starts->PartitionFromPosition(position);
90
if (run < starts->Partitions()) {
91
int runChange = starts->PositionFromPartition(run);
92
if (runChange > position)
94
int nextChange = starts->PositionFromPartition(run + 1);
95
if (nextChange > position) {
97
} else if (position < end) {
107
int RunStyles::StartRun(int position) {
108
return starts->PositionFromPartition(starts->PartitionFromPosition(position));
111
int RunStyles::EndRun(int position) {
112
return starts->PositionFromPartition(starts->PartitionFromPosition(position) + 1);
115
bool RunStyles::FillRange(int &position, int value, int &fillLength) {
116
int end = position + fillLength;
117
int runEnd = RunFromPosition(end);
118
if (styles->ValueAt(runEnd) == value) {
119
// End already has value so trim range.
120
end = starts->PositionFromPartition(runEnd);
121
if (position >= end) {
122
// Whole range is already same as value so no action
125
fillLength = end - position;
127
runEnd = SplitRun(end);
129
int runStart = RunFromPosition(position);
130
if (styles->ValueAt(runStart) == value) {
131
// Start is in expected value so trim range.
133
position = starts->PositionFromPartition(runStart);
134
fillLength = end - position;
136
if (starts->PositionFromPartition(runStart) < position) {
137
runStart = SplitRun(position);
141
if (runStart < runEnd) {
142
styles->SetValueAt(runStart, value);
143
// Remove each old run over the range
144
for (int run=runStart+1; run<runEnd; run++) {
145
RemoveRun(runStart+1);
147
runEnd = RunFromPosition(end);
148
RemoveRunIfSameAsPrevious(runEnd);
149
RemoveRunIfSameAsPrevious(runStart);
156
void RunStyles::SetValueAt(int position, int value) {
158
FillRange(position, value, len);
161
void RunStyles::InsertSpace(int position, int insertLength) {
162
int runStart = RunFromPosition(position);
163
if (starts->PositionFromPartition(runStart) == position) {
164
int runStyle = ValueAt(position);
165
// Inserting at start of run so make previous longer
167
// Inserting at start of document so ensure 0
169
styles->SetValueAt(0, 0);
170
starts->InsertPartition(1, 0);
171
styles->InsertValue(1, 1, runStyle);
172
starts->InsertText(0, insertLength);
174
starts->InsertText(runStart, insertLength);
178
starts->InsertText(runStart-1, insertLength);
180
// Insert at end of run so do not extend style
181
starts->InsertText(runStart, insertLength);
185
starts->InsertText(runStart, insertLength);
189
void RunStyles::DeleteAll() {
194
starts = new Partitioning(8);
195
styles = new SplitVector<int>();
196
styles->InsertValue(0, 2, 0);
199
void RunStyles::DeleteRange(int position, int deleteLength) {
200
int end = position + deleteLength;
201
int runStart = RunFromPosition(position);
202
int runEnd = RunFromPosition(end);
203
if (runStart == runEnd) {
204
// Deleting from inside one run
205
starts->InsertText(runStart, -deleteLength);
207
runStart = SplitRun(position);
208
runEnd = SplitRun(end);
209
starts->InsertText(runStart, -deleteLength);
210
// Remove each old run over the range
211
for (int run=runStart; run<runEnd; run++) {
214
RemoveRunIfEmpty(runStart);
215
RemoveRunIfSameAsPrevious(runStart);