]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexOthers.cxx
31ac415ad4eb7b7ebf865e55628c46853d252c62
[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 (lineBuffer[0] == '-') {
431 styler.ColourTo(endPos, SCE_ERR_DIFF_DELETION);
432 } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
433 styler.ColourTo(endPos, SCE_ERR_PYTHON);
434 } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) {
435 styler.ColourTo(endPos, SCE_ERR_PHP);
436 } else if ((strstart(lineBuffer, "Error ") ||
437 strstart(lineBuffer, "Warning ")) &&
438 strstr(lineBuffer, " at (") &&
439 strstr(lineBuffer, ") : ") &&
440 (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) {
441 // Intel Fortran Compiler error/warning message
442 styler.ColourTo(endPos, SCE_ERR_IFC);
443 } else if (strstart(lineBuffer, "Error ")) {
444 // Borland error message
445 styler.ColourTo(endPos, SCE_ERR_BORLAND);
446 } else if (strstart(lineBuffer, "Warning ")) {
447 // Borland warning message
448 styler.ColourTo(endPos, SCE_ERR_BORLAND);
449 } else if (strstr(lineBuffer, "at line " ) &&
450 (strstr(lineBuffer, "at line " ) < (lineBuffer + lengthLine)) &&
451 strstr(lineBuffer, "file ") &&
452 (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) {
453 // Lua error message
454 styler.ColourTo(endPos, SCE_ERR_LUA);
455 } else if (strstr(lineBuffer, " at " ) &&
456 (strstr(lineBuffer, " at " ) < (lineBuffer + lengthLine)) &&
457 strstr(lineBuffer, " line ") &&
458 (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) &&
459 (strstr(lineBuffer, " at " ) < (strstr(lineBuffer, " line ")))) {
460 // perl error message
461 styler.ColourTo(endPos, SCE_ERR_PERL);
462 } else if ((memcmp(lineBuffer, " at ", 6) == 0) &&
463 strstr(lineBuffer, ":line ")) {
464 // A .NET traceback
465 styler.ColourTo(endPos, SCE_ERR_NET);
466 } else if (strstart(lineBuffer, "Line ") &&
467 strstr(lineBuffer, ", file ")) {
468 // Essential Lahey Fortran error message
469 styler.ColourTo(endPos, SCE_ERR_ELF);
470 } else {
471 // Look for GCC <filename>:<line>:message
472 // Look for Microsoft <filename>(line) :message
473 // Look for Microsoft <filename>(line,pos)message
474 // Look for CTags \tmessage
475 int state = 0;
476 for (unsigned int i = 0; i < lengthLine; i++) {
477 char ch = lineBuffer[i];
478 char chNext = ' ';
479 if ((i+1) < lengthLine)
480 chNext = lineBuffer[i+1];
481 if (state == 0) {
482 if (ch == ':') {
483 // May be GCC
484 if ((chNext != '\\') && (chNext != '/')) {
485 // This check is not completely accurate as may be on
486 // GTK+ with a file name that includes ':'.
487 state = 1;
488 }
489 } else if ((ch == '(') && Is1To9(chNext)) {
490 // May be Microsoft
491 // Check againt '0' often removes phone numbers
492 state = 10;
493 } else if (ch == '\t') {
494 // May be CTags
495 state = 20;
496 }
497 } else if (state == 1) {
498 state = Is1To9(ch) ? 2 : unRecognized;
499 } else if (state == 2) {
500 if (ch == ':') {
501 state = 3; // :9.*: is GCC
502 break;
503 } else if (!Is0To9(ch)) {
504 state = unRecognized;
505 }
506 } else if (state == 10) {
507 state = Is0To9(ch) ? 11 : unRecognized;
508 } else if (state == 11) {
509 if (ch == ',') {
510 state = 14;
511 } else if (ch == ')') {
512 state = 12;
513 } else if ((ch != ' ') && !Is0To9(ch)) {
514 state = unRecognized;
515 }
516 } else if (state == 12) {
517 if ((ch == ' ') && (chNext == ':'))
518 state = 13;
519 else
520 state = unRecognized;
521 } else if (state == 14) {
522 if (ch == ')') {
523 state = 15;
524 break;
525 } else if ((ch != ' ') && !Is0To9(ch)) {
526 state = unRecognized;
527 }
528 } else if (state == 20) {
529 if ((lineBuffer[i-1] == '\t') &&
530 ((ch == '/' && lineBuffer[i+1] == '^') || Is0To9(ch))) {
531 state = 24;
532 break;
533 } else if ((ch == '/') && (lineBuffer[i+1] == '^')) {
534 state = 21;
535 }
536 } else if ((state == 21) && ((lineBuffer[i] == '$') && (lineBuffer[i+1] == '/'))) {
537 state = 22;
538 break;
539 }
540 }
541 if (state == 3) {
542 styler.ColourTo(endPos, SCE_ERR_GCC);
543 } else if ((state == 13) || (state == 14) || (state == 15)) {
544 styler.ColourTo(endPos, SCE_ERR_MS);
545 } else if (((state == 22) || (state == 24)) && (lineBuffer[0] != '\t')) {
546 styler.ColourTo(endPos, SCE_ERR_CTAG);
547 } else {
548 styler.ColourTo(endPos, SCE_ERR_DEFAULT);
549 }
550 }
551 }
552
553 static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
554 char lineBuffer[1024];
555 styler.StartAt(startPos);
556 styler.StartSegment(startPos);
557 unsigned int linePos = 0;
558 for (unsigned int i = startPos; i < startPos + length; i++) {
559 lineBuffer[linePos++] = styler[i];
560 if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
561 // End of line (or of line buffer) met, colourise it
562 lineBuffer[linePos] = '\0';
563 ColouriseErrorListLine(lineBuffer, linePos, i, styler);
564 linePos = 0;
565 }
566 }
567 if (linePos > 0) { // Last line does not have ending characters
568 ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler);
569 }
570 }
571
572 static int isSpecial(char s) {
573 return (s == '\\') || (s == ',') || (s == ';') || (s == '\'') || (s == ' ') ||
574 (s == '\"') || (s == '`') || (s == '^') || (s == '~');
575 }
576
577 static int isTag(int start, Accessor &styler) {
578 char s[6];
579 unsigned int i = 0, e = 1;
580 while (i < 5 && e) {
581 s[i] = styler[start + i];
582 i++;
583 e = styler[start + i] != '{';
584 }
585 s[i] = '\0';
586 return (strcmp(s, "begin") == 0) || (strcmp(s, "end") == 0);
587 }
588
589 static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle,
590 WordList *[], Accessor &styler) {
591
592 styler.StartAt(startPos);
593
594 int state = initStyle;
595 char chNext = styler[startPos];
596 styler.StartSegment(startPos);
597 int lengthDoc = startPos + length;
598
599 for (int i = startPos; i < lengthDoc; i++) {
600 char ch = chNext;
601 chNext = styler.SafeGetCharAt(i + 1);
602
603 if (styler.IsLeadByte(ch)) {
604 chNext = styler.SafeGetCharAt(i + 2);
605 i++;
606 continue;
607 }
608 switch (state) {
609 case SCE_L_DEFAULT :
610 switch (ch) {
611 case '\\' :
612 styler.ColourTo(i - 1, state);
613 if (isSpecial(styler[i + 1])) {
614 styler.ColourTo(i + 1, SCE_L_COMMAND);
615 i++;
616 chNext = styler.SafeGetCharAt(i + 1);
617 } else {
618 if (isTag(i + 1, styler))
619 state = SCE_L_TAG;
620 else
621 state = SCE_L_COMMAND;
622 }
623 break;
624 case '$' :
625 styler.ColourTo(i - 1, state);
626 state = SCE_L_MATH;
627 if (chNext == '$') {
628 i++;
629 chNext = styler.SafeGetCharAt(i + 1);
630 }
631 break;
632 case '%' :
633 styler.ColourTo(i - 1, state);
634 state = SCE_L_COMMENT;
635 break;
636 }
637 break;
638 case SCE_L_COMMAND :
639 if (chNext == '[' || chNext == '{' || chNext == '}' ||
640 chNext == ' ' || chNext == '\r' || chNext == '\n') {
641 styler.ColourTo(i, state);
642 state = SCE_L_DEFAULT;
643 i++;
644 chNext = styler.SafeGetCharAt(i + 1);
645 }
646 break;
647 case SCE_L_TAG :
648 if (ch == '}') {
649 styler.ColourTo(i, state);
650 state = SCE_L_DEFAULT;
651 }
652 break;
653 case SCE_L_MATH :
654 if (ch == '$') {
655 if (chNext == '$') {
656 i++;
657 chNext = styler.SafeGetCharAt(i + 1);
658 }
659 styler.ColourTo(i, state);
660 state = SCE_L_DEFAULT;
661 }
662 break;
663 case SCE_L_COMMENT :
664 if (ch == '\r' || ch == '\n') {
665 styler.ColourTo(i - 1, state);
666 state = SCE_L_DEFAULT;
667 }
668 }
669 }
670 styler.ColourTo(lengthDoc-1, state);
671 }
672
673 static const char * const batchWordListDesc[] = {
674 "Keywords",
675 0
676 };
677
678 static const char * const emptyWordListDesc[] = {
679 0
680 };
681
682 static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[],
683 Accessor &styler) {
684 // Null language means all style bytes are 0 so just mark the end - no need to fill in.
685 if (length > 0) {
686 styler.StartAt(startPos + length - 1);
687 styler.StartSegment(startPos + length - 1);
688 styler.ColourTo(startPos + length - 1, 0);
689 }
690 }
691
692 LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc);
693 LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", 0, emptyWordListDesc);
694 LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc);
695 LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc);
696 LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc);
697 LexerModule lmLatex(SCLEX_LATEX, ColouriseLatexDoc, "latex", 0, emptyWordListDesc);
698 LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null");