]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/KeyWords.cxx
20f67624702b7e97507a666b206cd4286c605aea
[wxWidgets.git] / src / stc / scintilla / src / KeyWords.cxx
1 // SciTE - Scintilla based Text Editor
2 // KeyWords.cxx - colourise for particular languages
3 // Copyright 1998-2000 by Neil Hodgson <neilh@scintilla.org>
4 // The License.txt file describes the conditions under which this software may be distributed.
5
6 #include <stdlib.h>
7 #include <string.h>
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <stdarg.h>
11
12 #include "Platform.h"
13
14 #include "PropSet.h"
15 #include "Accessor.h"
16 #include "KeyWords.h"
17 #include "Scintilla.h"
18 #include "SciLexer.h"
19
20 inline bool IsLeadByte(int codePage, char ch) {
21 #if PLAT_GTK
22 // TODO: support DBCS under GTK+
23 return false;
24 #elif PLAT_WIN
25 return codePage && IsDBCSLeadByteEx(codePage, ch);
26 #elif PLAT_WX
27 return false;
28 #endif
29 }
30
31 inline bool iswordchar(char ch) {
32 return isalnum(ch) || ch == '.' || ch == '_';
33 }
34
35 inline bool iswordstart(char ch) {
36 return isalnum(ch) || ch == '_';
37 }
38
39 enum { wsSpace = 1, wsTab = 2, wsSpaceTab = 4, wsInconsistent=8};
40
41 static int IndentAmount(StylingContext &styler, int line, int *flags) {
42 int end = styler.Length();
43 int spaceFlags = 0;
44
45 // Determines the indentation level of the current line and also checks for consistent
46 // indentation compared to the previous line.
47 // Indentation is judged consistent when the indentation whitespace of each line lines
48 // the same or the indentation of one line is a prefix of the other.
49
50 int pos = styler.LineStart(line);
51 char ch = styler[pos];
52 int indent = 0;
53 bool inPrevPrefix = line > 0;
54 int posPrev = inPrevPrefix ? styler.LineStart(line-1) : 0;
55 while ((ch == ' ' || ch == '\t') && (pos < end)) {
56 if (inPrevPrefix) {
57 char chPrev = styler[posPrev++];
58 if (chPrev == ' ' || chPrev == '\t') {
59 if (chPrev != ch)
60 spaceFlags |= wsInconsistent;
61 } else {
62 inPrevPrefix = false;
63 }
64 }
65 if (ch == ' ') {
66 spaceFlags |= wsSpace;
67 indent++;
68 } else { // Tab
69 spaceFlags |= wsTab;
70 if (spaceFlags & wsSpace)
71 spaceFlags |= wsSpaceTab;
72 indent = (indent / 8 + 1) * 8;
73 }
74 ch = styler[++pos];
75 }
76
77 *flags = spaceFlags;
78 indent += SC_FOLDLEVELBASE;
79 if (isspace(ch)) // Completely empty line
80 return indent | SC_FOLDLEVELWHITEFLAG;
81 else
82 return indent;
83 }
84
85 inline bool isoperator(char ch) {
86 if (isalnum(ch))
87 return false;
88 // '.' left out as it is used to make up numbers
89 if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
90 ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
91 ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
92 ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
93 ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
94 ch == '?' || ch == '!' || ch == '.' || ch == '~')
95 return true;
96 return false;
97 }
98
99 static void classifyWordCpp(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
100 char s[100];
101 bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
102 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
103 s[i] = styler[start + i];
104 s[i + 1] = '\0';
105 }
106 char chAttr = SCE_C_IDENTIFIER;
107 if (wordIsNumber)
108 chAttr = SCE_C_NUMBER;
109 else {
110 if (keywords.InList(s))
111 chAttr = SCE_C_WORD;
112 }
113 styler.ColourSegment(start, end, chAttr);
114 }
115
116 static void ColouriseCppDoc(int codePage, int startPos, int length,
117 int initStyle, WordList &keywords, StylingContext &styler) {
118
119 bool fold = styler.GetPropSet().GetInt("fold");
120 int lineCurrent = styler.GetLine(startPos);
121 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
122 int levelCurrent = levelPrev;
123
124 int state = initStyle;
125 char chPrev = ' ';
126 char chNext = styler[startPos];
127 int startSeg = startPos;
128 int lengthDoc = startPos + length;
129 int visChars = 0;
130 for (unsigned int i = startPos; i <= lengthDoc; i++) {
131 char ch = chNext;
132 chNext = styler.SafeGetCharAt(i + 1);
133
134 if ((fold) && ((ch == '\r' && chNext != '\n') || (ch == '\n'))) {
135 int lev = levelPrev;
136 if (visChars == 0)
137 lev |= SC_FOLDLEVELWHITEFLAG;
138 if ((levelCurrent > levelPrev) && (visChars > 0))
139 lev |= SC_FOLDLEVELHEADERFLAG;
140 styler.SetLevel(lineCurrent, lev);
141 lineCurrent++;
142 visChars = 0;
143 levelPrev = levelCurrent;
144 }
145 if (!isspace(ch))
146 visChars++;
147
148 if (IsLeadByte(codePage, ch)) { // dbcs
149 chNext = styler.SafeGetCharAt(i + 2);
150 chPrev = ' ';
151 i += 1;
152 continue;
153 }
154
155 if (state == SCE_C_STRINGEOL) {
156 if (ch != '\r' && ch != '\n') {
157 styler.ColourSegment(startSeg, i - 1, state);
158 state = SCE_C_DEFAULT;
159 startSeg = i;
160 }
161 }
162 if (state == SCE_C_DEFAULT) {
163 if (iswordstart(ch)) {
164 styler.ColourSegment(startSeg, i - 1, state);
165 state = SCE_C_WORD;
166 startSeg = i;
167 } else if (ch == '/' && chNext == '*') {
168 styler.ColourSegment(startSeg, i - 1, state);
169 if (styler.SafeGetCharAt(i + 2) == '*')
170 state = SCE_C_COMMENTDOC;
171 else
172 state = SCE_C_COMMENT;
173 startSeg = i;
174 } else if (ch == '/' && chNext == '/') {
175 styler.ColourSegment(startSeg, i - 1, state);
176 state = SCE_C_COMMENTLINE;
177 startSeg = i;
178 } else if (ch == '\"') {
179 styler.ColourSegment(startSeg, i - 1, state);
180 state = SCE_C_STRING;
181 startSeg = i;
182 } else if (ch == '\'') {
183 styler.ColourSegment(startSeg, i - 1, state);
184 state = SCE_C_CHARACTER;
185 startSeg = i;
186 } else if (ch == '#') {
187 styler.ColourSegment(startSeg, i - 1, state);
188 state = SCE_C_PREPROCESSOR;
189 startSeg = i;
190 } else if (isoperator(ch)) {
191 styler.ColourSegment(startSeg, i - 1, state);
192 styler.ColourSegment(i, i, SCE_C_OPERATOR);
193 startSeg = i + 1;
194 if ((ch == '{') || (ch == '}')) {
195 levelCurrent += (ch == '{') ? 1 : -1;
196 }
197 }
198 } else if (state == SCE_C_WORD) {
199 if (!iswordchar(ch)) {
200 classifyWordCpp(startSeg, i - 1, keywords, styler);
201 state = SCE_C_DEFAULT;
202 startSeg = i;
203 if (ch == '/' && chNext == '*') {
204 if (styler.SafeGetCharAt(i + 2) == '*')
205 state = SCE_C_COMMENTDOC;
206 else
207 state = SCE_C_COMMENT;
208 } else if (ch == '/' && chNext == '/') {
209 state = SCE_C_COMMENTLINE;
210 } else if (ch == '\"') {
211 state = SCE_C_STRING;
212 } else if (ch == '\'') {
213 state = SCE_C_CHARACTER;
214 } else if (ch == '#') {
215 state = SCE_C_PREPROCESSOR;
216 } else if (isoperator(ch)) {
217 styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
218 startSeg = i + 1;
219 if ((ch == '{') || (ch == '}')) {
220 levelCurrent += (ch == '{') ? 1 : -1;
221 }
222 }
223 }
224 } else {
225 if (state == SCE_C_PREPROCESSOR) {
226 if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
227 styler.ColourSegment(startSeg, i - 1, state);
228 state = SCE_C_DEFAULT;
229 startSeg = i;
230 }
231 } else if (state == SCE_C_COMMENT) {
232 if (ch == '/' && chPrev == '*' && (
233 (i > startSeg + 2) || ((initStyle == SCE_C_COMMENT) && (startSeg == startPos)))) {
234 styler.ColourSegment(startSeg, i, state);
235 state = SCE_C_DEFAULT;
236 startSeg = i + 1;
237 }
238 } else if (state == SCE_C_COMMENTDOC) {
239 if (ch == '/' && chPrev == '*' && (
240 (i > startSeg + 3) || ((initStyle == SCE_C_COMMENTDOC) && (startSeg == startPos)))) {
241 styler.ColourSegment(startSeg, i, state);
242 state = SCE_C_DEFAULT;
243 startSeg = i + 1;
244 }
245 } else if (state == SCE_C_COMMENTLINE) {
246 if (ch == '\r' || ch == '\n') {
247 styler.ColourSegment(startSeg, i - 1, state);
248 state = SCE_C_DEFAULT;
249 startSeg = i;
250 }
251 } else if (state == SCE_C_STRING) {
252 if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
253 styler.ColourSegment(startSeg, i - 1, state);
254 state = SCE_C_STRINGEOL;
255 startSeg = i;
256 } else if (ch == '\\') {
257 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
258 i++;
259 ch = chNext;
260 chNext = styler.SafeGetCharAt(i + 1);
261 }
262 } else if (ch == '\"') {
263 styler.ColourSegment(startSeg, i, state);
264 state = SCE_C_DEFAULT;
265 i++;
266 ch = chNext;
267 chNext = styler.SafeGetCharAt(i + 1);
268 startSeg = i;
269 }
270 } else if (state == SCE_C_CHARACTER) {
271 if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
272 styler.ColourSegment(startSeg, i - 1, state);
273 state = SCE_C_STRINGEOL;
274 startSeg = i;
275 } else if (ch == '\\') {
276 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
277 i++;
278 ch = chNext;
279 chNext = styler.SafeGetCharAt(i + 1);
280 }
281 } else if (ch == '\'') {
282 styler.ColourSegment(startSeg, i, state);
283 state = SCE_C_DEFAULT;
284 i++;
285 ch = chNext;
286 chNext = styler.SafeGetCharAt(i + 1);
287 startSeg = i;
288 }
289 }
290 if (state == SCE_C_DEFAULT) { // One of the above succeeded
291 if (ch == '/' && chNext == '*') {
292 if (styler.SafeGetCharAt(i + 2) == '*')
293 state = SCE_C_COMMENTDOC;
294 else
295 state = SCE_C_COMMENT;
296 } else if (ch == '/' && chNext == '/') {
297 state = SCE_C_COMMENTLINE;
298 } else if (ch == '\"') {
299 state = SCE_C_STRING;
300 } else if (ch == '\'') {
301 state = SCE_C_CHARACTER;
302 } else if (ch == '#') {
303 state = SCE_C_PREPROCESSOR;
304 } else if (iswordstart(ch)) {
305 state = SCE_C_WORD;
306 } else if (isoperator(ch)) {
307 styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
308 startSeg = i + 1;
309 if ((ch == '{') || (ch == '}')) {
310 levelCurrent += (ch == '{') ? 1 : -1;
311 }
312 }
313 }
314 }
315 chPrev = ch;
316 }
317 if (startSeg < lengthDoc)
318 styler.ColourSegment(startSeg, lengthDoc - 1, state);
319 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
320 if (fold) {
321 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
322 //styler.SetLevel(lineCurrent, levelCurrent | flagsNext);
323 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
324
325 }
326 }
327
328 inline bool isPerlOperator(char ch) {
329 if (isalnum(ch))
330 return false;
331 // '.' left out as it is used to make up numbers
332 if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || ch == '\\' ||
333 ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
334 ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
335 ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
336 ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
337 ch == '?' || ch == '!' || ch == '.' || ch == '~')
338 return true;
339 return false;
340 }
341
342 static int classifyWordPerl(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
343 char s[100];
344 bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
345 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
346 s[i] = styler[start + i];
347 s[i + 1] = '\0';
348 }
349 char chAttr = SCE_PL_IDENTIFIER;
350 if (wordIsNumber)
351 chAttr = SCE_PL_NUMBER;
352 else {
353 if (keywords.InList(s))
354 chAttr = SCE_PL_WORD;
355 }
356 styler.ColourSegment(start, end, chAttr);
357 return chAttr;
358 }
359
360 static bool isEndVar(char ch) {
361 return !isalnum(ch) && ch != '#' && ch != '$' &&
362 ch != '_' && ch != '\'';
363 }
364
365 static bool isMatch(StylingContext &styler, int lengthDoc, int pos, const char *val) {
366 if ((pos + static_cast<int>(strlen(val))) >= lengthDoc) {
367 return false;
368 }
369 while (*val) {
370 if (*val != styler[pos++]) {
371 return false;
372 }
373 val++;
374 }
375 return true;
376 }
377
378 static bool isOKQuote(char ch) {
379 if (isalnum(ch))
380 return false;
381 if (isspace(ch))
382 return false;
383 if (iscntrl(ch))
384 return false;
385 return true;
386 }
387
388 static char opposite(char ch) {
389 if (ch == '(')
390 return ')';
391 if (ch == '[')
392 return ']';
393 if (ch == '{')
394 return '}';
395 if (ch == '<')
396 return '>';
397 return ch;
398 }
399
400 static void ColourisePerlDoc(int codePage, int startPos, int length, int initStyle,
401 WordList &keywords, StylingContext &styler) {
402 char sooked[100];
403 int quotes = 0;
404 char quoteDown = 'd';
405 char quoteUp = 'd';
406 int quoteRep = 1;
407 int sookedpos = 0;
408 bool preferRE = true;
409 sooked[sookedpos] = '\0';
410 int state = initStyle;
411 int lengthDoc = startPos + length;
412 // If in a long distance lexical state, seek to the beginning to find quote characters
413 if (state == SCE_PL_HERE || state == SCE_PL_REGEX ||
414 state == SCE_PL_REGSUBST || state == SCE_PL_LONGQUOTE) {
415 while ((startPos > 1) && (styler.StyleAt(startPos - 1) == state)) {
416 startPos--;
417 }
418 state = SCE_PL_DEFAULT;
419 }
420 styler.StartAt(startPos);
421 char chPrev = ' ';
422 char chNext = styler[startPos];
423 int startSeg = startPos;
424 for (int i = startPos; i <= lengthDoc; i++) {
425 char ch = chNext;
426 chNext = styler.SafeGetCharAt(i + 1);
427 char chNext2 = styler.SafeGetCharAt(i + 2);
428
429 if (IsLeadByte(codePage, ch)) { // dbcs
430 chNext = styler.SafeGetCharAt(i + 2);
431 chPrev = ' ';
432 i += 1;
433 continue;
434 }
435
436 if (state == SCE_PL_DEFAULT) {
437 if (iswordstart(ch)) {
438 styler.ColourSegment(startSeg, i - 1, state);
439 if (ch == 's' && !isalnum(chNext)) {
440 state = SCE_PL_REGSUBST;
441 quotes = 0;
442 quoteUp = '\0';
443 quoteDown = '\0';
444 quoteRep = 2;
445 startSeg = i;
446 } else if (ch == 'm' && !isalnum(chNext)) {
447 state = SCE_PL_REGEX;
448 quotes = 0;
449 quoteUp = '\0';
450 quoteDown = '\0';
451 quoteRep = 1;
452 startSeg = i;
453 } else if (ch == 't' && chNext == 'r' && !isalnum(chNext2)) {
454 state = SCE_PL_REGSUBST;
455 quotes = 0;
456 quoteUp = '\0';
457 quoteDown = '\0';
458 quoteRep = 2;
459 startSeg = i;
460 i++;
461 chNext = chNext2;
462 } else if (ch == 'q' && (chNext == 'q' || chNext == 'r' || chNext == 'w' || chNext == 'x') && !isalnum(chNext2)) {
463 state = SCE_PL_LONGQUOTE;
464 startSeg = i;
465 i++;
466 chNext = chNext2;
467 quotes = 0;
468 quoteUp = '\0';
469 quoteDown = '\0';
470 quoteRep = 1;
471 } else {
472 state = SCE_PL_WORD;
473 startSeg = i;
474 preferRE = false;
475 }
476 } else if (ch == '#') {
477 styler.ColourSegment(startSeg, i - 1, state);
478 state = SCE_PL_COMMENTLINE;
479 startSeg = i;
480 } else if (ch == '\"') {
481 styler.ColourSegment(startSeg, i - 1, state);
482 state = SCE_PL_STRING;
483 startSeg = i;
484 } else if (ch == '\'') {
485 if (chPrev == '&') {
486 // Archaic call
487 styler.ColourSegment(i, i, state);
488 startSeg = i + 1;
489 } else {
490 styler.ColourSegment(startSeg, i - 1, state);
491 state = SCE_PL_CHARACTER;
492 startSeg = i;
493 }
494 } else if (ch == '`') {
495 styler.ColourSegment(startSeg, i - 1, state);
496 state = SCE_PL_BACKTICKS;
497 startSeg = i;
498 } else if (ch == '$') {
499 preferRE = false;
500 styler.ColourSegment(startSeg, i - 1, state);
501 if (isalnum(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
502 state = SCE_PL_SCALAR;
503 startSeg = i;
504 } else if (chNext != '{' && chNext != '[') {
505 styler.ColourSegment(i - 1, i, SCE_PL_SCALAR);
506 i++;
507 startSeg = i + 1;
508 ch = ' ';
509 chNext = ' ';
510 } else {
511 styler.ColourSegment(i, i, SCE_PL_SCALAR);
512 startSeg = i + 1;
513 }
514 } else if (ch == '@') {
515 preferRE = false;
516 styler.ColourSegment(startSeg, i - 1, state);
517 if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
518 state = SCE_PL_ARRAY;
519 startSeg = i;
520 } else if (chNext != '{' && chNext != '[') {
521 styler.ColourSegment(i - 1, i, SCE_PL_ARRAY);
522 i++;
523 startSeg = i + 1;
524 ch = ' ';
525 } else {
526 styler.ColourSegment(i, i, SCE_PL_ARRAY);
527 startSeg = i + 1;
528 }
529 } else if (ch == '%') {
530 preferRE = false;
531 styler.ColourSegment(startSeg, i - 1, state);
532 if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
533 state = SCE_PL_HASH;
534 startSeg = i;
535 } else if (chNext != '{' && chNext != '[') {
536 styler.ColourSegment(i - 1, i, SCE_PL_HASH);
537 i++;
538 startSeg = i + 1;
539 ch = ' ';
540 } else {
541 styler.ColourSegment(i, i, SCE_PL_HASH);
542 startSeg = i + 1;
543 }
544 } else if (ch == '*') {
545 styler.ColourSegment(startSeg, i - 1, state);
546 state = SCE_PL_SYMBOLTABLE;
547 startSeg = i;
548 } else if (ch == '/' && preferRE) {
549 styler.ColourSegment(startSeg, i - 1, state);
550 state = SCE_PL_REGEX;
551 quoteUp = '/';
552 quoteDown = '/';
553 quotes = 1;
554 quoteRep = 1;
555 startSeg = i;
556 } else if (ch == '<' && chNext == '<') {
557 styler.ColourSegment(startSeg, i - 1, state);
558 state = SCE_PL_HERE;
559 startSeg = i;
560 i++;
561 ch = chNext;
562 chNext = chNext2;
563 quotes = 0;
564 sookedpos = 0;
565 sooked[sookedpos] = '\0';
566 } else if (ch == '=' && isalpha(chNext)) {
567 styler.ColourSegment(startSeg, i - 1, state);
568 state = SCE_PL_POD;
569 startSeg = i;
570 quotes = 0;
571 sookedpos = 0;
572 sooked[sookedpos] = '\0';
573 } else if (isPerlOperator(ch)) {
574 if (ch == ')' || ch == ']')
575 preferRE = false;
576 else
577 preferRE = true;
578 styler.ColourSegment(startSeg, i - 1, state);
579 styler.ColourSegment(i, i, SCE_PL_OPERATOR);
580 startSeg = i + 1;
581 }
582 } else if (state == SCE_PL_WORD) {
583 if (!iswordchar(ch) && ch != '\'') { // Archaic Perl has quotes inside names
584 if (isMatch(styler, lengthDoc, startSeg, "__DATA__")) {
585 styler.ColourSegment(startSeg, i, SCE_PL_DATASECTION);
586 state = SCE_PL_DATASECTION;
587 } else if (isMatch(styler, lengthDoc, startSeg, "__END__")) {
588 styler.ColourSegment(startSeg, i, SCE_PL_DATASECTION);
589 state = SCE_PL_DATASECTION;
590 } else {
591 if (classifyWordPerl(startSeg, i - 1, keywords, styler) == SCE_PL_WORD)
592 preferRE = true;
593 state = SCE_PL_DEFAULT;
594 startSeg = i;
595 if (ch == '#') {
596 state = SCE_PL_COMMENTLINE;
597 } else if (ch == '\"') {
598 state = SCE_PL_STRING;
599 } else if (ch == '\'') {
600 state = SCE_PL_CHARACTER;
601 } else if (ch == '<' && chNext == '<') {
602 state = SCE_PL_HERE;
603 quotes = 0;
604 startSeg = i;
605 sookedpos = 0;
606 sooked[sookedpos] = '\0';
607 } else if (isPerlOperator(ch)) {
608 if (ch == ')' || ch == ']')
609 preferRE = false;
610 else
611 preferRE = true;
612 styler.ColourSegment(startSeg, i, SCE_PL_OPERATOR);
613 state = SCE_PL_DEFAULT;
614 startSeg = i + 1;
615 }
616 }
617 }
618 } else {
619 if (state == SCE_PL_COMMENTLINE) {
620 if (ch == '\r' || ch == '\n') {
621 styler.ColourSegment(startSeg, i - 1, state);
622 state = SCE_PL_DEFAULT;
623 startSeg = i;
624 }
625 } else if (state == SCE_PL_HERE) {
626 if (isalnum(ch) && quotes < 2) {
627 sooked[sookedpos++] = ch;
628 sooked[sookedpos] = '\0';
629 if (quotes == 0)
630 quotes = 1;
631 } else {
632 quotes++;
633 }
634
635 if (quotes > 1 && isMatch(styler, lengthDoc, i, sooked)) {
636 styler.ColourSegment(startSeg, i + sookedpos - 1, SCE_PL_HERE);
637 state = SCE_PL_DEFAULT;
638 i += sookedpos;
639 startSeg = i;
640 chNext = ' ';
641 }
642 } else if (state == SCE_PL_STRING) {
643 if (ch == '\\') {
644 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
645 i++;
646 ch = chNext;
647 chNext = styler.SafeGetCharAt(i + 1);
648 }
649 } else if (ch == '\"') {
650 styler.ColourSegment(startSeg, i, state);
651 state = SCE_PL_DEFAULT;
652 i++;
653 ch = chNext;
654 chNext = styler.SafeGetCharAt(i + 1);
655 startSeg = i;
656 }
657 } else if (state == SCE_PL_CHARACTER) {
658 if (ch == '\\') {
659 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
660 i++;
661 ch = chNext;
662 chNext = styler.SafeGetCharAt(i + 1);
663 }
664 } else if (ch == '\'') {
665 styler.ColourSegment(startSeg, i, state);
666 state = SCE_PL_DEFAULT;
667 i++;
668 ch = chNext;
669 chNext = styler.SafeGetCharAt(i + 1);
670 startSeg = i;
671 }
672 } else if (state == SCE_PL_BACKTICKS) {
673 if (ch == '`') {
674 styler.ColourSegment(startSeg, i, state);
675 state = SCE_PL_DEFAULT;
676 i++;
677 ch = chNext;
678 chNext = styler.SafeGetCharAt(i + 1);
679 startSeg = i;
680 }
681 } else if (state == SCE_PL_POD) {
682 if (ch == '=') {
683 if (isMatch(styler, lengthDoc, i, "=cut")) {
684 styler.ColourSegment(startSeg, i - 1 + 4, state);
685 i += 4;
686 startSeg = i;
687 state = SCE_PL_DEFAULT;
688 chNext = ' ';
689 ch = ' ';
690 }
691 }
692 } else if (state == SCE_PL_SCALAR) {
693 if (isEndVar(ch)) {
694 styler.ColourSegment(startSeg, i - 1, state);
695 startSeg = i;
696 state = SCE_PL_DEFAULT;
697 }
698 } else if (state == SCE_PL_ARRAY) {
699 if (isEndVar(ch)) {
700 styler.ColourSegment(startSeg, i - 1, state);
701 startSeg = i;
702 state = SCE_PL_DEFAULT;
703 }
704 } else if (state == SCE_PL_HASH) {
705 if (isEndVar(ch)) {
706 styler.ColourSegment(startSeg, i - 1, state);
707 startSeg = i;
708 state = SCE_PL_DEFAULT;
709 }
710 } else if (state == SCE_PL_SYMBOLTABLE) {
711 if (isEndVar(ch)) {
712 styler.ColourSegment(startSeg, i - 1, state);
713 startSeg = i;
714 state = SCE_PL_DEFAULT;
715 }
716 } else if (state == SCE_PL_REF) {
717 if (isEndVar(ch)) {
718 styler.ColourSegment(startSeg, i - 1, state);
719 startSeg = i;
720 state = SCE_PL_DEFAULT;
721 }
722 } else if (state == SCE_PL_REGEX) {
723 if (!quoteUp && !isspace(ch)) {
724 quoteUp = ch;
725 quoteDown = opposite(ch);
726 quotes++;
727 } else {
728 if (ch == quoteDown && chPrev != '\\') {
729 quotes--;
730 if (quotes == 0) {
731 quoteRep--;
732 if (quoteUp == quoteDown) {
733 quotes++;
734 }
735 }
736 if (!isalpha(chNext)) {
737 if (quoteRep <= 0) {
738 styler.ColourSegment(startSeg, i, state);
739 startSeg = i + 1;
740 state = SCE_PL_DEFAULT;
741 ch = ' ';
742 }
743 }
744 } else if (ch == quoteUp && chPrev != '\\') {
745 quotes++;
746 } else if (!isalpha(chNext)) {
747 if (quoteRep <= 0) {
748 styler.ColourSegment(startSeg, i, state);
749 startSeg = i + 1;
750 state = SCE_PL_DEFAULT;
751 ch = ' ';
752 }
753 }
754 }
755 } else if (state == SCE_PL_REGSUBST) {
756 if (!quoteUp && !isspace(ch)) {
757 quoteUp = ch;
758 quoteDown = opposite(ch);
759 quotes++;
760 } else {
761 if (ch == quoteDown && chPrev != '\\') {
762 quotes--;
763 if (quotes == 0) {
764 quoteRep--;
765 }
766 if (!isalpha(chNext)) {
767 if (quoteRep <= 0) {
768 styler.ColourSegment(startSeg, i, state);
769 startSeg = i + 1;
770 state = SCE_PL_DEFAULT;
771 ch = ' ';
772 }
773 }
774 if (quoteUp == quoteDown) {
775 quotes++;
776 }
777 } else if (ch == quoteUp && chPrev != '\\') {
778 quotes++;
779 } else if (!isalpha(chNext)) {
780 if (quoteRep <= 0) {
781 styler.ColourSegment(startSeg, i, state);
782 startSeg = i + 1;
783 state = SCE_PL_DEFAULT;
784 ch = ' ';
785 }
786 }
787 }
788 } else if (state == SCE_PL_LONGQUOTE) {
789 if (!quoteDown && !isspace(ch)) {
790 quoteUp = ch;
791 quoteDown = opposite(quoteUp);
792 quotes++;
793 } else if (ch == quoteDown) {
794 quotes--;
795 if (quotes == 0) {
796 quoteRep--;
797 if (quoteRep <= 0) {
798 styler.ColourSegment(startSeg, i, state);
799 startSeg = i + 1;
800 state = SCE_PL_DEFAULT;
801 ch = ' ';
802 }
803 if (quoteUp == quoteDown) {
804 quotes++;
805 }
806 }
807 } else if (ch == quoteUp) {
808 quotes++;
809 }
810 }
811
812 if (state == SCE_PL_DEFAULT) { // One of the above succeeded
813 if (ch == '#') {
814 state = SCE_PL_COMMENTLINE;
815 } else if (ch == '\"') {
816 state = SCE_PL_STRING;
817 } else if (ch == '\'') {
818 state = SCE_PL_CHARACTER;
819 } else if (iswordstart(ch)) {
820 state = SCE_PL_WORD;
821 preferRE = false;
822 } else if (isoperator(ch)) {
823 styler.ColourSegment(startSeg, i, SCE_PL_OPERATOR);
824 startSeg = i + 1;
825 }
826 }
827 }
828 chPrev = ch;
829 }
830 if (startSeg < lengthDoc)
831 styler.ColourSegment(startSeg, lengthDoc, state);
832 }
833
834
835 static int classifyWordVB(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
836 char s[100];
837 bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
838 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
839 s[i] = tolower(styler[start + i]);
840 s[i + 1] = '\0';
841 }
842 char chAttr = SCE_C_DEFAULT;
843 if (wordIsNumber)
844 chAttr = SCE_C_NUMBER;
845 else {
846 if (keywords.InList(s)) {
847 chAttr = SCE_C_WORD;
848 if (strcmp(s, "rem") == 0)
849 chAttr = SCE_C_COMMENTLINE;
850 }
851 }
852 styler.ColourSegment(start, end, chAttr);
853 if (chAttr == SCE_C_COMMENTLINE)
854 return SCE_C_COMMENTLINE;
855 else
856 return SCE_C_DEFAULT;
857 }
858
859 static void ColouriseVBDoc(int codePage, int startPos, int length, int initStyle,
860 WordList &keywords, StylingContext &styler) {
861 int state = initStyle;
862 char chNext = styler[startPos];
863 int startSeg = startPos;
864 int lengthDoc = startPos + length;
865 for (int i = startPos; i < lengthDoc; i++) {
866 char ch = chNext;
867 chNext = styler.SafeGetCharAt(i + 1);
868
869 if (IsLeadByte(codePage, ch)) { // dbcs
870 chNext = styler.SafeGetCharAt(i + 2);
871 i += 1;
872 continue;
873 }
874
875 if (state == SCE_C_DEFAULT) {
876 if (iswordstart(ch)) {
877 styler.ColourSegment(startSeg, i - 1, state);
878 state = SCE_C_WORD;
879 startSeg = i;
880 } else if (ch == '\'') {
881 styler.ColourSegment(startSeg, i - 1, state);
882 state = SCE_C_COMMENTLINE;
883 startSeg = i;
884 } else if (ch == '\"') {
885 styler.ColourSegment(startSeg, i - 1, state);
886 state = SCE_C_STRING;
887 startSeg = i;
888 }
889 } else if (state == SCE_C_WORD) {
890 if (!iswordchar(ch)) {
891 state = classifyWordVB(startSeg, i - 1, keywords, styler);
892 if (state == SCE_C_DEFAULT) {
893 startSeg = i;
894 if (ch == '\'') {
895 state = SCE_C_COMMENTLINE;
896 } else if (ch == '\"') {
897 state = SCE_C_STRING;
898 }
899 }
900 }
901 } else {
902 if (state == SCE_C_COMMENTLINE) {
903 if (ch == '\r' || ch == '\n') {
904 styler.ColourSegment(startSeg, i - 1, state);
905 state = SCE_C_DEFAULT;
906 startSeg = i;
907 }
908 } else if (state == SCE_C_STRING) {
909 // VB doubles quotes to preserve them
910 if (ch == '\"') {
911 styler.ColourSegment(startSeg, i, state);
912 state = SCE_C_DEFAULT;
913 i++;
914 ch = chNext;
915 chNext = styler.SafeGetCharAt(i + 1);
916 startSeg = i;
917 }
918 }
919 if (state == SCE_C_DEFAULT) { // One of the above succeeded
920 if (ch == '\'') {
921 state = SCE_C_COMMENTLINE;
922 } else if (ch == '\"') {
923 state = SCE_C_STRING;
924 } else if (iswordstart(ch)) {
925 state = SCE_C_WORD;
926 }
927 }
928 }
929 }
930 if (startSeg < lengthDoc)
931 styler.ColourSegment(startSeg, lengthDoc, state);
932 }
933
934 static void classifyWordPy(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler, char *prevWord) {
935 char s[100];
936 bool wordIsNumber = isdigit(styler[start]);
937 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
938 s[i] = styler[start + i];
939 s[i + 1] = '\0';
940 }
941 char chAttr = SCE_P_IDENTIFIER;
942 if (0 == strcmp(prevWord, "class"))
943 chAttr = SCE_P_CLASSNAME;
944 else if (0 == strcmp(prevWord, "def"))
945 chAttr = SCE_P_DEFNAME;
946 else if (wordIsNumber)
947 chAttr = SCE_P_NUMBER;
948 else if (keywords.InList(s))
949 chAttr = SCE_P_WORD;
950 styler.ColourSegment(start, end, chAttr);
951 strcpy(prevWord, s);
952 }
953
954 static void ColourisePyDoc(int codePage, int startPos, int length, int initStyle, WordList &keywords, StylingContext &styler) {
955 //Platform::DebugPrintf("Python coloured\n");
956 bool fold = styler.GetPropSet().GetInt("fold");
957 int whingeLevel = styler.GetPropSet().GetInt("tab.timmy.whinge.level");
958 char prevWord[200];
959 prevWord[0] = '\0';
960 if (length == 0)
961 return ;
962 int lineCurrent = styler.GetLine(startPos);
963 int spaceFlags = 0;
964 // TODO: Need to check previous line for indentation for both folding and bad indentation
965 int indentCurrent = IndentAmount(styler, lineCurrent, &spaceFlags);
966
967 int state = initStyle & 31;
968 char chPrev = ' ';
969 char chPrev2 = ' ';
970 char chNext = styler[startPos];
971 char chNext2 = styler[startPos];
972 int startSeg = startPos;
973 int lengthDoc = startPos + length;
974 bool atStartLine = true;
975 for (int i = startPos; i <= lengthDoc; i++) {
976
977 if (atStartLine) {
978 if (whingeLevel == 1) {
979 styler.SetFlags((spaceFlags & wsInconsistent) ? 64 : 0, state);
980 } else if (whingeLevel == 2) {
981 styler.SetFlags((spaceFlags & wsSpaceTab) ? 64 : 0, state);
982 } else if (whingeLevel == 3) {
983 styler.SetFlags((spaceFlags & wsSpace) ? 64 : 0, state);
984 } else if (whingeLevel == 4) {
985 styler.SetFlags((spaceFlags & wsTab) ? 64 : 0, state);
986 }
987 atStartLine = false;
988 }
989
990 char ch = chNext;
991 chNext = styler.SafeGetCharAt(i + 1);
992 chNext2 = styler.SafeGetCharAt(i + 2);
993
994 if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
995 if ((state == SCE_P_DEFAULT) || (state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) {
996 // Perform colourisation of white space and triple quoted strings at end of each line to allow
997 // tab marking to work inside white space and triple quoted strings
998 styler.ColourSegment(startSeg, i, state);
999 startSeg = i + 1;
1000 }
1001
1002 int lev = indentCurrent;
1003 int indentNext = IndentAmount(styler, lineCurrent + 1, &spaceFlags);
1004 if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
1005 // Only non whitespace lines can be headers
1006 if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
1007 lev |= SC_FOLDLEVELHEADERFLAG;
1008 }
1009 }
1010 indentCurrent = indentNext;
1011 if (fold) {
1012 styler.SetLevel(lineCurrent, lev);
1013 }
1014 lineCurrent++;
1015 atStartLine = true;
1016 }
1017
1018 if (IsLeadByte(codePage, ch)) { // dbcs
1019 chNext = styler.SafeGetCharAt(i + 2);
1020 chPrev = ' ';
1021 chPrev2 = ' ';
1022 i += 1;
1023 continue;
1024 }
1025
1026 if (state == SCE_P_DEFAULT) {
1027 if (iswordstart(ch)) {
1028 styler.ColourSegment(startSeg, i - 1, state);
1029 state = SCE_P_WORD;
1030 startSeg = i;
1031 } else if (ch == '#') {
1032 styler.ColourSegment(startSeg, i - 1, state);
1033 state = SCE_P_COMMENTLINE;
1034 startSeg = i;
1035 } else if (ch == '\"') {
1036 styler.ColourSegment(startSeg, i - 1, state);
1037 startSeg = i;
1038 if (chNext == '\"' && chNext2 == '\"') {
1039 i += 2;
1040 state = SCE_P_TRIPLEDOUBLE;
1041 ch = ' ';
1042 chPrev = ' ';
1043 chNext = styler.SafeGetCharAt(i + 1);
1044 } else {
1045 state = SCE_P_STRING;
1046 }
1047 } else if (ch == '\'') {
1048 styler.ColourSegment(startSeg, i - 1, state);
1049 startSeg = i;
1050 if (chNext == '\'' && chNext2 == '\'') {
1051 i += 2;
1052 state = SCE_P_TRIPLE;
1053 ch = ' ';
1054 chPrev = ' ';
1055 chNext = styler.SafeGetCharAt(i + 1);
1056 } else {
1057 state = SCE_P_CHARACTER;
1058 }
1059 } else if (isoperator(ch)) {
1060 styler.ColourSegment(startSeg, i - 1, state);
1061 styler.ColourSegment(i, i, SCE_P_OPERATOR);
1062 startSeg = i + 1;
1063 }
1064 } else if (state == SCE_P_WORD) {
1065 if (!iswordchar(ch)) {
1066 classifyWordPy(startSeg, i - 1, keywords, styler, prevWord);
1067 state = SCE_P_DEFAULT;
1068 startSeg = i;
1069 if (ch == '#') {
1070 state = SCE_P_COMMENTLINE;
1071 } else if (ch == '\"') {
1072 if (chNext == '\"' && chNext2 == '\"') {
1073 i += 2;
1074 state = SCE_P_TRIPLEDOUBLE;
1075 ch = ' ';
1076 chPrev = ' ';
1077 chNext = styler.SafeGetCharAt(i + 1);
1078 } else {
1079 state = SCE_P_STRING;
1080 }
1081 } else if (ch == '\'') {
1082 if (chNext == '\'' && chNext2 == '\'') {
1083 i += 2;
1084 state = SCE_P_TRIPLE;
1085 ch = ' ';
1086 chPrev = ' ';
1087 chNext = styler.SafeGetCharAt(i + 1);
1088 } else {
1089 state = SCE_P_CHARACTER;
1090 }
1091 } else if (isoperator(ch)) {
1092 styler.ColourSegment(startSeg, i, SCE_P_OPERATOR);
1093 startSeg = i + 1;
1094 }
1095 }
1096 } else {
1097 if (state == SCE_P_COMMENTLINE) {
1098 if (ch == '\r' || ch == '\n') {
1099 styler.ColourSegment(startSeg, i - 1, state);
1100 state = SCE_P_DEFAULT;
1101 startSeg = i;
1102 }
1103 } else if (state == SCE_P_STRING) {
1104 if (ch == '\\') {
1105 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
1106 i++;
1107 ch = chNext;
1108 chNext = styler.SafeGetCharAt(i + 1);
1109 }
1110 } else if (ch == '\"') {
1111 styler.ColourSegment(startSeg, i, state);
1112 state = SCE_P_DEFAULT;
1113 startSeg = i + 1;
1114 }
1115 } else if (state == SCE_P_CHARACTER) {
1116 if (ch == '\\') {
1117 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
1118 i++;
1119 ch = chNext;
1120 chNext = styler.SafeGetCharAt(i + 1);
1121 }
1122 } else if (ch == '\'') {
1123 styler.ColourSegment(startSeg, i, state);
1124 state = SCE_P_DEFAULT;
1125 startSeg = i + 1;
1126 }
1127 } else if (state == SCE_P_TRIPLE) {
1128 if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
1129 styler.ColourSegment(startSeg, i, state);
1130 state = SCE_P_DEFAULT;
1131 startSeg = i + 1;
1132 }
1133 } else if (state == SCE_P_TRIPLEDOUBLE) {
1134 if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
1135 styler.ColourSegment(startSeg, i, state);
1136 state = SCE_P_DEFAULT;
1137 startSeg = i + 1;
1138 }
1139 }
1140 }
1141 chPrev2 = chPrev;
1142 chPrev = ch;
1143 }
1144 if (startSeg <= lengthDoc) {
1145 if (state == SCE_P_DEFAULT) {
1146 styler.ColourSegment(startSeg, lengthDoc, state);
1147 } else if (state == SCE_P_WORD) {
1148 classifyWordPy(startSeg, lengthDoc, keywords, styler, prevWord);
1149 } else if (state == SCE_P_COMMENTLINE) {
1150 styler.ColourSegment(startSeg, lengthDoc, state);
1151 } else if (state == SCE_P_STRING) {
1152 styler.ColourSegment(startSeg, lengthDoc, state);
1153 } else if (state == SCE_P_CHARACTER) {
1154 styler.ColourSegment(startSeg, lengthDoc, state);
1155 } else if (state == SCE_P_TRIPLE) {
1156 styler.ColourSegment(startSeg, lengthDoc, state);
1157 } else if (state == SCE_P_TRIPLEDOUBLE) {
1158 styler.ColourSegment(startSeg, lengthDoc, state);
1159 }
1160 }
1161 }
1162
1163 static void ColouriseBatchLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
1164 if (0 == strncmp(lineBuffer, "REM", 3)) {
1165 styler.ColourSegment(0, lengthLine - 1, 1);
1166 } else if (0 == strncmp(lineBuffer, "rem", 3)) {
1167 styler.ColourSegment(0, lengthLine - 1, 1);
1168 } else if (0 == strncmp(lineBuffer, "SET", 3)) {
1169 styler.ColourSegment(0, lengthLine - 1, 2);
1170 } else if (0 == strncmp(lineBuffer, "set", 3)) {
1171 styler.ColourSegment(0, lengthLine - 1, 2);
1172 } else if (lineBuffer[0] == ':') {
1173 styler.ColourSegment(0, lengthLine - 1, 3);
1174 } else {
1175 styler.ColourSegment(0, lengthLine - 1, 0);
1176 }
1177 }
1178
1179 static void ColouriseBatchDoc(int startPos, int length, int, StylingContext &styler) {
1180 char lineBuffer[1024];
1181 unsigned int linePos = 0;
1182 for (int i = startPos; i < startPos + length; i++) {
1183 lineBuffer[linePos++] = styler[i];
1184 if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
1185 ColouriseBatchLine(lineBuffer, linePos, styler);
1186 linePos = 0;
1187 }
1188 }
1189 if (linePos > 0)
1190 ColouriseBatchLine(lineBuffer, linePos, styler);
1191 }
1192
1193 enum { eScriptNone, eScriptJS, eScriptVBS, eScriptPython };
1194 static int segIsScriptingIndicator(StylingContext &styler, unsigned int start, unsigned int end, int prevValue) {
1195 char s[100];
1196 s[0] = '\0';
1197 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
1198 s[i] = tolower(styler[start + i]);
1199 s[i + 1] = '\0';
1200 }
1201 Platform::DebugPrintf("Scripting indicator [%s]\n", s);
1202 if (strstr(s, "vbs"))
1203 return eScriptVBS;
1204 if (strstr(s, "pyth"))
1205 return eScriptPython;
1206 if (strstr(s, "javas"))
1207 return eScriptJS;
1208 if (strstr(s, "jscr"))
1209 return eScriptJS;
1210
1211 return prevValue;
1212 }
1213
1214 static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
1215 bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.') ||
1216 (styler[start] == '-') || (styler[start] == '#');
1217 char chAttr = SCE_H_ATTRIBUTEUNKNOWN;
1218 if (wordIsNumber) {
1219 chAttr = SCE_H_NUMBER;
1220 } else {
1221 char s[100];
1222 s[0] = '\0';
1223 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
1224 s[i] = tolower(styler[start + i]);
1225 s[i + 1] = '\0';
1226 }
1227 if (keywords.InList(s))
1228 chAttr = SCE_H_ATTRIBUTE;
1229 }
1230 styler.ColourTo(end, chAttr);
1231 }
1232
1233 static int classifyTagHTML(unsigned int start, unsigned int end,
1234 WordList &keywords, StylingContext &styler) {
1235 char s[100];
1236 // Copy after the '<'
1237 unsigned int i = 0;
1238 for (int cPos=start; cPos <= end && i < 30; cPos++) {
1239 char ch = styler[cPos];
1240 if (ch != '<')
1241 s[i++] = tolower(ch);
1242 }
1243 s[i] = '\0';
1244 char chAttr = SCE_H_TAGUNKNOWN;
1245 if (s[0] == '!' && s[1] == '-' && s[2] == '-') { //Comment
1246 chAttr = SCE_H_COMMENT;
1247 } else if (s[0] == '/') { // Closing tag
1248 if (keywords.InList(s + 1))
1249 chAttr = SCE_H_TAG;
1250 } else {
1251 if (keywords.InList(s)) {
1252 chAttr = SCE_H_TAG;
1253 if (0 == strcmp(s, "script"))
1254 chAttr = SCE_H_SCRIPT;
1255 }
1256 }
1257 styler.ColourTo(end, chAttr);
1258 return chAttr;
1259 }
1260
1261 static void classifyWordHTJS(unsigned int start, unsigned int end,
1262 WordList &keywords, StylingContext &styler) {
1263 char s[100];
1264 bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
1265 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
1266 s[i] = styler[start + i];
1267 s[i + 1] = '\0';
1268 }
1269 char chAttr = SCE_HJ_WORD;
1270 if (wordIsNumber)
1271 chAttr = SCE_HJ_NUMBER;
1272 else {
1273 if (keywords.InList(s))
1274 chAttr = SCE_HJ_KEYWORD;
1275 }
1276 styler.ColourTo(end, chAttr);
1277 }
1278
1279 static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
1280 char s[100];
1281 bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
1282 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
1283 s[i] = tolower(styler[start + i]);
1284 s[i + 1] = '\0';
1285 }
1286 char chAttr = SCE_HB_IDENTIFIER;
1287 if (wordIsNumber)
1288 chAttr = SCE_HB_NUMBER;
1289 else {
1290 if (keywords.InList(s)) {
1291 chAttr = SCE_HB_WORD;
1292 if (strcmp(s, "rem") == 0)
1293 chAttr = SCE_HB_COMMENTLINE;
1294 }
1295 }
1296 styler.ColourTo(end, chAttr);
1297 if (chAttr == SCE_HB_COMMENTLINE)
1298 return SCE_HB_COMMENTLINE;
1299 else
1300 return SCE_HB_DEFAULT;
1301 }
1302
1303 static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler, char *prevWord) {
1304 char s[100];
1305 bool wordIsNumber = isdigit(styler[start]);
1306 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
1307 s[i] = styler[start + i];
1308 s[i + 1] = '\0';
1309 }
1310 char chAttr = SCE_HP_IDENTIFIER;
1311 if (0 == strcmp(prevWord, "class"))
1312 chAttr = SCE_HP_CLASSNAME;
1313 else if (0 == strcmp(prevWord, "def"))
1314 chAttr = SCE_HP_DEFNAME;
1315 else if (wordIsNumber)
1316 chAttr = SCE_HP_NUMBER;
1317 else if (keywords.InList(s))
1318 chAttr = SCE_HP_WORD;
1319 styler.ColourTo(end, chAttr);
1320 strcpy(prevWord, s);
1321 }
1322
1323 inline bool ishtmlwordchar(char ch) {
1324 return isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || ch == '#';
1325 }
1326
1327 static bool InTagState(int state) {
1328 return state == SCE_H_TAG || state == SCE_H_TAGUNKNOWN ||
1329 state == SCE_H_SCRIPT ||
1330 state == SCE_H_ATTRIBUTE || state == SCE_H_ATTRIBUTEUNKNOWN ||
1331 state == SCE_H_NUMBER || state == SCE_H_OTHER ||
1332 state == SCE_H_DOUBLESTRING || state == SCE_H_SINGLESTRING;
1333 }
1334
1335 static bool isLineEnd(char ch) {
1336 return ch == '\r' || ch == '\n';
1337 }
1338
1339 static void ColouriseHyperTextDoc(int codePage, int startPos, int length,
1340 int initStyle, WordList &keywords, WordList &keywords2, WordList &keywords3, WordList &keywords4,
1341 StylingContext &styler) {
1342
1343 styler.StartAt(startPos, 63);
1344 bool lastTagWasScript = false;
1345 char prevWord[200];
1346 prevWord[0] = '\0';
1347 int scriptLanguage = eScriptJS;
1348 int state = initStyle;
1349 // If inside a tag, it may be a script tage, so reread from the start to ensure any language tas are seen
1350 if (InTagState(state)) {
1351 while ((startPos > 1) && (InTagState(styler.StyleAt(startPos - 1)))) {
1352 startPos--;
1353 }
1354 state = SCE_H_DEFAULT;
1355 }
1356 styler.StartAt(startPos, 63);
1357
1358 int lineState = eScriptVBS;
1359 int lineCurrent = styler.GetLine(startPos);
1360 if (lineCurrent > 0)
1361 lineState = styler.GetLineState(lineCurrent);
1362 int defaultScript = lineState &0xff;
1363 int beforeASP = (lineState >> 8) &0xff;
1364 int inASP = (lineState >> 16) &0xff;
1365
1366 char chPrev = ' ';
1367 char chPrev2 = ' ';
1368 styler.StartSegment(startPos);
1369 int lengthDoc = startPos + length;
1370 for (int i = startPos; i <= lengthDoc; i++) {
1371 char ch = styler[i];
1372 char chNext = styler.SafeGetCharAt(i + 1);
1373 char chNext2 = styler.SafeGetCharAt(i + 2);
1374
1375 if (IsLeadByte(codePage, ch)) { // dbcs
1376 chPrev2 = ' ';
1377 chPrev = ' ';
1378 i += 1;
1379 continue;
1380 }
1381
1382 if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
1383 // New line -> record any line state onto /next/ line
1384 lineCurrent++;
1385 styler.SetLineState(lineCurrent,
1386 defaultScript | (beforeASP << 8) | (inASP << 16));
1387 }
1388
1389 // Handle ASP even within other constructs as it is a preprocessor
1390 if ((ch == '<') && (chNext == '%')) {
1391 beforeASP = state;
1392 styler.ColourTo(i - 1, state);
1393 if (chNext2 == '@') {
1394 styler.ColourTo(i + 2, SCE_H_ASP);
1395 state = SCE_H_ASPAT;
1396 i+=2;
1397 } else {
1398 if (defaultScript == eScriptVBS)
1399 state = SCE_HB_START;
1400 else if (defaultScript == eScriptPython)
1401 state = SCE_HP_START;
1402 else
1403 state = SCE_HJ_START;
1404 if (chNext2 == '=') {
1405 styler.ColourTo(i + 2, SCE_H_ASP);
1406 i+=2;
1407 } else {
1408 styler.ColourTo(i + 1, SCE_H_ASP);
1409 i++;
1410 }
1411 }
1412 inASP = 1;
1413 continue;
1414 }
1415 if (inASP && (ch == '%') && (chNext == '>')) {
1416 if (state == SCE_H_ASPAT)
1417 defaultScript = segIsScriptingIndicator(styler, styler.GetStartSegment(), i-1, defaultScript);
1418 // Bounce out of any ASP mode
1419 styler.ColourTo(i - 1, state);
1420 //if (state == SCE_H_ASPAT)
1421 // styler.ColourTo(i+1, SCE_H_ASPAT);
1422 //else
1423 styler.ColourTo(i+1, SCE_H_ASP);
1424 i++;
1425 state = beforeASP;
1426 beforeASP = SCE_H_DEFAULT;
1427 inASP = 0;
1428 continue;
1429 }
1430
1431 if (state == SCE_H_DEFAULT) {
1432 if (ch == '<') {
1433 styler.ColourTo(i - 1, state);
1434 state = SCE_H_TAGUNKNOWN;
1435 if (chNext == '?') {
1436 styler.ColourTo(i + 1, SCE_H_XMLSTART);
1437 i++;
1438 ch = chNext;
1439 }
1440 } else if (ch == '&') {
1441 styler.ColourTo(i - 1, SCE_H_DEFAULT);
1442 state = SCE_H_ENTITY;
1443 }
1444 } else if (state == SCE_H_COMMENT) {
1445 if ((ch == '>') && (chPrev == '-')) {
1446 styler.ColourTo(i, state);
1447 state = SCE_H_DEFAULT;
1448 }
1449 } else if (state == SCE_H_ENTITY) {
1450 if (ch == ';') {
1451 styler.ColourTo(i, state);
1452 state = SCE_H_DEFAULT;
1453 }
1454 } else if (state == SCE_H_TAGUNKNOWN) {
1455 if (!ishtmlwordchar(ch) && ch != '/' && ch != '-') {
1456 int eClass = classifyTagHTML(styler.GetStartSegment(), i - 1, keywords, styler);
1457 lastTagWasScript = eClass == SCE_H_SCRIPT;
1458 if (lastTagWasScript) {
1459 scriptLanguage = eScriptJS;
1460 eClass = SCE_H_TAG;
1461 }
1462 if (ch == '>') {
1463 styler.ColourTo(i, SCE_H_TAG);
1464 if (lastTagWasScript) {
1465 if (scriptLanguage == eScriptVBS)
1466 state = SCE_HB_START;
1467 else if (scriptLanguage == eScriptPython)
1468 state = SCE_HP_START;
1469 else
1470 state = SCE_HJ_START;
1471 } else {
1472 state = SCE_H_DEFAULT;
1473 }
1474 } else {
1475 if (eClass == SCE_H_COMMENT) {
1476 state = SCE_H_COMMENT;
1477 } else {
1478 state = SCE_H_OTHER;
1479 }
1480 }
1481 }
1482 } else if (state == SCE_H_ATTRIBUTE) {
1483 if (!ishtmlwordchar(ch) && ch != '/' && ch != '-') {
1484 if (lastTagWasScript)
1485 scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i-1, scriptLanguage);
1486 classifyAttribHTML(styler.GetStartSegment(), i - 1, keywords, styler);
1487 if (ch == '>') {
1488 styler.ColourTo(i, SCE_H_TAG);
1489 if (lastTagWasScript) {
1490 if (scriptLanguage == eScriptVBS)
1491 state = SCE_HB_START;
1492 else if (scriptLanguage == eScriptPython)
1493 state = SCE_HP_START;
1494 else
1495 state = SCE_HJ_START;
1496 } else {
1497 state = SCE_H_DEFAULT;
1498 }
1499 } else {
1500 state = SCE_H_OTHER;
1501 }
1502 }
1503 } else if (state == SCE_H_ASP) {
1504 if ((ch == '>') && (chPrev == '%')) {
1505 styler.ColourTo(i, state);
1506 state = SCE_H_DEFAULT;
1507 }
1508 } else if (state == SCE_H_ASPAT) {
1509 if ((ch == '>') && (chPrev == '%')) {
1510 styler.ColourTo(i, state);
1511 state = SCE_H_DEFAULT;
1512 }
1513 } else if (state == SCE_H_OTHER) {
1514 if (ch == '>') {
1515 styler.ColourTo(i - 1, state);
1516 styler.ColourTo(i, SCE_H_TAG);
1517 if (lastTagWasScript) {
1518 if (scriptLanguage == eScriptVBS)
1519 state = SCE_HB_START;
1520 else if (scriptLanguage == eScriptPython)
1521 state = SCE_HP_START;
1522 else
1523 state = SCE_HJ_START;
1524 } else {
1525 state = SCE_H_DEFAULT;
1526 }
1527 } else if (ch == '\"') {
1528 styler.ColourTo(i - 1, state);
1529 state = SCE_H_DOUBLESTRING;
1530 } else if (ch == '\'') {
1531 styler.ColourTo(i - 1, state);
1532 state = SCE_H_SINGLESTRING;
1533 } else if (ch == '/' && chNext == '>') {
1534 styler.ColourTo(i - 1, state);
1535 styler.ColourTo(i + 1, SCE_H_TAGEND);
1536 i++;
1537 ch = chNext;
1538 state = SCE_H_DEFAULT;
1539 } else if (ch == '?' && chNext == '>') {
1540 styler.ColourTo(i - 1, state);
1541 styler.ColourTo(i + 1, SCE_H_XMLEND);
1542 i++;
1543 ch = chNext;
1544 state = SCE_H_DEFAULT;
1545 } else if (ishtmlwordchar(ch)) {
1546 styler.ColourTo(i - 1, state);
1547 state = SCE_H_ATTRIBUTE;
1548 }
1549 } else if (state == SCE_H_DOUBLESTRING) {
1550 if (ch == '\"') {
1551 if (lastTagWasScript)
1552 scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
1553 styler.ColourTo(i, SCE_H_DOUBLESTRING);
1554 state = SCE_H_OTHER;
1555 }
1556 } else if (state == SCE_H_SINGLESTRING) {
1557 if (ch == '\'') {
1558 if (lastTagWasScript)
1559 scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment(), i, scriptLanguage);
1560 styler.ColourTo(i, SCE_H_SINGLESTRING);
1561 state = SCE_H_OTHER;
1562 }
1563 } else if (state == SCE_HJ_DEFAULT || state == SCE_HJ_START) {
1564 if (iswordstart(ch)) {
1565 styler.ColourTo(i - 1, state);
1566 state = SCE_HJ_WORD;
1567 } else if (ch == '/' && chNext == '*') {
1568 styler.ColourTo(i - 1, state);
1569 if (chNext2 == '*')
1570 state = SCE_HJ_COMMENTDOC;
1571 else
1572 state = SCE_HJ_COMMENT;
1573 } else if (ch == '/' && chNext == '/') {
1574 styler.ColourTo(i - 1, state);
1575 state = SCE_HJ_COMMENTLINE;
1576 } else if (ch == '\"') {
1577 styler.ColourTo(i - 1, state);
1578 state = SCE_HJ_DOUBLESTRING;
1579 } else if (ch == '\'') {
1580 styler.ColourTo(i - 1, state);
1581 state = SCE_HJ_SINGLESTRING;
1582 } else if ((ch == '<') && (chNext == '/')) {
1583 styler.ColourTo(i - 1, state);
1584 state = SCE_H_TAGUNKNOWN;
1585 } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
1586 styler.SafeGetCharAt(i + 3) == '-') {
1587 styler.ColourTo(i - 1, state);
1588 state = SCE_HJ_COMMENTLINE;
1589 } else if (isoperator(ch)) {
1590 styler.ColourTo(i - 1, state);
1591 styler.ColourTo(i, SCE_HJ_SYMBOLS);
1592 state = SCE_HJ_DEFAULT;
1593 } else if ((ch == ' ') || (ch == '\t')) {
1594 if (state == SCE_HJ_START) {
1595 styler.ColourTo(i - 1, state);
1596 state = SCE_HJ_DEFAULT;
1597 }
1598 }
1599 } else if (state == SCE_HJ_WORD) {
1600 if (!iswordchar(ch)) {
1601 classifyWordHTJS(styler.GetStartSegment(), i - 1, keywords2, styler);
1602 //styler.ColourTo(i - 1, eHTJSKeyword);
1603 state = SCE_HJ_DEFAULT;
1604 if (ch == '/' && chNext == '*') {
1605 if (chNext2 == '*')
1606 state = SCE_HJ_COMMENTDOC;
1607 else
1608 state = SCE_HJ_COMMENT;
1609 } else if (ch == '/' && chNext == '/') {
1610 state = SCE_HJ_COMMENTLINE;
1611 } else if (ch == '\"') {
1612 state = SCE_HJ_DOUBLESTRING;
1613 } else if (ch == '\'') {
1614 state = SCE_HJ_SINGLESTRING;
1615 } else if (isoperator(ch)) {
1616 styler.ColourTo(i, SCE_HJ_SYMBOLS);
1617 state = SCE_HJ_DEFAULT;
1618 }
1619 }
1620 } else if (state == SCE_HJ_COMMENT) {
1621 if (ch == '/' && chPrev == '*') {
1622 state = SCE_HJ_DEFAULT;
1623 styler.ColourTo(i, SCE_HJ_COMMENT);
1624 } else if ((ch == '<') && (chNext == '/')) {
1625 styler.ColourTo(i - 1, state);
1626 styler.ColourTo(i + 1, SCE_H_TAGEND);
1627 i++;
1628 ch = chNext;
1629 state = SCE_H_DEFAULT;
1630 }
1631 } else if (state == SCE_HJ_COMMENTDOC) {
1632 if (ch == '/' && chPrev == '*') {
1633 state = SCE_HJ_DEFAULT;
1634 styler.ColourTo(i, SCE_HJ_COMMENTDOC);
1635 } else if ((ch == '<') && (chNext == '/')) {
1636 styler.ColourTo(i - 1, state);
1637 styler.ColourTo(i + 1, SCE_H_TAGEND);
1638 i++;
1639 ch = chNext;
1640 state = SCE_H_DEFAULT;
1641 }
1642 } else if (state == SCE_HJ_COMMENTLINE) {
1643 if (ch == '\r' || ch == '\n') {
1644 styler.ColourTo(i - 1, SCE_HJ_COMMENTLINE);
1645 state = SCE_HJ_DEFAULT;
1646 } else if ((ch == '<') && (chNext == '/')) {
1647 // Common to hide end script tag in comment
1648 styler.ColourTo(i - 1, SCE_HJ_COMMENTLINE);
1649 state = SCE_H_TAGUNKNOWN;
1650 }
1651 } else if (state == SCE_HJ_DOUBLESTRING) {
1652 if (ch == '\\') {
1653 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
1654 i++;
1655 }
1656 } else if (ch == '\"') {
1657 styler.ColourTo(i, SCE_HJ_DOUBLESTRING);
1658 state = SCE_HJ_DEFAULT;
1659 i++;
1660 ch = chNext;
1661 } else if (isLineEnd(ch)) {
1662 styler.ColourTo(i-1, state);
1663 state = SCE_HJ_STRINGEOL;
1664 }
1665 } else if (state == SCE_HJ_SINGLESTRING) {
1666 if (ch == '\\') {
1667 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
1668 i++;
1669 }
1670 } else if (ch == '\'') {
1671 styler.ColourTo(i, SCE_HJ_SINGLESTRING);
1672 state = SCE_HJ_DEFAULT;
1673 i++;
1674 ch = chNext;
1675 } else if (isLineEnd(ch)) {
1676 styler.ColourTo(i-1, state);
1677 state = SCE_HJ_STRINGEOL;
1678 }
1679 } else if (state == SCE_HJ_STRINGEOL) {
1680 if (!isLineEnd(ch)) {
1681 styler.ColourTo(i - 1, state);
1682 state = SCE_HJ_DEFAULT;
1683 }
1684 } else if (state == SCE_HB_DEFAULT || state == SCE_HB_START) {
1685 if (iswordstart(ch)) {
1686 styler.ColourTo(i - 1, state);
1687 state = SCE_HB_WORD;
1688 } else if (ch == '\'') {
1689 styler.ColourTo(i - 1, state);
1690 state = SCE_HB_COMMENTLINE;
1691 } else if (ch == '\"') {
1692 styler.ColourTo(i - 1, state);
1693 state = SCE_HB_STRING;
1694 } else if ((ch == '<') && (chNext == '/')) {
1695 styler.ColourTo(i - 1, state);
1696 state = SCE_H_TAGUNKNOWN;
1697 } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
1698 styler.SafeGetCharAt(i + 3) == '-') {
1699 styler.ColourTo(i - 1, state);
1700 state = SCE_HB_COMMENTLINE;
1701 } else if (isoperator(ch)) {
1702 styler.ColourTo(i - 1, state);
1703 styler.ColourTo(i, SCE_HB_DEFAULT);
1704 state = SCE_HB_DEFAULT;
1705 } else if ((ch == ' ') || (ch == '\t')) {
1706 if (state == SCE_HB_START) {
1707 styler.ColourTo(i - 1, state);
1708 state = SCE_HB_DEFAULT;
1709 }
1710 }
1711 } else if (state == SCE_HB_WORD) {
1712 if (!iswordchar(ch)) {
1713 state = classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler);
1714 if (state == SCE_HB_DEFAULT) {
1715 if (ch == '\"') {
1716 state = SCE_HB_STRING;
1717 } else if (ch == '\'') {
1718 state = SCE_HB_COMMENTLINE;
1719 } else if (isoperator(ch)) {
1720 styler.ColourTo(i, SCE_HB_DEFAULT);
1721 state = SCE_HB_DEFAULT;
1722 }
1723 }
1724 }
1725 } else if (state == SCE_HB_STRING) {
1726 if (ch == '\"') {
1727 styler.ColourTo(i, state);
1728 state = SCE_HB_DEFAULT;
1729 i++;
1730 ch = chNext;
1731 } else if (ch == '\r' || ch == '\n') {
1732 styler.ColourTo(i-1, state);
1733 state = SCE_HB_STRINGEOL;
1734 }
1735 } else if (state == SCE_HB_COMMENTLINE) {
1736 if (ch == '\r' || ch == '\n') {
1737 styler.ColourTo(i - 1, state);
1738 state = SCE_HB_DEFAULT;
1739 } else if ((ch == '<') && (chNext == '/')) {
1740 // Common to hide end script tag in comment
1741 styler.ColourTo(i - 1, state);
1742 state = SCE_H_TAGUNKNOWN;
1743 }
1744 } else if (state == SCE_HB_STRINGEOL) {
1745 if (!isLineEnd(ch)) {
1746 styler.ColourTo(i - 1, state);
1747 state = SCE_HB_DEFAULT;
1748 }
1749 } else if (state == SCE_HP_DEFAULT || state == SCE_HP_START) {
1750 if (iswordstart(ch)) {
1751 styler.ColourTo(i - 1, state);
1752 state = SCE_HP_WORD;
1753 } else if ((ch == '<') && (chNext == '/')) {
1754 styler.ColourTo(i - 1, state);
1755 state = SCE_H_TAGUNKNOWN;
1756 } else if ((ch == '<') && (chNext == '!') && (chNext2 == '-') &&
1757 styler.SafeGetCharAt(i + 3) == '-') {
1758 styler.ColourTo(i - 1, state);
1759 state = SCE_HP_COMMENTLINE;
1760 } else if (ch == '#') {
1761 styler.ColourTo(i - 1, state);
1762 state = SCE_HP_COMMENTLINE;
1763 } else if (ch == '\"') {
1764 styler.ColourTo(i - 1, state);
1765 if (chNext == '\"' && chNext2 == '\"') {
1766 i += 2;
1767 state = SCE_HP_TRIPLEDOUBLE;
1768 ch = ' ';
1769 chPrev = ' ';
1770 chNext = styler.SafeGetCharAt(i + 1);
1771 } else {
1772 state = SCE_HP_STRING;
1773 }
1774 } else if (ch == '\'') {
1775 styler.ColourTo(i - 1, state);
1776 if (chNext == '\'' && chNext2 == '\'') {
1777 i += 2;
1778 state = SCE_HP_TRIPLE;
1779 ch = ' ';
1780 chPrev = ' ';
1781 chNext = styler.SafeGetCharAt(i + 1);
1782 } else {
1783 state = SCE_HP_CHARACTER;
1784 }
1785 } else if (isoperator(ch)) {
1786 styler.ColourTo(i - 1, state);
1787 styler.ColourTo(i, SCE_HP_OPERATOR);
1788 } else if ((ch == ' ') || (ch == '\t')) {
1789 if (state == SCE_HP_START) {
1790 styler.ColourTo(i - 1, state);
1791 state = SCE_HP_DEFAULT;
1792 }
1793 }
1794 } else if (state == SCE_HP_WORD) {
1795 if (!iswordchar(ch)) {
1796 classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord);
1797 state = SCE_HP_DEFAULT;
1798 if (ch == '#') {
1799 state = SCE_HP_COMMENTLINE;
1800 } else if (ch == '\"') {
1801 if (chNext == '\"' && chNext2 == '\"') {
1802 i += 2;
1803 state = SCE_HP_TRIPLEDOUBLE;
1804 ch = ' ';
1805 chPrev = ' ';
1806 chNext = styler.SafeGetCharAt(i + 1);
1807 } else {
1808 state = SCE_HP_STRING;
1809 }
1810 } else if (ch == '\'') {
1811 if (chNext == '\'' && chNext2 == '\'') {
1812 i += 2;
1813 state = SCE_HP_TRIPLE;
1814 ch = ' ';
1815 chPrev = ' ';
1816 chNext = styler.SafeGetCharAt(i + 1);
1817 } else {
1818 state = SCE_HP_CHARACTER;
1819 }
1820 } else if (isoperator(ch)) {
1821 styler.ColourTo(i, SCE_HP_OPERATOR);
1822 }
1823 }
1824 } else {
1825 if (state == SCE_HP_COMMENTLINE) {
1826 if (ch == '\r' || ch == '\n') {
1827 styler.ColourTo(i - 1, state);
1828 state = SCE_HP_DEFAULT;
1829 }
1830 } else if (state == SCE_HP_STRING) {
1831 if (ch == '\\') {
1832 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
1833 i++;
1834 ch = chNext;
1835 chNext = styler.SafeGetCharAt(i + 1);
1836 }
1837 } else if (ch == '\"') {
1838 styler.ColourTo(i, state);
1839 state = SCE_HP_DEFAULT;
1840 }
1841 } else if (state == SCE_HP_CHARACTER) {
1842 if (ch == '\\') {
1843 if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
1844 i++;
1845 ch = chNext;
1846 chNext = styler.SafeGetCharAt(i + 1);
1847 }
1848 } else if (ch == '\'') {
1849 styler.ColourTo(i, state);
1850 state = SCE_HP_DEFAULT;
1851 }
1852 } else if (state == SCE_HP_TRIPLE) {
1853 if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
1854 styler.ColourTo(i, state);
1855 state = SCE_HP_DEFAULT;
1856 }
1857 } else if (state == SCE_HP_TRIPLEDOUBLE) {
1858 if (ch == '\"' && chPrev == '\"' && chPrev2 == '\"') {
1859 styler.ColourTo(i, state);
1860 state = SCE_HP_DEFAULT;
1861 }
1862 }
1863 }
1864 if (state == SCE_HB_DEFAULT) { // One of the above succeeded
1865 if (ch == '\"') {
1866 state = SCE_HB_STRING;
1867 } else if (ch == '\'') {
1868 state = SCE_HB_COMMENTLINE;
1869 } else if (iswordstart(ch)) {
1870 state = SCE_HB_WORD;
1871 } else if (isoperator(ch)) {
1872 styler.ColourTo(i, SCE_HB_DEFAULT);
1873 }
1874 }
1875 if (state == SCE_HJ_DEFAULT) { // One of the above succeeded
1876 if (ch == '/' && chNext == '*') {
1877 if (styler.SafeGetCharAt(i + 2) == '*')
1878 state = SCE_HJ_COMMENTDOC;
1879 else
1880 state = SCE_HJ_COMMENT;
1881 } else if (ch == '/' && chNext == '/') {
1882 state = SCE_HJ_COMMENTLINE;
1883 } else if (ch == '\"') {
1884 state = SCE_HJ_DOUBLESTRING;
1885 } else if (ch == '\'') {
1886 state = SCE_HJ_SINGLESTRING;
1887 } else if (iswordstart(ch)) {
1888 state = SCE_HJ_WORD;
1889 } else if (isoperator(ch)) {
1890 styler.ColourTo(i, SCE_HJ_SYMBOLS);
1891 }
1892 }
1893 chPrev2 = chPrev;
1894 chPrev = ch;
1895 }
1896 styler.ColourTo(lengthDoc - 1, state);
1897 }
1898
1899 static void ColourisePropsLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
1900 int i = 0;
1901 while (isspace(lineBuffer[i]) && (i < lengthLine)) // Skip initial spaces
1902 i++;
1903 if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') {
1904 styler.ColourSegment(0, lengthLine - 1, 1);
1905 } else if (lineBuffer[i] == '[') {
1906 styler.ColourSegment(0, lengthLine - 1, 2);
1907 } else if (lineBuffer[i] == '@') {
1908 styler.ColourSegment(0, i, 4);
1909 if (lineBuffer[++i] == '=')
1910 styler.ColourSegment(i, i, 3);
1911 if (++i < lengthLine)
1912 styler.ColourSegment(i, lengthLine - 1, 0);
1913 } else {
1914 while (lineBuffer[i] != '=' && (i < lengthLine)) // Search the '=' character
1915 i++;
1916 if (lineBuffer[i] == '=') {
1917 styler.ColourSegment(0, i - 1, 0);
1918 styler.ColourSegment(i, i, 3);
1919 if (++i < lengthLine)
1920 styler.ColourSegment(i, lengthLine - 1, 0);
1921 } else
1922 styler.ColourSegment(0, lengthLine - 1, 0);
1923 }
1924 }
1925
1926 static void ColourisePropsDoc(int startPos, int length, int, StylingContext &styler) {
1927 char lineBuffer[1024];
1928 unsigned int linePos = 0;
1929 for (int i = startPos; i <= startPos + length; i++) {
1930 lineBuffer[linePos++] = styler[i];
1931 if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
1932 lineBuffer[linePos] = '\0';
1933 ColourisePropsLine(lineBuffer, linePos, styler);
1934 linePos = 0;
1935 }
1936 }
1937 if (linePos > 0)
1938 ColourisePropsLine(lineBuffer, linePos, styler);
1939 }
1940
1941 static void ColouriseMakeLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
1942 int i = 0;
1943 while (isspace(lineBuffer[i]) && (i < lengthLine))
1944 i++;
1945 if (lineBuffer[i] == '#' || lineBuffer[i] == '!') {
1946 styler.ColourSegment(0, lengthLine - 1, 1);
1947 } else {
1948 styler.ColourSegment(0, lengthLine - 1, 0);
1949 }
1950 }
1951
1952 static void ColouriseMakeDoc(int startPos, int length, int, StylingContext &styler) {
1953 char lineBuffer[1024];
1954 unsigned int linePos = 0;
1955 for (int i = startPos; i <= startPos + length; i++) {
1956 lineBuffer[linePos++] = styler[i];
1957 if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
1958 ColouriseMakeLine(lineBuffer, linePos, styler);
1959 linePos = 0;
1960 }
1961 }
1962 if (linePos > 0)
1963 ColouriseMakeLine(lineBuffer, linePos, styler);
1964 }
1965
1966 static void ColouriseErrorListLine(char *lineBuffer, int lengthLine, StylingContext &styler) {
1967 if (lineBuffer[0] == '>') {
1968 // Command or return status
1969 styler.ColourSegment(0, lengthLine - 1, 4);
1970 } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
1971 styler.ColourSegment(0, lengthLine - 1, 1);
1972 } else if (0 == strncmp(lineBuffer, "Error ", strlen("Error "))) {
1973 // Borland error message
1974 styler.ColourSegment(0, lengthLine - 1, 5);
1975 } else if (0 == strncmp(lineBuffer, "Warning ", strlen("Warning "))) {
1976 // Borland warning message
1977 styler.ColourSegment(0, lengthLine - 1, 5);
1978 } else {
1979 // Look for <filename>:<line>:message
1980 // Look for <filename>(line)message
1981 // Look for <filename>(line,pos)message
1982 int state = 0;
1983 for (int i = 0; i < lengthLine; i++) {
1984 if (state == 0 && lineBuffer[i] == ':' && isdigit(lineBuffer[i + 1])) {
1985 state = 1;
1986 } else if (state == 0 && lineBuffer[i] == '(') {
1987 state = 10;
1988 } else if (state == 1 && isdigit(lineBuffer[i])) {
1989 state = 2;
1990 } else if (state == 2 && lineBuffer[i] == ':') {
1991 state = 3;
1992 break;
1993 } else if (state == 2 && !isdigit(lineBuffer[i])) {
1994 state = 99;
1995 } else if (state == 10 && isdigit(lineBuffer[i])) {
1996 state = 11;
1997 } else if (state == 11 && lineBuffer[i] == ',') {
1998 state = 14;
1999 } else if (state == 11 && lineBuffer[i] == ')') {
2000 state = 12;
2001 break;
2002 } else if (state == 12 && lineBuffer[i] == ':') {
2003 state = 13;
2004 } else if (state == 14 && lineBuffer[i] == ')') {
2005 state = 15;
2006 break;
2007 } else if (((state == 11) || (state == 14)) && !((lineBuffer[i] == ' ') || isdigit(lineBuffer[i]))) {
2008 state = 99;
2009 }
2010 }
2011 if (state == 3) {
2012 styler.ColourSegment(0, lengthLine - 1, 2);
2013 } else if ((state == 14) || (state == 15)) {
2014 styler.ColourSegment(0, lengthLine - 1, 3);
2015 } else {
2016 styler.ColourSegment(0, lengthLine - 1, 0);
2017 }
2018 }
2019 }
2020
2021 static void ColouriseErrorListDoc(int startPos, int length, int, StylingContext &styler) {
2022 char lineBuffer[1024];
2023 unsigned int linePos = 0;
2024 for (int i = startPos; i <= startPos + length; i++) {
2025 lineBuffer[linePos++] = styler[i];
2026 if (styler[i] == '\r' || styler[i] == '\n' || (linePos >= sizeof(lineBuffer) - 1)) {
2027 ColouriseErrorListLine(lineBuffer, linePos, styler);
2028 linePos = 0;
2029 }
2030 }
2031 if (linePos > 0)
2032 ColouriseErrorListLine(lineBuffer, linePos, styler);
2033 }
2034
2035 static void classifyWordSQL(unsigned int start, unsigned int end, WordList &keywords, StylingContext &styler) {
2036 char s[100];
2037 bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
2038 for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
2039 s[i] = toupper(styler[start + i]);
2040 s[i + 1] = '\0';
2041 }
2042 char chAttr = SCE_C_IDENTIFIER;
2043 if (wordIsNumber)
2044 chAttr = SCE_C_NUMBER;
2045 else {
2046 if (keywords.InList(s))
2047 chAttr = SCE_C_WORD;
2048 }
2049 styler.ColourSegment(start, end, chAttr);
2050 }
2051
2052 static void ColouriseSQLDoc(int codePage, int startPos, int length,
2053 int initStyle, WordList &keywords, StylingContext &styler) {
2054
2055 bool fold = styler.GetPropSet().GetInt("fold");
2056 int lineCurrent = styler.GetLine(startPos);
2057 int spaceFlags = 0;
2058 int indentCurrent = 0;
2059
2060 int state = initStyle;
2061 char chPrev = ' ';
2062 char chNext = styler[startPos];
2063 int startSeg = startPos;
2064 int lengthDoc = startPos + length;
2065 bool prevCr = false;
2066 for (int i = startPos; i <= lengthDoc; i++) {
2067 char ch = chNext;
2068 chNext = styler.SafeGetCharAt(i + 1);
2069
2070 if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
2071 indentCurrent = IndentAmount(styler, lineCurrent, &spaceFlags);
2072 int lev = indentCurrent;
2073 if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
2074 // Only non whitespace lines can be headers
2075 int indentNext = IndentAmount(styler, lineCurrent + 1, &spaceFlags);
2076 if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
2077 lev |= SC_FOLDLEVELHEADERFLAG;
2078 }
2079 }
2080 if (fold) {
2081 styler.SetLevel(lineCurrent, lev);
2082 }
2083 }
2084
2085 if (IsLeadByte(codePage, ch)) { // dbcs
2086 chNext = styler.SafeGetCharAt(i + 2);
2087 chPrev = ' ';
2088 i += 1;
2089 continue;
2090 }
2091
2092 if (state == SCE_C_DEFAULT) {
2093 if (iswordstart(ch)) {
2094 styler.ColourSegment(startSeg, i - 1, state);
2095 state = SCE_C_WORD;
2096 startSeg = i;
2097 } else if (ch == '/' && chNext == '*') {
2098 styler.ColourSegment(startSeg, i - 1, state);
2099 state = SCE_C_COMMENT;
2100 startSeg = i;
2101 } else if (ch == '-' && chNext == '-') {
2102 styler.ColourSegment(startSeg, i - 1, state);
2103 state = SCE_C_COMMENTLINE;
2104 startSeg = i;
2105 } else if (ch == '\'') {
2106 styler.ColourSegment(startSeg, i - 1, state);
2107 state = SCE_C_STRING;
2108 startSeg = i;
2109 } else if (isoperator(ch)) {
2110 styler.ColourSegment(startSeg, i - 1, state);
2111 styler.ColourSegment(i, i, SCE_C_OPERATOR);
2112 startSeg = i + 1;
2113 }
2114 } else if (state == SCE_C_WORD) {
2115 if (!iswordchar(ch)) {
2116 classifyWordSQL(startSeg, i - 1, keywords, styler);
2117 state = SCE_C_DEFAULT;
2118 startSeg = i;
2119 if (ch == '/' && chNext == '*') {
2120 state = SCE_C_COMMENT;
2121 } else if (ch == '-' && chNext == '-') {
2122 state = SCE_C_COMMENTLINE;
2123 } else if (ch == '\'') {
2124 state = SCE_C_STRING;
2125 } else if (isoperator(ch)) {
2126 styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
2127 startSeg = i + 1;
2128 }
2129 }
2130 } else {
2131 if (state == SCE_C_COMMENT) {
2132 if (ch == '/' && chPrev == '*' && (
2133 (i > startSeg + 2) || ((initStyle == SCE_C_COMMENT) && (startSeg == startPos)))) {
2134 state = SCE_C_DEFAULT;
2135 styler.ColourSegment(startSeg, i, state);
2136 startSeg = i + 1;
2137 }
2138 } else if (state == SCE_C_COMMENTLINE) {
2139 if (ch == '\r' || ch == '\n') {
2140 styler.ColourSegment(startSeg, i - 1, state);
2141 state = SCE_C_DEFAULT;
2142 startSeg = i;
2143 }
2144 } else if (state == SCE_C_STRING) {
2145 if (ch == '\'') {
2146 if ( chNext == '\'' ) {
2147 i++;
2148 } else {
2149 styler.ColourSegment(startSeg, i, state);
2150 state = SCE_C_DEFAULT;
2151 i++;
2152 startSeg = i;
2153 }
2154 ch = chNext;
2155 chNext = styler.SafeGetCharAt(i + 1);
2156 }
2157 }
2158 if (state == SCE_C_DEFAULT) { // One of the above succeeded
2159 if (ch == '/' && chNext == '*') {
2160 state = SCE_C_COMMENT;
2161 } else if (ch == '-' && chNext == '-') {
2162 state = SCE_C_COMMENTLINE;
2163 } else if (ch == '\'') {
2164 state = SCE_C_STRING;
2165 } else if (iswordstart(ch)) {
2166 state = SCE_C_WORD;
2167 } else if (isoperator(ch)) {
2168 styler.ColourSegment(startSeg, i, SCE_C_OPERATOR);
2169 startSeg = i + 1;
2170 }
2171 }
2172 }
2173 chPrev = ch;
2174 }
2175 if (startSeg < lengthDoc)
2176 styler.ColourSegment(startSeg, lengthDoc - 1, state);
2177 }
2178
2179 void ColouriseDoc(int codePage, int startPos, int lengthDoc, int initStyle,
2180 int language, WordList *keywordlists[], StylingContext &styler) {
2181 //Platform::DebugPrintf("ColouriseDoc <%s>\n", language);
2182 if (language == SCLEX_PYTHON) {
2183 // Python uses a different mask because bad indentation is marked by oring with 32
2184 styler.StartAt(startPos, 127);
2185 ColourisePyDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
2186 } else if (language == SCLEX_PERL) {
2187 // Lexer for perl often has to backtrack to start of current style to determine
2188 // which characters are being used as quotes, how deeply nested is the
2189 // start position and what the termination string is for here documents
2190 ColourisePerlDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
2191 } else if ((language == SCLEX_HTML) || (language == SCLEX_XML)) {
2192 // Lexer for HTML requires more lexical states (6 bits worth) than most lexers
2193 ColouriseHyperTextDoc(codePage, startPos, lengthDoc, initStyle,
2194 *keywordlists[0], *keywordlists[1], *keywordlists[2], *keywordlists[3], styler);
2195 } else {
2196 styler.StartAt(startPos);
2197 if (language == SCLEX_CPP) {
2198 ColouriseCppDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
2199 } else if (language == SCLEX_SQL) {
2200 ColouriseSQLDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
2201 } else if (language == SCLEX_VB) {
2202 ColouriseVBDoc(codePage, startPos, lengthDoc, initStyle, *keywordlists[0], styler);
2203 } else if (language == SCLEX_PROPERTIES) {
2204 ColourisePropsDoc(startPos, lengthDoc, initStyle, styler);
2205 } else if (language == SCLEX_ERRORLIST) {
2206 ColouriseErrorListDoc(startPos, lengthDoc, initStyle, styler);
2207 } else if (language == SCLEX_MAKEFILE) {
2208 ColouriseMakeDoc(startPos, lengthDoc, initStyle, styler);
2209 } else if (language == SCLEX_BATCH) {
2210 ColouriseBatchDoc(startPos, lengthDoc, initStyle, styler);
2211 } else {
2212 // Null language means all style bytes are 0 so just mark the end - no need to fill in.
2213 styler.StartAt(startPos + lengthDoc - 1);
2214 styler.ColourSegment(0, 0, 0);
2215 }
2216 }
2217 }