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.
7 
8 #ifndef LEXACCESSOR_H
9 #define LEXACCESSOR_H
10 
11 namespace Scintilla {
12 
13 enum class EncodingType { eightBit, unicode, dbcs };
14 
15 class LexAccessor {
16 private:
17 	IDocument *pAccess;
18 	enum {extremePosition=0x7FFFFFFF};
19 	/** @a bufferSize is a trade off between time taken to copy the characters
20 	 * and retrieval overhead.
21 	 * @a slopSize positions the buffer before the desired position
22 	 * in case there is some backtracking. */
23 	enum {bufferSize=4000, slopSize=bufferSize/8};
24 	char buf[bufferSize+1];
25 	Sci_Position startPos;
26 	Sci_Position endPos;
27 	int codePage;
28 	enum EncodingType encodingType;
29 	Sci_Position lenDoc;
30 	char styleBuf[bufferSize];
31 	Sci_Position validLen;
32 	Sci_PositionU startSeg;
33 	Sci_Position startPosStyling;
34 	int documentVersion;
35 
Fill(Sci_Position position)36 	void Fill(Sci_Position position) {
37 		startPos = position - slopSize;
38 		if (startPos + bufferSize > lenDoc)
39 			startPos = lenDoc - bufferSize;
40 		if (startPos < 0)
41 			startPos = 0;
42 		endPos = startPos + bufferSize;
43 		if (endPos > lenDoc)
44 			endPos = lenDoc;
45 
46 		pAccess->GetCharRange(buf, startPos, endPos-startPos);
47 		buf[endPos-startPos] = '\0';
48 	}
49 
50 public:
LexAccessor(IDocument * pAccess_)51 	explicit LexAccessor(IDocument *pAccess_) :
52 		pAccess(pAccess_), startPos(extremePosition), endPos(0),
53 		codePage(pAccess->CodePage()),
54 		encodingType(EncodingType::eightBit),
55 		lenDoc(pAccess->Length()),
56 		validLen(0),
57 		startSeg(0), startPosStyling(0),
58 		documentVersion(pAccess->Version()) {
59 		// Prevent warnings by static analyzers about uninitialized buf and styleBuf.
60 		buf[0] = 0;
61 		styleBuf[0] = 0;
62 		switch (codePage) {
63 		case 65001:
64 			encodingType = EncodingType::unicode;
65 			break;
66 		case 932:
67 		case 936:
68 		case 949:
69 		case 950:
70 		case 1361:
71 			encodingType = EncodingType::dbcs;
72 		}
73 	}
74 	char operator[](Sci_Position position) {
75 		if (position < startPos || position >= endPos) {
76 			Fill(position);
77 		}
78 		return buf[position - startPos];
79 	}
MultiByteAccess()80 	IDocument *MultiByteAccess() const noexcept {
81 		return pAccess;
82 	}
83 	/** Safe version of operator[], returning a defined value for invalid position. */
84 	char SafeGetCharAt(Sci_Position position, char chDefault=' ') {
85 		if (position < startPos || position >= endPos) {
86 			Fill(position);
87 			if (position < startPos || position >= endPos) {
88 				// Position is outside range of document
89 				return chDefault;
90 			}
91 		}
92 		return buf[position - startPos];
93 	}
IsLeadByte(char ch)94 	bool IsLeadByte(char ch) const {
95 		return pAccess->IsDBCSLeadByte(ch);
96 	}
Encoding()97 	EncodingType Encoding() const noexcept {
98 		return encodingType;
99 	}
Match(Sci_Position pos,const char * s)100 	bool Match(Sci_Position pos, const char *s) {
101 		for (int i=0; *s; i++) {
102 			if (*s != SafeGetCharAt(pos+i))
103 				return false;
104 			s++;
105 		}
106 		return true;
107 	}
StyleAt(Sci_Position position)108 	char StyleAt(Sci_Position position) const {
109 		return pAccess->StyleAt(position);
110 	}
GetLine(Sci_Position position)111 	Sci_Position GetLine(Sci_Position position) const {
112 		return pAccess->LineFromPosition(position);
113 	}
LineStart(Sci_Position line)114 	Sci_Position LineStart(Sci_Position line) const {
115 		return pAccess->LineStart(line);
116 	}
LineEnd(Sci_Position line)117 	Sci_Position LineEnd(Sci_Position line) const {
118 		return pAccess->LineEnd(line);
119 	}
LevelAt(Sci_Position line)120 	int LevelAt(Sci_Position line) const {
121 		return pAccess->GetLevel(line);
122 	}
Length()123 	Sci_Position Length() const {
124 		return lenDoc;
125 	}
Flush()126 	void Flush() {
127 		if (validLen > 0) {
128 			pAccess->SetStyles(validLen, styleBuf);
129 			startPosStyling += validLen;
130 			validLen = 0;
131 		}
132 	}
GetLineState(Sci_Position line)133 	int GetLineState(Sci_Position line) const {
134 		return pAccess->GetLineState(line);
135 	}
SetLineState(Sci_Position line,int state)136 	int SetLineState(Sci_Position line, int state) {
137 		return pAccess->SetLineState(line, state);
138 	}
139 	// Style setting
StartAt(Sci_PositionU start)140 	void StartAt(Sci_PositionU start) {
141 		pAccess->StartStyling(start);
142 		startPosStyling = start;
143 	}
GetStartSegment()144 	Sci_PositionU GetStartSegment() const {
145 		return startSeg;
146 	}
StartSegment(Sci_PositionU pos)147 	void StartSegment(Sci_PositionU pos) {
148 		startSeg = pos;
149 	}
ColourTo(Sci_PositionU pos,int chAttr)150 	void ColourTo(Sci_PositionU pos, int chAttr) {
151 		// Only perform styling if non empty range
152 		if (pos != startSeg - 1) {
153 			assert(pos >= startSeg);
154 			if (pos < startSeg) {
155 				return;
156 			}
157 
158 			if (validLen + (pos - startSeg + 1) >= bufferSize)
159 				Flush();
160 			const char attr = static_cast<char>(chAttr);
161 			if (validLen + (pos - startSeg + 1) >= bufferSize) {
162 				// Too big for buffer so send directly
163 				pAccess->SetStyleFor(pos - startSeg + 1, attr);
164 			} else {
165 				for (Sci_PositionU i = startSeg; i <= pos; i++) {
166 					assert((startPosStyling + validLen) < Length());
167 					styleBuf[validLen++] = attr;
168 				}
169 			}
170 		}
171 		startSeg = pos+1;
172 	}
SetLevel(Sci_Position line,int level)173 	void SetLevel(Sci_Position line, int level) {
174 		pAccess->SetLevel(line, level);
175 	}
IndicatorFill(Sci_Position start,Sci_Position end,int indicator,int value)176 	void IndicatorFill(Sci_Position start, Sci_Position end, int indicator, int value) {
177 		pAccess->DecorationSetCurrentIndicator(indicator);
178 		pAccess->DecorationFillRange(start, value, end - start);
179 	}
180 
ChangeLexerState(Sci_Position start,Sci_Position end)181 	void ChangeLexerState(Sci_Position start, Sci_Position end) {
182 		pAccess->ChangeLexerState(start, end);
183 	}
184 };
185 
186 struct LexicalClass {
187 	int value;
188 	const char *name;
189 	const char *tags;
190 	const char *description;
191 };
192 
193 }
194 
195 #endif
196