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