geany  1.38
About: Geany is a text editor (using GTK2) with basic features of an integrated development environment (syntax highlighting, code folding, symbol name auto-completion, ...). F: office T: editor programming GTK+ IDE
  Fossies Dox: geany-1.38.tar.bz2  ("unofficial" and yet experimental doxygen-generated source code documentation)  

RunStyles.cxx
Go to the documentation of this file.
1/** @file RunStyles.cxx
2 ** Data structure used to store sparse styles.
3 **/
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.
6
7#include <cstddef>
8#include <cstdlib>
9#include <cstdint>
10#include <cstring>
11#include <cstdio>
12#include <cstdarg>
13#include <climits>
14
15#include <stdexcept>
16#include <vector>
17#include <algorithm>
18#include <memory>
19
20#include "Platform.h"
21
22#include "Scintilla.h"
23#include "Position.h"
24#include "SplitVector.h"
25#include "Partitioning.h"
26#include "RunStyles.h"
27
28using namespace Scintilla;
29
30// Find the first run at a position
31template <typename DISTANCE, typename STYLE>
32DISTANCE RunStyles<DISTANCE, STYLE>::RunFromPosition(DISTANCE position) const noexcept {
33 DISTANCE run = starts->PartitionFromPosition(position);
34 // Go to first element with this position
35 while ((run > 0) && (position == starts->PositionFromPartition(run-1))) {
36 run--;
37 }
38 return run;
39}
40
41// If there is no run boundary at position, insert one continuing style.
42template <typename DISTANCE, typename STYLE>
44 DISTANCE run = RunFromPosition(position);
45 const DISTANCE posRun = starts->PositionFromPartition(run);
46 if (posRun < position) {
47 STYLE runStyle = ValueAt(position);
48 run++;
49 starts->InsertPartition(run, position);
50 styles->InsertValue(run, 1, runStyle);
51 }
52 return run;
53}
54
55template <typename DISTANCE, typename STYLE>
57 starts->RemovePartition(run);
58 styles->DeleteRange(run, 1);
59}
60
61template <typename DISTANCE, typename STYLE>
63 if ((run < starts->Partitions()) && (starts->Partitions() > 1)) {
64 if (starts->PositionFromPartition(run) == starts->PositionFromPartition(run+1)) {
65 RemoveRun(run);
66 }
67 }
68}
69
70template <typename DISTANCE, typename STYLE>
72 if ((run > 0) && (run < starts->Partitions())) {
73 if (styles->ValueAt(run-1) == styles->ValueAt(run)) {
74 RemoveRun(run);
75 }
76 }
77}
78
79template <typename DISTANCE, typename STYLE>
81 starts = Sci::make_unique<Partitioning<DISTANCE>>(8);
82 styles = Sci::make_unique<SplitVector<STYLE>>();
83 styles->InsertValue(0, 2, 0);
84}
85
86template <typename DISTANCE, typename STYLE>
88}
89
90template <typename DISTANCE, typename STYLE>
91DISTANCE RunStyles<DISTANCE, STYLE>::Length() const noexcept {
92 return starts->PositionFromPartition(starts->Partitions());
93}
94
95template <typename DISTANCE, typename STYLE>
96STYLE RunStyles<DISTANCE, STYLE>::ValueAt(DISTANCE position) const noexcept {
97 return styles->ValueAt(starts->PartitionFromPosition(position));
98}
99
100template <typename DISTANCE, typename STYLE>
101DISTANCE RunStyles<DISTANCE, STYLE>::FindNextChange(DISTANCE position, DISTANCE end) const noexcept {
102 const DISTANCE run = starts->PartitionFromPosition(position);
103 if (run < starts->Partitions()) {
104 const DISTANCE runChange = starts->PositionFromPartition(run);
105 if (runChange > position)
106 return runChange;
107 const DISTANCE nextChange = starts->PositionFromPartition(run + 1);
108 if (nextChange > position) {
109 return nextChange;
110 } else if (position < end) {
111 return end;
112 } else {
113 return end + 1;
114 }
115 } else {
116 return end + 1;
117 }
118}
119
120template <typename DISTANCE, typename STYLE>
121DISTANCE RunStyles<DISTANCE, STYLE>::StartRun(DISTANCE position) const noexcept {
122 return starts->PositionFromPartition(starts->PartitionFromPosition(position));
123}
124
125template <typename DISTANCE, typename STYLE>
126DISTANCE RunStyles<DISTANCE, STYLE>::EndRun(DISTANCE position) const noexcept {
127 return starts->PositionFromPartition(starts->PartitionFromPosition(position) + 1);
128}
129
130template <typename DISTANCE, typename STYLE>
131FillResult<DISTANCE> RunStyles<DISTANCE, STYLE>::FillRange(DISTANCE position, STYLE value, DISTANCE fillLength) {
132 const FillResult<DISTANCE> resultNoChange{false, position, fillLength};
133 if (fillLength <= 0) {
134 return resultNoChange;
135 }
136 DISTANCE end = position + fillLength;
137 if (end > Length()) {
138 return resultNoChange;
139 }
140 DISTANCE runEnd = RunFromPosition(end);
141 if (styles->ValueAt(runEnd) == value) {
142 // End already has value so trim range.
143 end = starts->PositionFromPartition(runEnd);
144 if (position >= end) {
145 // Whole range is already same as value so no action
146 return resultNoChange;
147 }
148 fillLength = end - position;
149 } else {
150 runEnd = SplitRun(end);
151 }
152 DISTANCE runStart = RunFromPosition(position);
153 if (styles->ValueAt(runStart) == value) {
154 // Start is in expected value so trim range.
155 runStart++;
156 position = starts->PositionFromPartition(runStart);
157 fillLength = end - position;
158 } else {
159 if (starts->PositionFromPartition(runStart) < position) {
160 runStart = SplitRun(position);
161 runEnd++;
162 }
163 }
164 if (runStart < runEnd) {
165 const FillResult<DISTANCE> result{ true, position, fillLength };
166 styles->SetValueAt(runStart, value);
167 // Remove each old run over the range
168 for (DISTANCE run=runStart+1; run<runEnd; run++) {
169 RemoveRun(runStart+1);
170 }
171 runEnd = RunFromPosition(end);
172 RemoveRunIfSameAsPrevious(runEnd);
173 RemoveRunIfSameAsPrevious(runStart);
174 runEnd = RunFromPosition(end);
175 RemoveRunIfEmpty(runEnd);
176 return result;
177 } else {
178 return resultNoChange;
179 }
180}
181
182template <typename DISTANCE, typename STYLE>
184 FillRange(position, value, 1);
185}
186
187template <typename DISTANCE, typename STYLE>
188void RunStyles<DISTANCE, STYLE>::InsertSpace(DISTANCE position, DISTANCE insertLength) {
189 DISTANCE runStart = RunFromPosition(position);
190 if (starts->PositionFromPartition(runStart) == position) {
191 STYLE runStyle = ValueAt(position);
192 // Inserting at start of run so make previous longer
193 if (runStart == 0) {
194 // Inserting at start of document so ensure 0
195 if (runStyle) {
196 styles->SetValueAt(0, STYLE());
197 starts->InsertPartition(1, 0);
198 styles->InsertValue(1, 1, runStyle);
199 starts->InsertText(0, insertLength);
200 } else {
201 starts->InsertText(runStart, insertLength);
202 }
203 } else {
204 if (runStyle) {
205 starts->InsertText(runStart-1, insertLength);
206 } else {
207 // Insert at end of run so do not extend style
208 starts->InsertText(runStart, insertLength);
209 }
210 }
211 } else {
212 starts->InsertText(runStart, insertLength);
213 }
214}
215
216template <typename DISTANCE, typename STYLE>
218 starts = Sci::make_unique<Partitioning<DISTANCE>>(8);
219 styles = Sci::make_unique<SplitVector<STYLE>>();
220 styles->InsertValue(0, 2, 0);
221}
222
223template <typename DISTANCE, typename STYLE>
224void RunStyles<DISTANCE, STYLE>::DeleteRange(DISTANCE position, DISTANCE deleteLength) {
225 DISTANCE end = position + deleteLength;
226 DISTANCE runStart = RunFromPosition(position);
227 DISTANCE runEnd = RunFromPosition(end);
228 if (runStart == runEnd) {
229 // Deleting from inside one run
230 starts->InsertText(runStart, -deleteLength);
231 RemoveRunIfEmpty(runStart);
232 } else {
233 runStart = SplitRun(position);
234 runEnd = SplitRun(end);
235 starts->InsertText(runStart, -deleteLength);
236 // Remove each old run over the range
237 for (DISTANCE run=runStart; run<runEnd; run++) {
238 RemoveRun(runStart);
239 }
240 RemoveRunIfEmpty(runStart);
241 RemoveRunIfSameAsPrevious(runStart);
242 }
243}
244
245template <typename DISTANCE, typename STYLE>
246DISTANCE RunStyles<DISTANCE, STYLE>::Runs() const noexcept {
247 return starts->Partitions();
248}
249
250template <typename DISTANCE, typename STYLE>
252 for (DISTANCE run = 1; run < starts->Partitions(); run++) {
253 if (styles->ValueAt(run) != styles->ValueAt(run - 1))
254 return false;
255 }
256 return true;
257}
258
259template <typename DISTANCE, typename STYLE>
260bool RunStyles<DISTANCE, STYLE>::AllSameAs(STYLE value) const noexcept {
261 return AllSame() && (styles->ValueAt(0) == value);
262}
263
264template <typename DISTANCE, typename STYLE>
265DISTANCE RunStyles<DISTANCE, STYLE>::Find(STYLE value, DISTANCE start) const noexcept {
266 if (start < Length()) {
267 DISTANCE run = start ? RunFromPosition(start) : 0;
268 if (styles->ValueAt(run) == value)
269 return start;
270 run++;
271 while (run < starts->Partitions()) {
272 if (styles->ValueAt(run) == value)
273 return starts->PositionFromPartition(run);
274 run++;
275 }
276 }
277 return -1;
278}
279
280template <typename DISTANCE, typename STYLE>
282 if (Length() < 0) {
283 throw std::runtime_error("RunStyles: Length can not be negative.");
284 }
285 if (starts->Partitions() < 1) {
286 throw std::runtime_error("RunStyles: Must always have 1 or more partitions.");
287 }
288 if (starts->Partitions() != styles->Length()-1) {
289 throw std::runtime_error("RunStyles: Partitions and styles different lengths.");
290 }
291 DISTANCE start=0;
292 while (start < Length()) {
293 const DISTANCE end = EndRun(start);
294 if (start >= end) {
295 throw std::runtime_error("RunStyles: Partition is 0 length.");
296 }
297 start = end;
298 }
299 if (styles->ValueAt(styles->Length()-1) != 0) {
300 throw std::runtime_error("RunStyles: Unused style at end changed.");
301 }
302 for (ptrdiff_t j=1; j<styles->Length()-1; j++) {
303 if (styles->ValueAt(j) == styles->ValueAt(j-1)) {
304 throw std::runtime_error("RunStyles: Style of a partition same as previous.");
305 }
306 }
307}
308
309template class Scintilla::RunStyles<int, int>;
311#if (PTRDIFF_MAX != INT_MAX) || PLAT_HAIKU
314#endif
Data structure used to partition an interval.
Interface to platform facilities.
Defines global type name Position in the Sci internal namespace.
Data structure used to store sparse styles.
Interface to the edit control.
Main data structure for holding arrays that handle insertions and deletions efficiently.
STYLE ValueAt(DISTANCE position) const noexcept
Definition: RunStyles.cxx:96
void DeleteRange(DISTANCE position, DISTANCE deleteLength)
Definition: RunStyles.cxx:224
Styling buffer using one element for each run rather than using a filled buffer.
Definition: Converter.h:9
gint position[2]
Definition: search.c:120