]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexPS.cxx
Interface fixes for Phoenix
[wxWidgets.git] / src / stc / scintilla / src / LexPS.cxx
1 // Scintilla source code edit control
2 /** @file LexPS.cxx
3 ** Lexer for PostScript
4 **
5 ** Written by Nigel Hathaway <nigel@bprj.co.uk>.
6 ** The License.txt file describes the conditions under which this software may be distributed.
7 **/
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <stdarg.h>
13 #include <stdio.h>
14
15 #include "Platform.h"
16
17 #include "PropSet.h"
18 #include "Accessor.h"
19 #include "StyleContext.h"
20 #include "KeyWords.h"
21 #include "Scintilla.h"
22 #include "SciLexer.h"
23
24 #ifdef SCI_NAMESPACE
25 using namespace Scintilla;
26 #endif
27
28 static inline bool IsASelfDelimitingChar(const int ch) {
29 return (ch == '[' || ch == ']' || ch == '{' || ch == '}' ||
30 ch == '/' || ch == '<' || ch == '>' ||
31 ch == '(' || ch == ')' || ch == '%');
32 }
33
34 static inline bool IsAWhitespaceChar(const int ch) {
35 return (ch == ' ' || ch == '\t' || ch == '\r' ||
36 ch == '\n' || ch == '\f' || ch == '\0');
37 }
38
39 static bool IsABaseNDigit(const int ch, const int base) {
40 int maxdig = '9';
41 int letterext = -1;
42
43 if (base <= 10)
44 maxdig = '0' + base - 1;
45 else
46 letterext = base - 11;
47
48 return ((ch >= '0' && ch <= maxdig) ||
49 (ch >= 'A' && ch <= ('A' + letterext)) ||
50 (ch >= 'a' && ch <= ('a' + letterext)));
51 }
52
53 static inline bool IsABase85Char(const int ch) {
54 return ((ch >= '!' && ch <= 'u') || ch == 'z');
55 }
56
57 static void ColourisePSDoc(
58 unsigned int startPos,
59 int length,
60 int initStyle,
61 WordList *keywordlists[],
62 Accessor &styler) {
63
64 WordList &keywords1 = *keywordlists[0];
65 WordList &keywords2 = *keywordlists[1];
66 WordList &keywords3 = *keywordlists[2];
67 WordList &keywords4 = *keywordlists[3];
68 WordList &keywords5 = *keywordlists[4];
69
70 StyleContext sc(startPos, length, initStyle, styler);
71
72 bool tokenizing = styler.GetPropertyInt("ps.tokenize") != 0;
73 int pslevel = styler.GetPropertyInt("ps.level", 3);
74 int lineCurrent = styler.GetLine(startPos);
75 int nestTextCurrent = 0;
76 if (lineCurrent > 0 && initStyle == SCE_PS_TEXT)
77 nestTextCurrent = styler.GetLineState(lineCurrent - 1);
78 int numRadix = 0;
79 bool numHasPoint = false;
80 bool numHasExponent = false;
81 bool numHasSign = false;
82
83 // Clear out existing tokenization
84 if (tokenizing && length > 0) {
85 styler.StartAt(startPos, static_cast<char>(INDIC2_MASK));
86 styler.ColourTo(startPos + length-1, 0);
87 styler.Flush();
88 styler.StartAt(startPos);
89 styler.StartSegment(startPos);
90 }
91
92 for (; sc.More(); sc.Forward()) {
93 if (sc.atLineStart)
94 lineCurrent = styler.GetLine(sc.currentPos);
95
96 // Determine if the current state should terminate.
97 if (sc.state == SCE_PS_COMMENT || sc.state == SCE_PS_DSC_VALUE) {
98 if (sc.atLineEnd) {
99 sc.SetState(SCE_C_DEFAULT);
100 }
101 } else if (sc.state == SCE_PS_DSC_COMMENT) {
102 if (sc.ch == ':') {
103 sc.Forward();
104 if (!sc.atLineEnd)
105 sc.SetState(SCE_PS_DSC_VALUE);
106 else
107 sc.SetState(SCE_C_DEFAULT);
108 } else if (sc.atLineEnd) {
109 sc.SetState(SCE_C_DEFAULT);
110 } else if (IsAWhitespaceChar(sc.ch) && sc.ch != '\r') {
111 sc.ChangeState(SCE_PS_COMMENT);
112 }
113 } else if (sc.state == SCE_PS_NUMBER) {
114 if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) {
115 if ((sc.chPrev == '+' || sc.chPrev == '-' ||
116 sc.chPrev == 'E' || sc.chPrev == 'e') && numRadix == 0)
117 sc.ChangeState(SCE_PS_NAME);
118 sc.SetState(SCE_C_DEFAULT);
119 } else if (sc.ch == '#') {
120 if (numHasPoint || numHasExponent || numHasSign || numRadix != 0) {
121 sc.ChangeState(SCE_PS_NAME);
122 } else {
123 char szradix[5];
124 sc.GetCurrent(szradix, 4);
125 numRadix = atoi(szradix);
126 if (numRadix < 2 || numRadix > 36)
127 sc.ChangeState(SCE_PS_NAME);
128 }
129 } else if ((sc.ch == 'E' || sc.ch == 'e') && numRadix == 0) {
130 if (numHasExponent) {
131 sc.ChangeState(SCE_PS_NAME);
132 } else {
133 numHasExponent = true;
134 if (sc.chNext == '+' || sc.chNext == '-')
135 sc.Forward();
136 }
137 } else if (sc.ch == '.') {
138 if (numHasPoint || numHasExponent || numRadix != 0) {
139 sc.ChangeState(SCE_PS_NAME);
140 } else {
141 numHasPoint = true;
142 }
143 } else if (numRadix == 0) {
144 if (!IsABaseNDigit(sc.ch, 10))
145 sc.ChangeState(SCE_PS_NAME);
146 } else {
147 if (!IsABaseNDigit(sc.ch, numRadix))
148 sc.ChangeState(SCE_PS_NAME);
149 }
150 } else if (sc.state == SCE_PS_NAME || sc.state == SCE_PS_KEYWORD) {
151 if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) {
152 char s[100];
153 sc.GetCurrent(s, sizeof(s));
154 if ((pslevel >= 1 && keywords1.InList(s)) ||
155 (pslevel >= 2 && keywords2.InList(s)) ||
156 (pslevel >= 3 && keywords3.InList(s)) ||
157 keywords4.InList(s) || keywords5.InList(s)) {
158 sc.ChangeState(SCE_PS_KEYWORD);
159 }
160 sc.SetState(SCE_C_DEFAULT);
161 }
162 } else if (sc.state == SCE_PS_LITERAL || sc.state == SCE_PS_IMMEVAL) {
163 if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch))
164 sc.SetState(SCE_C_DEFAULT);
165 } else if (sc.state == SCE_PS_PAREN_ARRAY || sc.state == SCE_PS_PAREN_DICT ||
166 sc.state == SCE_PS_PAREN_PROC) {
167 sc.SetState(SCE_C_DEFAULT);
168 } else if (sc.state == SCE_PS_TEXT) {
169 if (sc.ch == '(') {
170 nestTextCurrent++;
171 } else if (sc.ch == ')') {
172 if (--nestTextCurrent == 0)
173 sc.ForwardSetState(SCE_PS_DEFAULT);
174 } else if (sc.ch == '\\') {
175 sc.Forward();
176 }
177 } else if (sc.state == SCE_PS_HEXSTRING) {
178 if (sc.ch == '>') {
179 sc.ForwardSetState(SCE_PS_DEFAULT);
180 } else if (!IsABaseNDigit(sc.ch, 16) && !IsAWhitespaceChar(sc.ch)) {
181 sc.SetState(SCE_PS_HEXSTRING);
182 styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
183 }
184 } else if (sc.state == SCE_PS_BASE85STRING) {
185 if (sc.Match('~', '>')) {
186 sc.Forward();
187 sc.ForwardSetState(SCE_PS_DEFAULT);
188 } else if (!IsABase85Char(sc.ch) && !IsAWhitespaceChar(sc.ch)) {
189 sc.SetState(SCE_PS_BASE85STRING);
190 styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
191 }
192 }
193
194 // Determine if a new state should be entered.
195 if (sc.state == SCE_C_DEFAULT) {
196 unsigned int tokenpos = sc.currentPos;
197
198 if (sc.ch == '[' || sc.ch == ']') {
199 sc.SetState(SCE_PS_PAREN_ARRAY);
200 } else if (sc.ch == '{' || sc.ch == '}') {
201 sc.SetState(SCE_PS_PAREN_PROC);
202 } else if (sc.ch == '/') {
203 if (sc.chNext == '/') {
204 sc.SetState(SCE_PS_IMMEVAL);
205 sc.Forward();
206 } else {
207 sc.SetState(SCE_PS_LITERAL);
208 }
209 } else if (sc.ch == '<') {
210 if (sc.chNext == '<') {
211 sc.SetState(SCE_PS_PAREN_DICT);
212 sc.Forward();
213 } else if (sc.chNext == '~') {
214 sc.SetState(SCE_PS_BASE85STRING);
215 sc.Forward();
216 } else {
217 sc.SetState(SCE_PS_HEXSTRING);
218 }
219 } else if (sc.ch == '>' && sc.chNext == '>') {
220 sc.SetState(SCE_PS_PAREN_DICT);
221 sc.Forward();
222 } else if (sc.ch == '>' || sc.ch == ')') {
223 sc.SetState(SCE_C_DEFAULT);
224 styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR);
225 } else if (sc.ch == '(') {
226 sc.SetState(SCE_PS_TEXT);
227 nestTextCurrent = 1;
228 } else if (sc.ch == '%') {
229 if (sc.chNext == '%' && sc.atLineStart) {
230 sc.SetState(SCE_PS_DSC_COMMENT);
231 sc.Forward();
232 if (sc.chNext == '+') {
233 sc.Forward();
234 sc.ForwardSetState(SCE_PS_DSC_VALUE);
235 }
236 } else {
237 sc.SetState(SCE_PS_COMMENT);
238 }
239 } else if ((sc.ch == '+' || sc.ch == '-' || sc.ch == '.') &&
240 IsABaseNDigit(sc.chNext, 10)) {
241 sc.SetState(SCE_PS_NUMBER);
242 numRadix = 0;
243 numHasPoint = (sc.ch == '.');
244 numHasExponent = false;
245 numHasSign = (sc.ch == '+' || sc.ch == '-');
246 } else if ((sc.ch == '+' || sc.ch == '-') && sc.chNext == '.' &&
247 IsABaseNDigit(sc.GetRelative(2), 10)) {
248 sc.SetState(SCE_PS_NUMBER);
249 numRadix = 0;
250 numHasPoint = false;
251 numHasExponent = false;
252 numHasSign = true;
253 } else if (IsABaseNDigit(sc.ch, 10)) {
254 sc.SetState(SCE_PS_NUMBER);
255 numRadix = 0;
256 numHasPoint = false;
257 numHasExponent = false;
258 numHasSign = false;
259 } else if (!IsAWhitespaceChar(sc.ch)) {
260 sc.SetState(SCE_PS_NAME);
261 }
262
263 // Mark the start of tokens
264 if (tokenizing && sc.state != SCE_C_DEFAULT && sc.state != SCE_PS_COMMENT &&
265 sc.state != SCE_PS_DSC_COMMENT && sc.state != SCE_PS_DSC_VALUE) {
266 styler.Flush();
267 styler.StartAt(tokenpos, static_cast<char>(INDIC2_MASK));
268 styler.ColourTo(tokenpos, INDIC2_MASK);
269 styler.Flush();
270 styler.StartAt(tokenpos);
271 styler.StartSegment(tokenpos);
272 }
273 }
274
275 if (sc.atLineEnd)
276 styler.SetLineState(lineCurrent, nestTextCurrent);
277 }
278
279 sc.Complete();
280 }
281
282 static void FoldPSDoc(unsigned int startPos, int length, int, WordList *[],
283 Accessor &styler) {
284 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
285 bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
286 unsigned int endPos = startPos + length;
287 int visibleChars = 0;
288 int lineCurrent = styler.GetLine(startPos);
289 int levelCurrent = SC_FOLDLEVELBASE;
290 if (lineCurrent > 0)
291 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
292 int levelMinCurrent = levelCurrent;
293 int levelNext = levelCurrent;
294 char chNext = styler[startPos];
295 int styleNext = styler.StyleAt(startPos);
296 int style;
297 for (unsigned int i = startPos; i < endPos; i++) {
298 char ch = chNext;
299 chNext = styler.SafeGetCharAt(i + 1);
300 style = styleNext;
301 styleNext = styler.StyleAt(i + 1);
302 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); //mac??
303 if ((style & 31) == SCE_PS_PAREN_PROC) {
304 if (ch == '{') {
305 // Measure the minimum before a '{' to allow
306 // folding on "} {"
307 if (levelMinCurrent > levelNext) {
308 levelMinCurrent = levelNext;
309 }
310 levelNext++;
311 } else if (ch == '}') {
312 levelNext--;
313 }
314 }
315 if (atEOL) {
316 int levelUse = levelCurrent;
317 if (foldAtElse) {
318 levelUse = levelMinCurrent;
319 }
320 int lev = levelUse | levelNext << 16;
321 if (visibleChars == 0 && foldCompact)
322 lev |= SC_FOLDLEVELWHITEFLAG;
323 if (levelUse < levelNext)
324 lev |= SC_FOLDLEVELHEADERFLAG;
325 if (lev != styler.LevelAt(lineCurrent)) {
326 styler.SetLevel(lineCurrent, lev);
327 }
328 lineCurrent++;
329 levelCurrent = levelNext;
330 levelMinCurrent = levelCurrent;
331 visibleChars = 0;
332 }
333 if (!isspacechar(ch))
334 visibleChars++;
335 }
336 }
337
338 static const char * const psWordListDesc[] = {
339 "PS Level 1 operators",
340 "PS Level 2 operators",
341 "PS Level 3 operators",
342 "RIP-specific operators",
343 "User-defined operators",
344 0
345 };
346
347 LexerModule lmPS(SCLEX_PS, ColourisePSDoc, "ps", FoldPSDoc, psWordListDesc);