]>
Commit | Line | Data |
---|---|---|
1dcf666d RD |
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 | #ifdef SCI_NAMESPACE | |
12 | namespace Scintilla { | |
13 | #endif | |
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 | int startPos; | |
26 | int endPos; | |
27 | int codePage; | |
28 | int lenDoc; | |
29 | int mask; | |
30 | char styleBuf[bufferSize]; | |
31 | int validLen; | |
32 | char chFlags; | |
33 | char chWhile; | |
34 | unsigned int startSeg; | |
35 | int startPosStyling; | |
36 | ||
37 | void Fill(int position) { | |
38 | startPos = position - slopSize; | |
39 | if (startPos + bufferSize > lenDoc) | |
40 | startPos = lenDoc - bufferSize; | |
41 | if (startPos < 0) | |
42 | startPos = 0; | |
43 | endPos = startPos + bufferSize; | |
44 | if (endPos > lenDoc) | |
45 | endPos = lenDoc; | |
46 | ||
47 | pAccess->GetCharRange(buf, startPos, endPos-startPos); | |
48 | buf[endPos-startPos] = '\0'; | |
49 | } | |
50 | ||
51 | public: | |
52 | LexAccessor(IDocument *pAccess_) : | |
53 | pAccess(pAccess_), startPos(extremePosition), endPos(0), | |
54 | codePage(pAccess->CodePage()), lenDoc(pAccess->Length()), | |
55 | mask(127), validLen(0), chFlags(0), chWhile(0), | |
56 | startSeg(0), startPosStyling(0) { | |
57 | } | |
58 | char operator[](int position) { | |
59 | if (position < startPos || position >= endPos) { | |
60 | Fill(position); | |
61 | } | |
62 | return buf[position - startPos]; | |
63 | } | |
64 | /** Safe version of operator[], returning a defined value for invalid position. */ | |
65 | char SafeGetCharAt(int position, char chDefault=' ') { | |
66 | if (position < startPos || position >= endPos) { | |
67 | Fill(position); | |
68 | if (position < startPos || position >= endPos) { | |
69 | // Position is outside range of document | |
70 | return chDefault; | |
71 | } | |
72 | } | |
73 | return buf[position - startPos]; | |
74 | } | |
75 | bool IsLeadByte(char ch) { | |
76 | return pAccess->IsDBCSLeadByte(ch); | |
77 | } | |
78 | ||
79 | bool Match(int pos, const char *s) { | |
80 | for (int i=0; *s; i++) { | |
81 | if (*s != SafeGetCharAt(pos+i)) | |
82 | return false; | |
83 | s++; | |
84 | } | |
85 | return true; | |
86 | } | |
87 | char StyleAt(int position) { | |
88 | return static_cast<char>(pAccess->StyleAt(position) & mask); | |
89 | } | |
90 | int GetLine(int position) { | |
91 | return pAccess->LineFromPosition(position); | |
92 | } | |
93 | int LineStart(int line) { | |
94 | return pAccess->LineStart(line); | |
95 | } | |
96 | int LevelAt(int line) { | |
97 | return pAccess->GetLevel(line); | |
98 | } | |
99 | int Length() const { | |
100 | return lenDoc; | |
101 | } | |
102 | void Flush() { | |
103 | startPos = extremePosition; | |
104 | if (validLen > 0) { | |
105 | pAccess->SetStyles(validLen, styleBuf); | |
106 | startPosStyling += validLen; | |
107 | validLen = 0; | |
108 | } | |
109 | } | |
110 | int GetLineState(int line) { | |
111 | return pAccess->GetLineState(line); | |
112 | } | |
113 | int SetLineState(int line, int state) { | |
114 | return pAccess->SetLineState(line, state); | |
115 | } | |
116 | // Style setting | |
117 | void StartAt(unsigned int start, char chMask=31) { | |
118 | // Store the mask specified for use with StyleAt. | |
119 | mask = chMask; | |
120 | pAccess->StartStyling(start, chMask); | |
121 | startPosStyling = start; | |
122 | } | |
123 | void SetFlags(char chFlags_, char chWhile_) { | |
124 | chFlags = chFlags_; | |
125 | chWhile = chWhile_; | |
126 | } | |
127 | unsigned int GetStartSegment() const { | |
128 | return startSeg; | |
129 | } | |
130 | void StartSegment(unsigned int pos) { | |
131 | startSeg = pos; | |
132 | } | |
133 | void ColourTo(unsigned int pos, int chAttr) { | |
134 | // Only perform styling if non empty range | |
135 | if (pos != startSeg - 1) { | |
136 | assert(pos >= startSeg); | |
137 | if (pos < startSeg) { | |
138 | return; | |
139 | } | |
140 | ||
141 | if (validLen + (pos - startSeg + 1) >= bufferSize) | |
142 | Flush(); | |
143 | if (validLen + (pos - startSeg + 1) >= bufferSize) { | |
144 | // Too big for buffer so send directly | |
145 | pAccess->SetStyleFor(pos - startSeg + 1, static_cast<char>(chAttr)); | |
146 | } else { | |
147 | if (chAttr != chWhile) | |
148 | chFlags = 0; | |
149 | chAttr = static_cast<char>(chAttr | chFlags); | |
150 | for (unsigned int i = startSeg; i <= pos; i++) { | |
151 | assert((startPosStyling + validLen) < Length()); | |
152 | styleBuf[validLen++] = static_cast<char>(chAttr); | |
153 | } | |
154 | } | |
155 | } | |
156 | startSeg = pos+1; | |
157 | } | |
158 | void SetLevel(int line, int level) { | |
159 | pAccess->SetLevel(line, level); | |
160 | } | |
161 | void IndicatorFill(int start, int end, int indicator, int value) { | |
162 | pAccess->DecorationSetCurrentIndicator(indicator); | |
163 | pAccess->DecorationFillRange(start, value, end - start); | |
164 | } | |
165 | ||
166 | void ChangeLexerState(int start, int end) { | |
167 | pAccess->ChangeLexerState(start, end); | |
168 | } | |
169 | }; | |
170 | ||
171 | #ifdef SCI_NAMESPACE | |
172 | } | |
173 | #endif | |
174 | ||
175 | #endif |