]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexOthers.cxx
819dd312905ade74736add7af3ac4781c450a7f7
[wxWidgets.git] / src / stc / scintilla / src / LexOthers.cxx
1 // Scintilla source code edit control
2 /** @file LexOthers.cxx
3 ** Lexers for batch files, diff results, properties files, make files and error lists.
4 ** Also lexer for LaTeX documents.
5 **/
6 // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
7 // The License.txt file describes the conditions under which this software may be distributed.
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include <ctype.h>
12 #include <stdio.h>
13 #include <stdarg.h>
14
15 #include "Platform.h"
16
17 #include "PropSet.h"
18 #include "Accessor.h"
19 #include "KeyWords.h"
20 #include "Scintilla.h"
21 #include "SciLexer.h"
22
23 static bool Is0To9(char ch) {
24 return (ch >= '0') && (ch <= '9');
25 }
26
27 static bool Is1To9(char ch) {
28 return (ch >= '1') && (ch <= '9');
29 }
30
31 static inline bool AtEOL(Accessor &styler, unsigned int i) {
32 return (styler[i] == '\n') ||
33 ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
34 }
35
36 static void ColouriseBatchLine(
37 char *lineBuffer,
38 unsigned int lengthLine,
39 unsigned int startLine,
40 unsigned int endPos,
41 WordList &keywords,
42 Accessor &styler) {
43
44 unsigned int i = 0;
45 unsigned int state = SCE_BAT_DEFAULT;
46
47 while ((i < lengthLine) && isspacechar(lineBuffer[i])) { // Skip initial spaces
48 i++;
49 }
50 if (lineBuffer[i] == '@') { // Hide command (ECHO OFF)
51 styler.ColourTo(startLine + i, SCE_BAT_HIDE);
52 i++;
53 while ((i < lengthLine) && isspacechar(lineBuffer[i])) { // Skip next spaces
54 i++;
55 }
56 }
57 if (lineBuffer[i] == ':') {
58 // Label
59 if (lineBuffer[i + 1] == ':') {
60 // :: is a fake label, similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
61 styler.ColourTo(endPos, SCE_BAT_COMMENT);
62 } else { // Real label
63 styler.ColourTo(endPos, SCE_BAT_LABEL);
64 }
65 } else {
66 // Check if initial word is a keyword
67 char wordBuffer[21];
68 unsigned int wbl = 0, offset = i;
69 // Copy word in buffer
70 for (; offset < lengthLine && wbl < 20 &&
71 !isspacechar(lineBuffer[offset]); wbl++, offset++) {
72 wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset]));
73 }
74 wordBuffer[wbl] = '\0';
75 // Check if it is a comment
76 if (CompareCaseInsensitive(wordBuffer, "rem") == 0) {
77 styler.ColourTo(endPos, SCE_BAT_COMMENT);
78 return ;
79 }
80 // Check if it is in the list
81 if (keywords.InList(wordBuffer)) {
82 styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD); // Regular keyword
83 } else {
84 // Search end of word (can be a long path)
85 while (offset < lengthLine &&
86 !isspacechar(lineBuffer[offset])) {
87 offset++;
88 }
89 styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); // External command / program
90 }
91 // Remainder of the line: colourise the variables.
92
93 while (offset < lengthLine) {
94 if (state == SCE_BAT_DEFAULT && lineBuffer[offset] == '%') {
95 styler.ColourTo(startLine + offset - 1, state);
96 if (Is0To9(lineBuffer[offset + 1])) {
97 styler.ColourTo(startLine + offset + 1, SCE_BAT_IDENTIFIER);
98 offset += 2;
99 } else if (lineBuffer[offset + 1] == '%' &&
100 !isspacechar(lineBuffer[offset + 2])) {
101 // Should be safe, as there is CRLF at the end of the line...
102 styler.ColourTo(startLine + offset + 2, SCE_BAT_IDENTIFIER);
103 offset += 3;
104 } else {
105 state = SCE_BAT_IDENTIFIER;
106 }
107 } else if (state == SCE_BAT_IDENTIFIER && lineBuffer[offset] == '%') {
108 styler.ColourTo(startLine + offset, state);
109 state = SCE_BAT_DEFAULT;
110 } else if (state == SCE_BAT_DEFAULT &&
111 (lineBuffer[offset] == '*' ||
112 lineBuffer[offset] == '?' ||
113 lineBuffer[offset] == '=' ||
114 lineBuffer[offset] == '<' ||
115 lineBuffer[offset] == '>' ||
116 lineBuffer[offset] == '|')) {
117 styler.ColourTo(startLine + offset - 1, state);
118 styler.ColourTo(startLine + offset, SCE_BAT_OPERATOR);
119 }
120 offset++;
121 }
122 // if (endPos > startLine + offset - 1) {
123 styler.ColourTo(endPos, SCE_BAT_DEFAULT); // Remainder of line, currently not lexed
124 // }
125 }
126
127 }
128 // ToDo: (not necessarily at beginning of line) GOTO, [IF] NOT, ERRORLEVEL
129 // IF [NO] (test) (command) -- test is EXIST (filename) | (string1)==(string2) | ERRORLEVEL (number)
130 // FOR %%(variable) IN (set) DO (command) -- variable is [a-zA-Z] -- eg for %%X in (*.txt) do type %%X
131 // ToDo: %n (parameters), %EnvironmentVariable% colourising
132 // ToDo: Colourise = > >> < | "
133
134 static void ColouriseBatchDoc(
135 unsigned int startPos,
136 int length,
137 int /*initStyle*/,
138 WordList *keywordlists[],
139 Accessor &styler) {
140
141 char lineBuffer[1024];
142 WordList &keywords = *keywordlists[0];
143
144 styler.StartAt(startPos);
145 styler.StartSegment(startPos);
146 unsigned int linePos = 0;
147 unsigned int startLine = startPos;
148 for (unsigned int i = startPos; i < startPos + length; i++) {
149 lineBuffer[linePos++] = styler[i];
150 if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
151 // End of line (or of line buffer) met, colourise it
152 lineBuffer[linePos] = '\0';
153 ColouriseBatchLine(lineBuffer, linePos, startLine, i, keywords, styler);
154 linePos = 0;
155 startLine = i + 1;
156 }
157 }
158 if (linePos > 0) { // Last line does not have ending characters
159 ColouriseBatchLine(lineBuffer, linePos, startLine, startPos + length - 1,
160 keywords, styler);
161 }
162 }
163
164 static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) {
165 // It is needed to remember the current state to recognize starting
166 // comment lines before the first "diff " or "--- ". If a real
167 // difference starts then each line starting with ' ' is a whitespace
168 // otherwise it is considered a comment (Only in..., Binary file...)
169 if (0 == strncmp(lineBuffer, "diff ", 3)) {
170 styler.ColourTo(endLine, SCE_DIFF_COMMAND);
171 } else if (0 == strncmp(lineBuffer, "--- ", 3)) {
172 styler.ColourTo(endLine, SCE_DIFF_HEADER);
173 } else if (0 == strncmp(lineBuffer, "+++ ", 3)) {
174 styler.ColourTo(endLine, SCE_DIFF_HEADER);
175 } else if (0 == strncmp(lineBuffer, "====", 4)) { // For p4's diff
176 styler.ColourTo(endLine, SCE_DIFF_HEADER);
177 } else if (0 == strncmp(lineBuffer, "***", 3)) {
178 styler.ColourTo(endLine, SCE_DIFF_HEADER);
179 } else if (0 == strncmp(lineBuffer, "? ", 2)) { // For difflib
180 styler.ColourTo(endLine, SCE_DIFF_HEADER);
181 } else if (lineBuffer[0] == '@') {
182 styler.ColourTo(endLine, SCE_DIFF_POSITION);
183 } else if (lineBuffer[0] == '-' || lineBuffer[0] == '<') {
184 styler.ColourTo(endLine, SCE_DIFF_DELETED);
185 } else if (lineBuffer[0] == '+' || lineBuffer[0] == '>') {
186 styler.ColourTo(endLine, SCE_DIFF_ADDED);
187 } else if (lineBuffer[0] != ' ') {
188 styler.ColourTo(endLine, SCE_DIFF_COMMENT);
189 } else {
190 styler.ColourTo(endLine, SCE_DIFF_DEFAULT);
191 }
192 }
193
194 static void ColouriseDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
195 char lineBuffer[1024];
196 styler.StartAt(startPos);
197 styler.StartSegment(startPos);
198 unsigned int linePos = 0;
199 for (unsigned int i = startPos; i < startPos + length; i++) {
200 lineBuffer[linePos++] = styler[i];
201 if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
202 // End of line (or of line buffer) met, colourise it
203 lineBuffer[linePos] = '\0';
204 ColouriseDiffLine(lineBuffer, i, styler);
205 linePos = 0;
206 }
207 }
208 if (linePos > 0) { // Last line does not have ending characters
209 ColouriseDiffLine(lineBuffer, startPos + length - 1, styler);
210 }
211 }
212
213 static void ColourisePropsLine(
214 char *lineBuffer,
215 unsigned int lengthLine,
216 unsigned int startLine,
217 unsigned int endPos,
218 Accessor &styler) {
219
220 unsigned int i = 0;
221 while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces
222 i++;
223 if (i < lengthLine) {
224 if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') {
225 styler.ColourTo(endPos, SCE_PROPS_COMMENT);
226 } else if (lineBuffer[i] == '[') {
227 styler.ColourTo(endPos, SCE_PROPS_SECTION);
228 } else if (lineBuffer[i] == '@') {
229 styler.ColourTo(startLine + i, SCE_PROPS_DEFVAL);
230 if (lineBuffer[++i] == '=')
231 styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT);
232 styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
233 } else {
234 // Search for the '=' character
235 while ((i < lengthLine) && (lineBuffer[i] != '='))
236 i++;
237 if ((i < lengthLine) && (lineBuffer[i] == '=')) {
238 styler.ColourTo(startLine + i - 1, SCE_PROPS_DEFAULT);
239 styler.ColourTo(startLine + i, 3);
240 styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
241 } else {
242 styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
243 }
244 }
245 } else {
246 styler.ColourTo(endPos, SCE_PROPS_DEFAULT);
247 }
248 }
249
250 static void ColourisePropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
251 char lineBuffer[1024];
252 styler.StartAt(startPos);
253 styler.StartSegment(startPos);
254 unsigned int linePos = 0;
255 unsigned int startLine = startPos;
256 for (unsigned int i = startPos; i < startPos + length; i++) {
257 lineBuffer[linePos++] = styler[i];
258 if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
259 // End of line (or of line buffer) met, colourise it
260 lineBuffer[linePos] = '\0';
261 ColourisePropsLine(lineBuffer, linePos, startLine, i, styler);
262 linePos = 0;
263 startLine = i + 1;
264 }
265 }
266 if (linePos > 0) { // Last line does not have ending characters
267 ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler);
268 }
269 }
270
271 // adaption by ksc, using the "} else {" trick of 1.53
272 // 030721
273 static void FoldPropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
274 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
275
276 unsigned int endPos = startPos + length;
277 int visibleChars = 0;
278 int lineCurrent = styler.GetLine(startPos);
279
280 char chNext = styler[startPos];
281 int styleNext = styler.StyleAt(startPos);
282 bool headerPoint = false;
283
284 for (unsigned int i = startPos; i < endPos; i++) {
285 char ch = chNext;
286 chNext = styler[i+1];
287
288 int style = styleNext;
289 styleNext = styler.StyleAt(i + 1);
290 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
291
292 if (style==2) {
293 headerPoint = true;
294 }
295
296 if (atEOL) {
297 int lev = SC_FOLDLEVELBASE+1;
298 if (headerPoint)
299 lev = SC_FOLDLEVELBASE;
300
301 if (visibleChars == 0 && foldCompact)
302 lev |= SC_FOLDLEVELWHITEFLAG;
303
304 if (headerPoint)
305 lev |= SC_FOLDLEVELHEADERFLAG;
306
307 if (lev != styler.LevelAt(lineCurrent)) {
308 styler.SetLevel(lineCurrent, lev);
309 }
310
311 lineCurrent++;
312 visibleChars = 0;
313 headerPoint=false;
314 }
315 if (!isspacechar(ch))
316 visibleChars++;
317 }
318
319 int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1;
320 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
321 styler.SetLevel(lineCurrent, lev | flagsNext);
322 }
323
324 static void ColouriseMakeLine(
325 char *lineBuffer,
326 unsigned int lengthLine,
327 unsigned int startLine,
328 unsigned int endPos,
329 Accessor &styler) {
330
331 unsigned int i = 0;
332 int lastNonSpace = -1;
333 unsigned int state = SCE_MAKE_DEFAULT;
334 bool bSpecial = false;
335 // Skip initial spaces
336 while ((i < lengthLine) && isspacechar(lineBuffer[i])) {
337 i++;
338 }
339 if (lineBuffer[i] == '#') { // Comment
340 styler.ColourTo(endPos, SCE_MAKE_COMMENT);
341 return;
342 }
343 if (lineBuffer[i] == '!') { // Special directive
344 styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR);
345 return;
346 }
347 while (i < lengthLine) {
348 if (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(') {
349 styler.ColourTo(startLine + i - 1, state);
350 state = SCE_MAKE_IDENTIFIER;
351 } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') {
352 styler.ColourTo(startLine + i, state);
353 state = SCE_MAKE_DEFAULT;
354 }
355 if (!bSpecial) {
356 if (lineBuffer[i] == ':') {
357 // We should check that no colouring was made since the beginning of the line,
358 // to avoid colouring stuff like /OUT:file
359 if (lastNonSpace >= 0)
360 styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET);
361 styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
362 styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
363 bSpecial = true; // Only react to the first ':' of the line
364 state = SCE_MAKE_DEFAULT;
365 } else if (lineBuffer[i] == '=') {
366 if (lastNonSpace >= 0)
367 styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
368 styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
369 styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
370 bSpecial = true; // Only react to the first '=' of the line
371 state = SCE_MAKE_DEFAULT;
372 }
373 }
374 if (!isspacechar(lineBuffer[i])) {
375 lastNonSpace = i;
376 }
377 i++;
378 }
379 if (state == SCE_MAKE_IDENTIFIER) {
380 styler.ColourTo(endPos, SCE_MAKE_IDEOL); // Error, variable reference not ended
381 } else {
382 styler.ColourTo(endPos, SCE_MAKE_DEFAULT);
383 }
384 }
385
386 static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
387 char lineBuffer[1024];
388 styler.StartAt(startPos);
389 styler.StartSegment(startPos);
390 unsigned int linePos = 0;
391 unsigned int startLine = startPos;
392 for (unsigned int i = startPos; i < startPos + length; i++) {
393 lineBuffer[linePos++] = styler[i];
394 if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
395 // End of line (or of line buffer) met, colourise it
396 lineBuffer[linePos] = '\0';
397 ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler);
398 linePos = 0;
399 startLine = i + 1;
400 }
401 }
402 if (linePos > 0) { // Last line does not have ending characters
403 ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler);
404 }
405 }
406
407 static bool strstart(char *haystack, char *needle) {
408 return strncmp(haystack, needle, strlen(needle)) == 0;
409 }
410
411 static void ColouriseErrorListLine(
412 char *lineBuffer,
413 unsigned int lengthLine,
414 // unsigned int startLine,
415 unsigned int endPos,
416 Accessor &styler) {
417 const int unRecognized = 99;
418 if (lineBuffer[0] == '>') {
419 // Command or return status
420 styler.ColourTo(endPos, SCE_ERR_CMD);
421 } else if (lineBuffer[0] == '<') {
422 // Diff removal, but not interested. Trapped to avoid hitting CTAG cases.
423 styler.ColourTo(endPos, SCE_ERR_DEFAULT);
424 } else if (lineBuffer[0] == '!') {
425 styler.ColourTo(endPos, SCE_ERR_DIFF_CHANGED);
426 } else if (lineBuffer[0] == '+') {
427 styler.ColourTo(endPos, SCE_ERR_DIFF_ADDITION);
428 } else if (lineBuffer[0] == '-' && lineBuffer[1] == '-' && lineBuffer[2] == '-') {
429 styler.ColourTo(endPos, SCE_ERR_DIFF_MESSAGE);
430 } else if (strstart(lineBuffer, "cf90-")) {
431 // Absoft Pro Fortran 90/95 v8.2 error and/or warning message
432 styler.ColourTo(endPos, SCE_ERR_ABSF);
433 } else if (strstart(lineBuffer, "fortcom:")) {
434 // Intel Fortran Compiler v8.0 error/warning message
435 styler.ColourTo(endPos, SCE_ERR_IFORT);
436 } else if (lineBuffer[0] == '-') {
437 styler.ColourTo(endPos, SCE_ERR_DIFF_DELETION);
438 } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
439 styler.ColourTo(endPos, SCE_ERR_PYTHON);
440 } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) {
441 styler.ColourTo(endPos, SCE_ERR_PHP);
442 } else if ((strstart(lineBuffer, "Error ") ||
443 strstart(lineBuffer, "Warning ")) &&
444 strstr(lineBuffer, " at (") &&
445 strstr(lineBuffer, ") : ") &&
446 (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) {
447 // Intel Fortran Compiler error/warning message
448 styler.ColourTo(endPos, SCE_ERR_IFC);
449 } else if (strstart(lineBuffer, "Error ")) {
450 // Borland error message
451 styler.ColourTo(endPos, SCE_ERR_BORLAND);
452 } else if (strstart(lineBuffer, "Warning ")) {
453 // Borland warning message
454 styler.ColourTo(endPos, SCE_ERR_BORLAND);
455 } else if (strstr(lineBuffer, "at line " ) &&
456 (strstr(lineBuffer, "at line " ) < (lineBuffer + lengthLine)) &&
457 strstr(lineBuffer, "file ") &&
458 (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) {
459 // Lua error message
460 styler.ColourTo(endPos, SCE_ERR_LUA);
461 } else if (strstr(lineBuffer, " at " ) &&
462 (strstr(lineBuffer, " at " ) < (lineBuffer + lengthLine)) &&
463 strstr(lineBuffer, " line ") &&
464 (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) &&
465 (strstr(lineBuffer, " at " ) < (strstr(lineBuffer, " line ")))) {
466 // perl error message
467 styler.ColourTo(endPos, SCE_ERR_PERL);
468 } else if ((memcmp(lineBuffer, " at ", 6) == 0) &&
469 strstr(lineBuffer, ":line ")) {
470 // A .NET traceback
471 styler.ColourTo(endPos, SCE_ERR_NET);
472 } else if (strstart(lineBuffer, "Line ") &&
473 strstr(lineBuffer, ", file ")) {
474 // Essential Lahey Fortran error message
475 styler.ColourTo(endPos, SCE_ERR_ELF);
476 } else {
477 // Look for GCC <filename>:<line>:message
478 // Look for Microsoft <filename>(line) :message
479 // Look for Microsoft <filename>(line,pos)message
480 // Look for CTags \tmessage
481 int state = 0;
482 for (unsigned int i = 0; i < lengthLine; i++) {
483 char ch = lineBuffer[i];
484 char chNext = ' ';
485 if ((i+1) < lengthLine)
486 chNext = lineBuffer[i+1];
487 if (state == 0) {
488 if (ch == ':') {
489 // May be GCC
490 if ((chNext != '\\') && (chNext != '/')) {
491 // This check is not completely accurate as may be on
492 // GTK+ with a file name that includes ':'.
493 state = 1;
494 }
495 } else if ((ch == '(') && Is1To9(chNext)) {
496 // May be Microsoft
497 // Check againt '0' often removes phone numbers
498 state = 10;
499 } else if (ch == '\t') {
500 // May be CTags
501 state = 20;
502 }
503 } else if (state == 1) {
504 state = Is1To9(ch) ? 2 : unRecognized;
505 } else if (state == 2) {
506 if (ch == ':') {
507 state = 3; // :9.*: is GCC
508 break;
509 } else if (!Is0To9(ch)) {
510 state = unRecognized;
511 }
512 } else if (state == 10) {
513 state = Is0To9(ch) ? 11 : unRecognized;
514 } else if (state == 11) {
515 if (ch == ',') {
516 state = 14;
517 } else if (ch == ')') {
518 state = 12;
519 } else if ((ch != ' ') && !Is0To9(ch)) {
520 state = unRecognized;
521 }
522 } else if (state == 12) {
523 if ((ch == ' ') && (chNext == ':'))
524 state = 13;
525 else
526 state = unRecognized;
527 } else if (state == 14) {
528 if (ch == ')') {
529 state = 15;
530 break;
531 } else if ((ch != ' ') && !Is0To9(ch)) {
532 state = unRecognized;
533 }
534 } else if (state == 20) {
535 if ((lineBuffer[i-1] == '\t') &&
536 ((ch == '/' && lineBuffer[i+1] == '^') || Is0To9(ch))) {
537 state = 24;
538 break;
539 } else if ((ch == '/') && (lineBuffer[i+1] == '^')) {
540 state = 21;
541 }
542 } else if ((state == 21) && ((lineBuffer[i] == '$') && (lineBuffer[i+1] == '/'))) {
543 state = 22;
544 break;
545 }
546 }
547 if (state == 3) {
548 styler.ColourTo(endPos, SCE_ERR_GCC);
549 } else if ((state == 13) || (state == 14) || (state == 15)) {
550 styler.ColourTo(endPos, SCE_ERR_MS);
551 } else if (((state == 22) || (state == 24)) && (lineBuffer[0] != '\t')) {
552 styler.ColourTo(endPos, SCE_ERR_CTAG);
553 } else {
554 styler.ColourTo(endPos, SCE_ERR_DEFAULT);
555 }
556 }
557 }
558
559 static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
560 char lineBuffer[1024];
561 styler.StartAt(startPos);
562 styler.StartSegment(startPos);
563 unsigned int linePos = 0;
564 for (unsigned int i = startPos; i < startPos + length; i++) {
565 lineBuffer[linePos++] = styler[i];
566 if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
567 // End of line (or of line buffer) met, colourise it
568 lineBuffer[linePos] = '\0';
569 ColouriseErrorListLine(lineBuffer, linePos, i, styler);
570 linePos = 0;
571 }
572 }
573 if (linePos > 0) { // Last line does not have ending characters
574 ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler);
575 }
576 }
577
578 static int isSpecial(char s) {
579 return (s == '\\') || (s == ',') || (s == ';') || (s == '\'') || (s == ' ') ||
580 (s == '\"') || (s == '`') || (s == '^') || (s == '~');
581 }
582
583 static int isTag(int start, Accessor &styler) {
584 char s[6];
585 unsigned int i = 0, e = 1;
586 while (i < 5 && e) {
587 s[i] = styler[start + i];
588 i++;
589 e = styler[start + i] != '{';
590 }
591 s[i] = '\0';
592 return (strcmp(s, "begin") == 0) || (strcmp(s, "end") == 0);
593 }
594
595 static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle,
596 WordList *[], Accessor &styler) {
597
598 styler.StartAt(startPos);
599
600 int state = initStyle;
601 char chNext = styler[startPos];
602 styler.StartSegment(startPos);
603 int lengthDoc = startPos + length;
604
605 for (int i = startPos; i < lengthDoc; i++) {
606 char ch = chNext;
607 chNext = styler.SafeGetCharAt(i + 1);
608
609 if (styler.IsLeadByte(ch)) {
610 chNext = styler.SafeGetCharAt(i + 2);
611 i++;
612 continue;
613 }
614 switch (state) {
615 case SCE_L_DEFAULT :
616 switch (ch) {
617 case '\\' :
618 styler.ColourTo(i - 1, state);
619 if (isSpecial(styler[i + 1])) {
620 styler.ColourTo(i + 1, SCE_L_COMMAND);
621 i++;
622 chNext = styler.SafeGetCharAt(i + 1);
623 } else {
624 if (isTag(i + 1, styler))
625 state = SCE_L_TAG;
626 else
627 state = SCE_L_COMMAND;
628 }
629 break;
630 case '$' :
631 styler.ColourTo(i - 1, state);
632 state = SCE_L_MATH;
633 if (chNext == '$') {
634 i++;
635 chNext = styler.SafeGetCharAt(i + 1);
636 }
637 break;
638 case '%' :
639 styler.ColourTo(i - 1, state);
640 state = SCE_L_COMMENT;
641 break;
642 }
643 break;
644 case SCE_L_COMMAND :
645 if (chNext == '[' || chNext == '{' || chNext == '}' ||
646 chNext == ' ' || chNext == '\r' || chNext == '\n') {
647 styler.ColourTo(i, state);
648 state = SCE_L_DEFAULT;
649 i++;
650 chNext = styler.SafeGetCharAt(i + 1);
651 }
652 break;
653 case SCE_L_TAG :
654 if (ch == '}') {
655 styler.ColourTo(i, state);
656 state = SCE_L_DEFAULT;
657 }
658 break;
659 case SCE_L_MATH :
660 if (ch == '$') {
661 if (chNext == '$') {
662 i++;
663 chNext = styler.SafeGetCharAt(i + 1);
664 }
665 styler.ColourTo(i, state);
666 state = SCE_L_DEFAULT;
667 }
668 break;
669 case SCE_L_COMMENT :
670 if (ch == '\r' || ch == '\n') {
671 styler.ColourTo(i - 1, state);
672 state = SCE_L_DEFAULT;
673 }
674 }
675 }
676 styler.ColourTo(lengthDoc-1, state);
677 }
678
679 static const char * const batchWordListDesc[] = {
680 "Keywords",
681 0
682 };
683
684 static const char * const emptyWordListDesc[] = {
685 0
686 };
687
688 static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[],
689 Accessor &styler) {
690 // Null language means all style bytes are 0 so just mark the end - no need to fill in.
691 if (length > 0) {
692 styler.StartAt(startPos + length - 1);
693 styler.StartSegment(startPos + length - 1);
694 styler.ColourTo(startPos + length - 1, 0);
695 }
696 }
697
698 LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc);
699 LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", 0, emptyWordListDesc);
700 LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc);
701 LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc);
702 LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc);
703 LexerModule lmLatex(SCLEX_LATEX, ColouriseLatexDoc, "latex", 0, emptyWordListDesc);
704 LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null");