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)  

PerLine.cxx
Go to the documentation of this file.
1// Scintilla source code edit control
2/** @file PerLine.cxx
3 ** Manages data associated with each line of the document
4 **/
5// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org>
6// The License.txt file describes the conditions under which this software may be distributed.
7
8#include <cstddef>
9#include <cassert>
10#include <cstring>
11
12#include <stdexcept>
13#include <vector>
14#include <forward_list>
15#include <algorithm>
16#include <memory>
17
18#include "Platform.h"
19
20#include "Scintilla.h"
21#include "Position.h"
22#include "SplitVector.h"
23#include "Partitioning.h"
24#include "CellBuffer.h"
25#include "PerLine.h"
26
27using namespace Scintilla;
28
29MarkerHandleSet::MarkerHandleSet() {
30}
31
33 mhList.clear();
34}
35
36bool MarkerHandleSet::Empty() const noexcept {
37 return mhList.empty();
38}
39
40int MarkerHandleSet::MarkValue() const noexcept {
41 unsigned int m = 0;
42 for (const MarkerHandleNumber &mhn : mhList) {
43 m |= (1 << mhn.number);
44 }
45 return m;
46}
47
48bool MarkerHandleSet::Contains(int handle) const noexcept {
49 for (const MarkerHandleNumber &mhn : mhList) {
50 if (mhn.handle == handle) {
51 return true;
52 }
53 }
54 return false;
55}
56
58 for (const MarkerHandleNumber &mhn : mhList) {
59 if (which == 0)
60 return &mhn;
61 which--;
62 }
63 return nullptr;
64}
65
66bool MarkerHandleSet::InsertHandle(int handle, int markerNum) {
67 mhList.push_front(MarkerHandleNumber(handle, markerNum));
68 return true;
69}
70
72 mhList.remove_if([handle](const MarkerHandleNumber &mhn) noexcept { return mhn.handle == handle; });
73}
74
75bool MarkerHandleSet::RemoveNumber(int markerNum, bool all) {
76 bool performedDeletion = false;
77 mhList.remove_if([&](const MarkerHandleNumber &mhn) noexcept {
78 if ((all || !performedDeletion) && (mhn.number == markerNum)) {
79 performedDeletion = true;
80 return true;
81 }
82 return false;
83 });
84 return performedDeletion;
85}
86
88 mhList.splice_after(mhList.before_begin(), other->mhList);
89}
90
92}
93
95 markers.DeleteAll();
96}
97
99 if (markers.Length()) {
100 markers.Insert(line, 0);
101 }
102}
103
105 if (markers.Length()) {
106 markers.InsertEmpty(line, lines);
107 }
108}
109
111 // Retain the markers from the deleted line by oring them into the previous line
112 if (markers.Length()) {
113 if (line > 0) {
114 MergeMarkers(line - 1);
115 }
116 markers.Delete(line);
117 }
118}
119
120Sci::Line LineMarkers::LineFromHandle(int markerHandle) const noexcept {
121 for (Sci::Line line = 0; line < markers.Length(); line++) {
122 if (markers[line] && markers[line]->Contains(markerHandle)) {
123 return line;
124 }
125 }
126 return -1;
127}
128
129int LineMarkers::HandleFromLine(Sci::Line line, int which) const noexcept {
130 if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) {
131 MarkerHandleNumber const *pnmh = markers[line]->GetMarkerHandleNumber(which);
132 return pnmh ? pnmh->handle : -1;
133 }
134 return -1;
135}
136
137int LineMarkers::NumberFromLine(Sci::Line line, int which) const noexcept {
138 if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) {
139 MarkerHandleNumber const *pnmh = markers[line]->GetMarkerHandleNumber(which);
140 return pnmh ? pnmh->number : -1;
141 }
142 return -1;
143}
144
146 if (markers[line + 1]) {
147 if (!markers[line])
148 markers[line] = Sci::make_unique<MarkerHandleSet>();
149 markers[line]->CombineWith(markers[line + 1].get());
150 markers[line + 1].reset();
151 }
152}
153
155 if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line])
156 return markers[line]->MarkValue();
157 else
158 return 0;
159}
160
161Sci::Line LineMarkers::MarkerNext(Sci::Line lineStart, int mask) const noexcept {
162 if (lineStart < 0)
163 lineStart = 0;
164 const Sci::Line length = markers.Length();
165 for (Sci::Line iLine = lineStart; iLine < length; iLine++) {
166 const MarkerHandleSet *onLine = markers[iLine].get();
167 if (onLine && ((onLine->MarkValue() & mask) != 0))
168 return iLine;
169 }
170 return -1;
171}
172
175 if (!markers.Length()) {
176 // No existing markers so allocate one element per line
177 markers.InsertEmpty(0, lines);
178 }
179 if (line >= markers.Length()) {
180 return -1;
181 }
182 if (!markers[line]) {
183 // Need new structure to hold marker handle
184 markers[line] = Sci::make_unique<MarkerHandleSet>();
185 }
186 markers[line]->InsertHandle(handleCurrent, markerNum);
187
188 return handleCurrent;
189}
190
191bool LineMarkers::DeleteMark(Sci::Line line, int markerNum, bool all) {
192 bool someChanges = false;
193 if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) {
194 if (markerNum == -1) {
195 someChanges = true;
196 markers[line].reset();
197 } else {
198 someChanges = markers[line]->RemoveNumber(markerNum, all);
199 if (markers[line]->Empty()) {
200 markers[line].reset();
201 }
202 }
203 }
204 return someChanges;
205}
206
207void LineMarkers::DeleteMarkFromHandle(int markerHandle) {
208 const Sci::Line line = LineFromHandle(markerHandle);
209 if (line >= 0) {
210 markers[line]->RemoveHandle(markerHandle);
211 if (markers[line]->Empty()) {
212 markers[line].reset();
213 }
214 }
215}
216
218}
219
221 levels.DeleteAll();
222}
223
225 if (levels.Length()) {
226 const int level = (line < levels.Length()) ? levels[line] : SC_FOLDLEVELBASE;
227 levels.Insert(line, level);
228 }
229}
230
232 if (levels.Length()) {
233 const int level = (line < levels.Length()) ? levels[line] : SC_FOLDLEVELBASE;
234 levels.InsertValue(line, lines, level);
235 }
236}
237
239 if (levels.Length()) {
240 // Move up following lines but merge header flag from this line
241 // to line before to avoid a temporary disappearance causing expansion.
242 int firstHeader = levels[line] & SC_FOLDLEVELHEADERFLAG;
243 levels.Delete(line);
244 if (line == levels.Length()-1) // Last line loses the header flag
245 levels[line-1] &= ~SC_FOLDLEVELHEADERFLAG;
246 else if (line > 0)
247 levels[line-1] |= firstHeader;
248 }
249}
250
252 levels.InsertValue(levels.Length(), sizeNew - levels.Length(), SC_FOLDLEVELBASE);
253}
254
256 levels.DeleteAll();
257}
258
260 int prev = 0;
261 if ((line >= 0) && (line < lines)) {
262 if (!levels.Length()) {
263 ExpandLevels(lines + 1);
264 }
265 prev = levels[line];
266 if (prev != level) {
267 levels[line] = level;
268 }
269 }
270 return prev;
271}
272
274 if (levels.Length() && (line >= 0) && (line < levels.Length())) {
275 return levels[line];
276 } else {
277 return SC_FOLDLEVELBASE;
278 }
279}
280
282}
283
285 lineStates.DeleteAll();
286}
287
289 if (lineStates.Length()) {
290 lineStates.EnsureLength(line);
291 const int val = (line < lineStates.Length()) ? lineStates[line] : 0;
292 lineStates.Insert(line, val);
293 }
294}
295
297 if (lineStates.Length()) {
298 lineStates.EnsureLength(line);
299 const int val = (line < lineStates.Length()) ? lineStates[line] : 0;
300 lineStates.InsertValue(line, lines, val);
301 }
302}
303
305 if (lineStates.Length() > line) {
306 lineStates.Delete(line);
307 }
308}
309
311 lineStates.EnsureLength(line + 1);
312 const int stateOld = lineStates[line];
313 lineStates[line] = state;
314 return stateOld;
315}
316
318 if (line < 0)
319 return 0;
320 lineStates.EnsureLength(line + 1);
321 return lineStates[line];
322}
323
325 return lineStates.Length();
326}
327
328// Each allocated LineAnnotation is a char array which starts with an AnnotationHeader
329// and then has text and optional styles.
330
332 short style; // Style IndividualStyles implies array of styles
333 short lines;
335};
336
337namespace {
338
339constexpr int IndividualStyles = 0x100;
340
341size_t NumberLines(const char *text) noexcept {
342 int lines = 1;
343 if (text) {
344 while (*text) {
345 if (*text == '\n')
346 lines++;
347 text++;
348 }
349 }
350 return lines;
351}
352
353std::unique_ptr<char[]>AllocateAnnotation(size_t length, int style) {
354 const size_t len = sizeof(AnnotationHeader) + length + ((style == IndividualStyles) ? length : 0);
355 return Sci::make_unique<char[]>(len);
356}
357
358}
359
361}
362
364 ClearAll();
365}
366
368 if (annotations.Length()) {
369 annotations.EnsureLength(line);
370 annotations.Insert(line, std::unique_ptr<char []>());
371 }
372}
373
375 if (annotations.Length()) {
376 annotations.EnsureLength(line);
377 annotations.InsertEmpty(line, lines);
378 }
379}
380
382 if (annotations.Length() && (line > 0) && (line <= annotations.Length())) {
383 annotations[line-1].reset();
384 annotations.Delete(line-1);
385 }
386}
387
389 if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
390 return reinterpret_cast<AnnotationHeader *>(annotations[line].get())->style == IndividualStyles;
391 else
392 return false;
393}
394
396 if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
397 return reinterpret_cast<AnnotationHeader *>(annotations[line].get())->style;
398 else
399 return 0;
400}
401
402const char *LineAnnotation::Text(Sci::Line line) const noexcept {
403 if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
404 return annotations[line].get()+sizeof(AnnotationHeader);
405 else
406 return nullptr;
407}
408
409const unsigned char *LineAnnotation::Styles(Sci::Line line) const noexcept {
410 if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line] && MultipleStyles(line))
411 return reinterpret_cast<unsigned char *>(annotations[line].get() + sizeof(AnnotationHeader) + Length(line));
412 else
413 return nullptr;
414}
415
417 if (text && (line >= 0)) {
418 annotations.EnsureLength(line+1);
419 const int style = Style(line);
420 annotations[line] = AllocateAnnotation(strlen(text), style);
421 char *pa = annotations[line].get();
422 assert(pa);
423 AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(pa);
424 pah->style = static_cast<short>(style);
425 pah->length = static_cast<int>(strlen(text));
426 pah->lines = static_cast<short>(NumberLines(text));
427 memcpy(pa+sizeof(AnnotationHeader), text, pah->length);
428 } else {
429 if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) {
430 annotations[line].reset();
431 }
432 }
433}
434
436 annotations.DeleteAll();
437}
438
440 annotations.EnsureLength(line+1);
441 if (!annotations[line]) {
442 annotations[line] = AllocateAnnotation(0, style);
443 }
444 reinterpret_cast<AnnotationHeader *>(annotations[line].get())->style = static_cast<short>(style);
445}
446
447void LineAnnotation::SetStyles(Sci::Line line, const unsigned char *styles) {
448 if (line >= 0) {
449 annotations.EnsureLength(line+1);
450 if (!annotations[line]) {
451 annotations[line] = AllocateAnnotation(0, IndividualStyles);
452 } else {
453 const AnnotationHeader *pahSource = reinterpret_cast<AnnotationHeader *>(annotations[line].get());
454 if (pahSource->style != IndividualStyles) {
455 std::unique_ptr<char[]>allocation = AllocateAnnotation(pahSource->length, IndividualStyles);
456 AnnotationHeader *pahAlloc = reinterpret_cast<AnnotationHeader *>(allocation.get());
457 pahAlloc->length = pahSource->length;
458 pahAlloc->lines = pahSource->lines;
459 memcpy(allocation.get() + sizeof(AnnotationHeader), annotations[line].get() + sizeof(AnnotationHeader), pahSource->length);
460 annotations[line] = std::move(allocation);
461 }
462 }
463 AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line].get());
464 pah->style = IndividualStyles;
465 memcpy(annotations[line].get() + sizeof(AnnotationHeader) + pah->length, styles, pah->length);
466 }
467}
468
470 if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
471 return reinterpret_cast<AnnotationHeader *>(annotations[line].get())->length;
472 else
473 return 0;
474}
475
477 if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line])
478 return reinterpret_cast<AnnotationHeader *>(annotations[line].get())->lines;
479 else
480 return 0;
481}
482
484}
485
487 tabstops.DeleteAll();
488}
489
491 if (tabstops.Length()) {
492 tabstops.EnsureLength(line);
493 tabstops.Insert(line, nullptr);
494 }
495}
496
498 if (tabstops.Length()) {
499 tabstops.EnsureLength(line);
500 tabstops.InsertEmpty(line, lines);
501 }
502}
503
505 if (tabstops.Length() > line) {
506 tabstops[line].reset();
507 tabstops.Delete(line);
508 }
509}
510
512 if (line < tabstops.Length()) {
513 TabstopList *tl = tabstops[line].get();
514 if (tl) {
515 tl->clear();
516 return true;
517 }
518 }
519 return false;
520}
521
523 tabstops.EnsureLength(line + 1);
524 if (!tabstops[line]) {
525 tabstops[line] = Sci::make_unique<TabstopList>();
526 }
527
528 TabstopList *tl = tabstops[line].get();
529 if (tl) {
530 // tabstop positions are kept in order - insert in the right place
531 std::vector<int>::iterator it = std::lower_bound(tl->begin(), tl->end(), x);
532 // don't insert duplicates
533 if (it == tl->end() || *it != x) {
534 tl->insert(it, x);
535 return true;
536 }
537 }
538 return false;
539}
540
541int LineTabstops::GetNextTabstop(Sci::Line line, int x) const noexcept {
542 if (line < tabstops.Length()) {
543 TabstopList *tl = tabstops[line].get();
544 if (tl) {
545 for (const int i : *tl) {
546 if (i > x) {
547 return i;
548 }
549 }
550 }
551 }
552 return 0;
553}
Manages the text of the document.
Data structure used to partition an interval.
Manages data associated with each line of the document.
Interface to platform facilities.
Defines global type name Position in the Sci internal namespace.
Interface to the edit control.
#define SC_FOLDLEVELBASE
Definition: Scintilla.h:494
#define SC_FOLDLEVELHEADERFLAG
Definition: Scintilla.h:496
Main data structure for holding arrays that handle insertions and deletions efficiently.
void InsertLines(Sci::Line line, Sci::Line lines) override
Definition: PerLine.cxx:374
bool MultipleStyles(Sci::Line line) const noexcept
Definition: PerLine.cxx:388
void Init() override
Definition: PerLine.cxx:363
~LineAnnotation() override
Definition: PerLine.cxx:360
SplitVector< std::unique_ptr< char[]> > annotations
Definition: PerLine.h:120
void RemoveLine(Sci::Line line) override
Definition: PerLine.cxx:381
const char * Text(Sci::Line line) const noexcept
Definition: PerLine.cxx:402
void SetText(Sci::Line line, const char *text)
Definition: PerLine.cxx:416
int Length(Sci::Line line) const noexcept
Definition: PerLine.cxx:469
void SetStyles(Sci::Line line, const unsigned char *styles)
Definition: PerLine.cxx:447
int Style(Sci::Line line) const noexcept
Definition: PerLine.cxx:395
void InsertLine(Sci::Line line) override
Definition: PerLine.cxx:367
void SetStyle(Sci::Line line, int style)
Definition: PerLine.cxx:439
const unsigned char * Styles(Sci::Line line) const noexcept
Definition: PerLine.cxx:409
int Lines(Sci::Line line) const noexcept
Definition: PerLine.cxx:476
int SetLevel(Sci::Line line, int level, Sci::Line lines)
Definition: PerLine.cxx:259
SplitVector< int > levels
Definition: PerLine.h:77
void InsertLines(Sci::Line line, Sci::Line lines) override
Definition: PerLine.cxx:231
void ExpandLevels(Sci::Line sizeNew=-1)
Definition: PerLine.cxx:251
void InsertLine(Sci::Line line) override
Definition: PerLine.cxx:224
~LineLevels() override
Definition: PerLine.cxx:217
void Init() override
Definition: PerLine.cxx:220
int GetLevel(Sci::Line line) const noexcept
Definition: PerLine.cxx:273
void RemoveLine(Sci::Line line) override
Definition: PerLine.cxx:238
void MergeMarkers(Sci::Line line)
Definition: PerLine.cxx:145
int handleCurrent
Handles are allocated sequentially and should never have to be reused as 32 bit ints are very big.
Definition: PerLine.h:50
int HandleFromLine(Sci::Line line, int which) const noexcept
Definition: PerLine.cxx:129
~LineMarkers() override
Definition: PerLine.cxx:91
void DeleteMarkFromHandle(int markerHandle)
Definition: PerLine.cxx:207
int AddMark(Sci::Line line, int markerNum, Sci::Line lines)
Definition: PerLine.cxx:173
Sci::Line MarkerNext(Sci::Line lineStart, int mask) const noexcept
Definition: PerLine.cxx:161
void Init() override
Definition: PerLine.cxx:94
void InsertLine(Sci::Line line) override
Definition: PerLine.cxx:98
Sci::Line LineFromHandle(int markerHandle) const noexcept
Definition: PerLine.cxx:120
int NumberFromLine(Sci::Line line, int which) const noexcept
Definition: PerLine.cxx:137
SplitVector< std::unique_ptr< MarkerHandleSet > > markers
Definition: PerLine.h:48
int MarkValue(Sci::Line line) const noexcept
Definition: PerLine.cxx:154
void RemoveLine(Sci::Line line) override
Definition: PerLine.cxx:110
void InsertLines(Sci::Line line, Sci::Line lines) override
Definition: PerLine.cxx:104
bool DeleteMark(Sci::Line line, int markerNum, bool all)
Definition: PerLine.cxx:191
void InsertLine(Sci::Line line) override
Definition: PerLine.cxx:288
void Init() override
Definition: PerLine.cxx:284
Sci::Line GetMaxLineState() const noexcept
Definition: PerLine.cxx:324
int GetLineState(Sci::Line line)
Definition: PerLine.cxx:317
int SetLineState(Sci::Line line, int state)
Definition: PerLine.cxx:310
SplitVector< int > lineStates
Definition: PerLine.h:99
void InsertLines(Sci::Line line, Sci::Line lines) override
Definition: PerLine.cxx:296
~LineState() override
Definition: PerLine.cxx:281
void RemoveLine(Sci::Line line) override
Definition: PerLine.cxx:304
void RemoveLine(Sci::Line line) override
Definition: PerLine.cxx:504
SplitVector< std::unique_ptr< TabstopList > > tabstops
Definition: PerLine.h:150
void InsertLine(Sci::Line line) override
Definition: PerLine.cxx:490
bool AddTabstop(Sci::Line line, int x)
Definition: PerLine.cxx:522
void Init() override
Definition: PerLine.cxx:486
void InsertLines(Sci::Line line, Sci::Line lines) override
Definition: PerLine.cxx:497
bool ClearTabstops(Sci::Line line) noexcept
Definition: PerLine.cxx:511
~LineTabstops() override
Definition: PerLine.cxx:483
int GetNextTabstop(Sci::Line line, int x) const noexcept
Definition: PerLine.cxx:541
A marker handle set contains any number of MarkerHandleNumbers.
Definition: PerLine.h:26
int MarkValue() const noexcept
Bit set of marker numbers.
Definition: PerLine.cxx:40
MarkerHandleNumber const * GetMarkerHandleNumber(int which) const noexcept
Definition: PerLine.cxx:57
void CombineWith(MarkerHandleSet *other) noexcept
Definition: PerLine.cxx:87
bool Contains(int handle) const noexcept
Definition: PerLine.cxx:48
void RemoveHandle(int handle)
Definition: PerLine.cxx:71
bool Empty() const noexcept
Definition: PerLine.cxx:36
bool RemoveNumber(int markerNum, bool all)
Definition: PerLine.cxx:75
std::forward_list< MarkerHandleNumber > mhList
Definition: PerLine.h:27
bool InsertHandle(int handle, int markerNum)
Definition: PerLine.cxx:66
gchar * text
Definition: editor.c:83
vString * line
Definition: geany_cobol.c:133
ptrdiff_t Line
Definition: Position.h:20
Styling buffer using one element for each run rather than using a filled buffer.
Definition: Converter.h:9
std::vector< int > TabstopList
Definition: PerLine.h:147
long lines
Definition: stats.c:32
This holds the marker identifier and the marker type to display.
Definition: PerLine.h:17