]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexInno.cxx
53817509676730e2696d16b06668481b7eafd853
[wxWidgets.git] / src / stc / scintilla / src / LexInno.cxx
1 // Scintilla source code edit control
2 /** @file LexInno.cxx
3 ** Lexer for Inno Setup scripts.
4 **/
5 // Written by Friedrich Vedder <fvedd@t-online.de>, using code from LexOthers.cxx.
6 // The License.txt file describes the conditions under which this software may be distributed.
7
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include <stdio.h>
12 #include <stdarg.h>
13
14 #include "Platform.h"
15
16 #include "PropSet.h"
17 #include "Accessor.h"
18 #include "StyleContext.h"
19 #include "KeyWords.h"
20 #include "Scintilla.h"
21 #include "SciLexer.h"
22
23 #ifdef SCI_NAMESPACE
24 using namespace Scintilla;
25 #endif
26
27 static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler) {
28 int state = SCE_INNO_DEFAULT;
29 char chPrev;
30 char ch = 0;
31 char chNext = styler[startPos];
32 int lengthDoc = startPos + length;
33 char *buffer = new char[length];
34 int bufferCount = 0;
35 bool isBOL, isEOL, isWS, isBOLWS = 0;
36
37 WordList &sectionKeywords = *keywordLists[0];
38 WordList &standardKeywords = *keywordLists[1];
39 WordList &parameterKeywords = *keywordLists[2];
40 WordList &preprocessorKeywords = *keywordLists[3];
41 WordList &pascalKeywords = *keywordLists[4];
42 WordList &userKeywords = *keywordLists[5];
43
44 // Go through all provided text segment
45 // using the hand-written state machine shown below
46 styler.StartAt(startPos);
47 styler.StartSegment(startPos);
48 for (int i = startPos; i < lengthDoc; i++) {
49 chPrev = ch;
50 ch = chNext;
51 chNext = styler.SafeGetCharAt(i + 1);
52
53 if (styler.IsLeadByte(ch)) {
54 chNext = styler.SafeGetCharAt(i + 2);
55 i++;
56 continue;
57 }
58
59 isBOL = (chPrev == 0) || (chPrev == '\n') || (chPrev == '\r' && ch != '\n');
60 isBOLWS = (isBOL) ? 1 : (isBOLWS && (chPrev == ' ' || chPrev == '\t'));
61 isEOL = (ch == '\n' || ch == '\r');
62 isWS = (ch == ' ' || ch == '\t');
63
64 switch(state) {
65 case SCE_INNO_DEFAULT:
66 if (ch == ';' && isBOLWS) {
67 // Start of a comment
68 state = SCE_INNO_COMMENT;
69 } else if (ch == '[' && isBOLWS) {
70 // Start of a section name
71 bufferCount = 0;
72 state = SCE_INNO_SECTION;
73 } else if (ch == '#' && isBOLWS) {
74 // Start of a preprocessor directive
75 state = SCE_INNO_PREPROC;
76 } else if (ch == '{' && chNext == '#') {
77 // Start of a preprocessor inline directive
78 state = SCE_INNO_PREPROC_INLINE;
79 } else if ((ch == '{' && (chNext == ' ' || chNext == '\t'))
80 || (ch == '(' && chNext == '*')) {
81 // Start of a Pascal comment
82 state = SCE_INNO_COMMENT_PASCAL;
83 } else if (ch == '"') {
84 // Start of a double-quote string
85 state = SCE_INNO_STRING_DOUBLE;
86 } else if (ch == '\'') {
87 // Start of a single-quote string
88 state = SCE_INNO_STRING_SINGLE;
89 } else if (isascii(ch) && (isalpha(ch) || (ch == '_'))) {
90 // Start of an identifier
91 bufferCount = 0;
92 buffer[bufferCount++] = static_cast<char>(tolower(ch));
93 state = SCE_INNO_IDENTIFIER;
94 } else {
95 // Style it the default style
96 styler.ColourTo(i,SCE_INNO_DEFAULT);
97 }
98 break;
99
100 case SCE_INNO_COMMENT:
101 if (isEOL) {
102 state = SCE_INNO_DEFAULT;
103 styler.ColourTo(i,SCE_INNO_COMMENT);
104 }
105 break;
106
107 case SCE_INNO_IDENTIFIER:
108 if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
109 buffer[bufferCount++] = static_cast<char>(tolower(ch));
110 } else {
111 state = SCE_INNO_DEFAULT;
112 buffer[bufferCount] = '\0';
113
114 // Check if the buffer contains a keyword
115 if (standardKeywords.InList(buffer)) {
116 styler.ColourTo(i-1,SCE_INNO_KEYWORD);
117 } else if (parameterKeywords.InList(buffer)) {
118 styler.ColourTo(i-1,SCE_INNO_PARAMETER);
119 } else if (pascalKeywords.InList(buffer)) {
120 styler.ColourTo(i-1,SCE_INNO_KEYWORD_PASCAL);
121 } else if (userKeywords.InList(buffer)) {
122 styler.ColourTo(i-1,SCE_INNO_KEYWORD_USER);
123 } else {
124 styler.ColourTo(i-1,SCE_INNO_DEFAULT);
125 }
126
127 // Push back the faulty character
128 chNext = styler[i--];
129 ch = chPrev;
130 }
131 break;
132
133 case SCE_INNO_SECTION:
134 if (ch == ']') {
135 state = SCE_INNO_DEFAULT;
136 buffer[bufferCount] = '\0';
137
138 // Check if the buffer contains a section name
139 if (sectionKeywords.InList(buffer)) {
140 styler.ColourTo(i,SCE_INNO_SECTION);
141 } else {
142 styler.ColourTo(i,SCE_INNO_DEFAULT);
143 }
144 } else if (isascii(ch) && (isalnum(ch) || (ch == '_'))) {
145 buffer[bufferCount++] = static_cast<char>(tolower(ch));
146 } else {
147 state = SCE_INNO_DEFAULT;
148 styler.ColourTo(i,SCE_INNO_DEFAULT);
149 }
150 break;
151
152 case SCE_INNO_PREPROC:
153 if (isWS || isEOL) {
154 if (isascii(chPrev) && isalpha(chPrev)) {
155 state = SCE_INNO_DEFAULT;
156 buffer[bufferCount] = '\0';
157
158 // Check if the buffer contains a preprocessor directive
159 if (preprocessorKeywords.InList(buffer)) {
160 styler.ColourTo(i-1,SCE_INNO_PREPROC);
161 } else {
162 styler.ColourTo(i-1,SCE_INNO_DEFAULT);
163 }
164
165 // Push back the faulty character
166 chNext = styler[i--];
167 ch = chPrev;
168 }
169 } else if (isascii(ch) && isalpha(ch)) {
170 if (chPrev == '#' || chPrev == ' ' || chPrev == '\t')
171 bufferCount = 0;
172 buffer[bufferCount++] = static_cast<char>(tolower(ch));
173 }
174 break;
175
176 case SCE_INNO_STRING_DOUBLE:
177 if (ch == '"' || isEOL) {
178 state = SCE_INNO_DEFAULT;
179 styler.ColourTo(i,SCE_INNO_STRING_DOUBLE);
180 }
181 break;
182
183 case SCE_INNO_STRING_SINGLE:
184 if (ch == '\'' || isEOL) {
185 state = SCE_INNO_DEFAULT;
186 styler.ColourTo(i,SCE_INNO_STRING_SINGLE);
187 }
188 break;
189
190 case SCE_INNO_PREPROC_INLINE:
191 if (ch == '}') {
192 state = SCE_INNO_DEFAULT;
193 styler.ColourTo(i,SCE_INNO_PREPROC_INLINE);
194 } else if (isEOL) {
195 state = SCE_INNO_DEFAULT;
196 styler.ColourTo(i,SCE_INNO_DEFAULT);
197 }
198 break;
199
200 case SCE_INNO_COMMENT_PASCAL:
201 if (ch == '}' || (ch == ')' && chPrev == '*')) {
202 state = SCE_INNO_DEFAULT;
203 styler.ColourTo(i,SCE_INNO_COMMENT_PASCAL);
204 } else if (isEOL) {
205 state = SCE_INNO_DEFAULT;
206 styler.ColourTo(i,SCE_INNO_DEFAULT);
207 }
208 break;
209
210 }
211 }
212 delete []buffer;
213 }
214
215 static const char * const innoWordListDesc[] = {
216 "Sections",
217 "Keywords",
218 "Parameters",
219 "Preprocessor directives",
220 "Pascal keywords",
221 "User defined keywords",
222 0
223 };
224
225 static void FoldInnoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
226 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
227
228 unsigned int endPos = startPos + length;
229 int visibleChars = 0;
230 int lineCurrent = styler.GetLine(startPos);
231
232 char chNext = styler[startPos];
233 int styleNext = styler.StyleAt(startPos);
234 bool headerPoint = false;
235 int lev;
236
237 for (unsigned int i = startPos; i < endPos; i++) {
238 char ch = chNext;
239 chNext = styler[i+1];
240
241 int style = styleNext;
242 styleNext = styler.StyleAt(i + 1);
243 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
244
245 if (style == SCE_INNO_SECTION)
246 headerPoint = true;
247
248 if (atEOL) {
249 lev = SC_FOLDLEVELBASE;
250
251 if (lineCurrent > 0) {
252 int levelPrevious = styler.LevelAt(lineCurrent - 1);
253
254 if (levelPrevious & SC_FOLDLEVELHEADERFLAG)
255 lev = SC_FOLDLEVELBASE + 1;
256 else
257 lev = levelPrevious & SC_FOLDLEVELNUMBERMASK;
258 }
259
260 if (headerPoint)
261 lev = SC_FOLDLEVELBASE;
262
263 if (visibleChars == 0 && foldCompact)
264 lev |= SC_FOLDLEVELWHITEFLAG;
265
266 if (headerPoint)
267 lev |= SC_FOLDLEVELHEADERFLAG;
268
269 if (lev != styler.LevelAt(lineCurrent))
270 styler.SetLevel(lineCurrent, lev);
271
272 lineCurrent++;
273 visibleChars = 0;
274 headerPoint = false;
275 }
276 if (!isspacechar(ch))
277 visibleChars++;
278 }
279
280 if (lineCurrent > 0) {
281 int levelPrevious = styler.LevelAt(lineCurrent - 1);
282
283 if (levelPrevious & SC_FOLDLEVELHEADERFLAG)
284 lev = SC_FOLDLEVELBASE + 1;
285 else
286 lev = levelPrevious & SC_FOLDLEVELNUMBERMASK;
287 } else {
288 lev = SC_FOLDLEVELBASE;
289 }
290 int flagsNext = styler.LevelAt(lineCurrent);
291 styler.SetLevel(lineCurrent, lev | flagsNext & ~SC_FOLDLEVELNUMBERMASK);
292 }
293
294 LexerModule lmInno(SCLEX_INNOSETUP, ColouriseInnoDoc, "inno", FoldInnoDoc, innoWordListDesc);