Update Scintilla to version 3.5.3
[TortoiseGit.git] / ext / scintilla / lexlib / LexAccessor.h
blobba4a0e27add3d6d2d7b3afcc5f6c5615312aef7c
1 // Scintilla source code edit control
2 /** @file LexAccessor.h
3 ** Interfaces between Scintilla and lexers.
4 **/
5 // Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
8 #ifndef LEXACCESSOR_H
9 #define LEXACCESSOR_H
11 #ifdef SCI_NAMESPACE
12 namespace Scintilla {
13 #endif
15 enum EncodingType { enc8bit, encUnicode, encDBCS };
17 class LexAccessor {
18 private:
19 IDocument *pAccess;
20 enum {extremePosition=0x7FFFFFFF};
21 /** @a bufferSize is a trade off between time taken to copy the characters
22 * and retrieval overhead.
23 * @a slopSize positions the buffer before the desired position
24 * in case there is some backtracking. */
25 enum {bufferSize=4000, slopSize=bufferSize/8};
26 char buf[bufferSize+1];
27 int startPos;
28 int endPos;
29 int codePage;
30 enum EncodingType encodingType;
31 int lenDoc;
32 char styleBuf[bufferSize];
33 int validLen;
34 unsigned int startSeg;
35 int startPosStyling;
36 int documentVersion;
38 void Fill(int position) {
39 startPos = position - slopSize;
40 if (startPos + bufferSize > lenDoc)
41 startPos = lenDoc - bufferSize;
42 if (startPos < 0)
43 startPos = 0;
44 endPos = startPos + bufferSize;
45 if (endPos > lenDoc)
46 endPos = lenDoc;
48 pAccess->GetCharRange(buf, startPos, endPos-startPos);
49 buf[endPos-startPos] = '\0';
52 public:
53 explicit LexAccessor(IDocument *pAccess_) :
54 pAccess(pAccess_), startPos(extremePosition), endPos(0),
55 codePage(pAccess->CodePage()),
56 encodingType(enc8bit),
57 lenDoc(pAccess->Length()),
58 validLen(0),
59 startSeg(0), startPosStyling(0),
60 documentVersion(pAccess->Version()) {
61 // Prevent warnings by static analyzers about uninitialized buf and styleBuf.
62 buf[0] = 0;
63 styleBuf[0] = 0;
64 switch (codePage) {
65 case 65001:
66 encodingType = encUnicode;
67 break;
68 case 932:
69 case 936:
70 case 949:
71 case 950:
72 case 1361:
73 encodingType = encDBCS;
76 char operator[](int position) {
77 if (position < startPos || position >= endPos) {
78 Fill(position);
80 return buf[position - startPos];
82 IDocumentWithLineEnd *MultiByteAccess() const {
83 if (documentVersion >= dvLineEnd) {
84 return static_cast<IDocumentWithLineEnd *>(pAccess);
86 return 0;
88 /** Safe version of operator[], returning a defined value for invalid position. */
89 char SafeGetCharAt(int position, char chDefault=' ') {
90 if (position < startPos || position >= endPos) {
91 Fill(position);
92 if (position < startPos || position >= endPos) {
93 // Position is outside range of document
94 return chDefault;
97 return buf[position - startPos];
99 bool IsLeadByte(char ch) const {
100 return pAccess->IsDBCSLeadByte(ch);
102 EncodingType Encoding() const {
103 return encodingType;
105 bool Match(int pos, const char *s) {
106 for (int i=0; *s; i++) {
107 if (*s != SafeGetCharAt(pos+i))
108 return false;
109 s++;
111 return true;
113 char StyleAt(int position) const {
114 return static_cast<char>(pAccess->StyleAt(position));
116 int GetLine(int position) const {
117 return pAccess->LineFromPosition(position);
119 int LineStart(int line) const {
120 return pAccess->LineStart(line);
122 int LineEnd(int line) {
123 if (documentVersion >= dvLineEnd) {
124 return (static_cast<IDocumentWithLineEnd *>(pAccess))->LineEnd(line);
125 } else {
126 // Old interface means only '\r', '\n' and '\r\n' line ends.
127 int startNext = pAccess->LineStart(line+1);
128 char chLineEnd = SafeGetCharAt(startNext-1);
129 if (chLineEnd == '\n' && (SafeGetCharAt(startNext-2) == '\r'))
130 return startNext - 2;
131 else
132 return startNext - 1;
135 int LevelAt(int line) const {
136 return pAccess->GetLevel(line);
138 int Length() const {
139 return lenDoc;
141 void Flush() {
142 if (validLen > 0) {
143 pAccess->SetStyles(validLen, styleBuf);
144 startPosStyling += validLen;
145 validLen = 0;
148 int GetLineState(int line) const {
149 return pAccess->GetLineState(line);
151 int SetLineState(int line, int state) {
152 return pAccess->SetLineState(line, state);
154 // Style setting
155 void StartAt(unsigned int start) {
156 pAccess->StartStyling(start, '\377');
157 startPosStyling = start;
159 unsigned int GetStartSegment() const {
160 return startSeg;
162 void StartSegment(unsigned int pos) {
163 startSeg = pos;
165 void ColourTo(unsigned int pos, int chAttr) {
166 // Only perform styling if non empty range
167 if (pos != startSeg - 1) {
168 assert(pos >= startSeg);
169 if (pos < startSeg) {
170 return;
173 if (validLen + (pos - startSeg + 1) >= bufferSize)
174 Flush();
175 if (validLen + (pos - startSeg + 1) >= bufferSize) {
176 // Too big for buffer so send directly
177 pAccess->SetStyleFor(pos - startSeg + 1, static_cast<char>(chAttr));
178 } else {
179 for (unsigned int i = startSeg; i <= pos; i++) {
180 assert((startPosStyling + validLen) < Length());
181 styleBuf[validLen++] = static_cast<char>(chAttr);
185 startSeg = pos+1;
187 void SetLevel(int line, int level) {
188 pAccess->SetLevel(line, level);
190 void IndicatorFill(int start, int end, int indicator, int value) {
191 pAccess->DecorationSetCurrentIndicator(indicator);
192 pAccess->DecorationFillRange(start, value, end - start);
195 void ChangeLexerState(int start, int end) {
196 pAccess->ChangeLexerState(start, end);
200 #ifdef SCI_NAMESPACE
202 #endif
204 #endif