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.
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.
17 #include "CharClassify.h"
21 #include "Scintilla.h"
25 using namespace Scintilla
;
28 static bool strstart(const char *haystack
, const char *needle
) {
29 return strncmp(haystack
, needle
, strlen(needle
)) == 0;
32 static bool Is0To9(char ch
) {
33 return (ch
>= '0') && (ch
<= '9');
36 static bool Is1To9(char ch
) {
37 return (ch
>= '1') && (ch
<= '9');
40 static bool IsAlphabetic(int ch
) {
41 return isascii(ch
) && isalpha(ch
);
44 static inline bool AtEOL(Accessor
&styler
, unsigned int i
) {
45 return (styler
[i
] == '\n') ||
46 ((styler
[i
] == '\r') && (styler
.SafeGetCharAt(i
+ 1) != '\n'));
49 // Tests for BATCH Operators
50 static bool IsBOperator(char ch
) {
51 return (ch
== '=') || (ch
== '+') || (ch
== '>') || (ch
== '<') ||
52 (ch
== '|') || (ch
== '?') || (ch
== '*');
55 // Tests for BATCH Separators
56 static bool IsBSeparator(char ch
) {
57 return (ch
== '\\') || (ch
== '.') || (ch
== ';') ||
58 (ch
== '\"') || (ch
== '\'') || (ch
== '/') || (ch
== ')');
61 static void ColouriseBatchLine(
63 unsigned int lengthLine
,
64 unsigned int startLine
,
66 WordList
*keywordlists
[],
69 unsigned int offset
= 0; // Line Buffer Offset
70 unsigned int cmdLoc
; // External Command / Program Location
71 char wordBuffer
[81]; // Word Buffer - large to catch long paths
72 unsigned int wbl
; // Word Buffer Length
73 unsigned int wbo
; // Word Buffer Offset - also Special Keyword Buffer Length
74 WordList
&keywords
= *keywordlists
[0]; // Internal Commands
75 WordList
&keywords2
= *keywordlists
[1]; // External Commands (optional)
77 // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords
78 // Toggling Regular Keyword Checking off improves readability
79 // Other Regular Keywords and External Commands / Programs might also benefit from toggling
80 // Need a more robust algorithm to properly toggle Regular Keyword Checking
81 bool continueProcessing
= true; // Used to toggle Regular Keyword Checking
82 // Special Keywords are those that allow certain characters without whitespace after the command
83 // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path=
84 // Special Keyword Buffer used to determine if the first n characters is a Keyword
85 char sKeywordBuffer
[10]; // Special Keyword Buffer
86 bool sKeywordFound
; // Exit Special Keyword for-loop if found
88 // Skip initial spaces
89 while ((offset
< lengthLine
) && (isspacechar(lineBuffer
[offset
]))) {
92 // Colorize Default Text
93 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
94 // Set External Command / Program Location
97 // Check for Fake Label (Comment) or Real Label - return if found
98 if (lineBuffer
[offset
] == ':') {
99 if (lineBuffer
[offset
+ 1] == ':') {
100 // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
101 styler
.ColourTo(endPos
, SCE_BAT_COMMENT
);
103 // Colorize Real Label
104 styler
.ColourTo(endPos
, SCE_BAT_LABEL
);
107 // Check for Drive Change (Drive Change is internal command) - return if found
108 } else if ((IsAlphabetic(lineBuffer
[offset
])) &&
109 (lineBuffer
[offset
+ 1] == ':') &&
110 ((isspacechar(lineBuffer
[offset
+ 2])) ||
111 (((lineBuffer
[offset
+ 2] == '\\')) &&
112 (isspacechar(lineBuffer
[offset
+ 3]))))) {
113 // Colorize Regular Keyword
114 styler
.ColourTo(endPos
, SCE_BAT_WORD
);
118 // Check for Hide Command (@ECHO OFF/ON)
119 if (lineBuffer
[offset
] == '@') {
120 styler
.ColourTo(startLine
+ offset
, SCE_BAT_HIDE
);
124 while ((offset
< lengthLine
) && (isspacechar(lineBuffer
[offset
]))) {
128 // Read remainder of line word-at-a-time or remainder-of-word-at-a-time
129 while (offset
< lengthLine
) {
130 if (offset
> startLine
) {
131 // Colorize Default Text
132 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
134 // Copy word from Line Buffer into Word Buffer
136 for (; offset
< lengthLine
&& wbl
< 80 &&
137 !isspacechar(lineBuffer
[offset
]); wbl
++, offset
++) {
138 wordBuffer
[wbl
] = static_cast<char>(tolower(lineBuffer
[offset
]));
140 wordBuffer
[wbl
] = '\0';
143 // Check for Comment - return if found
144 if (CompareCaseInsensitive(wordBuffer
, "rem") == 0) {
145 styler
.ColourTo(endPos
, SCE_BAT_COMMENT
);
148 // Check for Separator
149 if (IsBSeparator(wordBuffer
[0])) {
150 // Check for External Command / Program
151 if ((cmdLoc
== offset
- wbl
) &&
152 ((wordBuffer
[0] == ':') ||
153 (wordBuffer
[0] == '\\') ||
154 (wordBuffer
[0] == '.'))) {
155 // Reset Offset to re-process remainder of word
157 // Colorize External Command / Program
159 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
160 } else if (keywords2
.InList(wordBuffer
)) {
161 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
163 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
165 // Reset External Command / Program Location
168 // Reset Offset to re-process remainder of word
170 // Colorize Default Text
171 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
173 // Check for Regular Keyword in list
174 } else if ((keywords
.InList(wordBuffer
)) &&
175 (continueProcessing
)) {
176 // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking
177 if ((CompareCaseInsensitive(wordBuffer
, "echo") == 0) ||
178 (CompareCaseInsensitive(wordBuffer
, "goto") == 0) ||
179 (CompareCaseInsensitive(wordBuffer
, "prompt") == 0) ||
180 (CompareCaseInsensitive(wordBuffer
, "set") == 0)) {
181 continueProcessing
= false;
183 // Identify External Command / Program Location for ERRORLEVEL, and EXIST
184 if ((CompareCaseInsensitive(wordBuffer
, "errorlevel") == 0) ||
185 (CompareCaseInsensitive(wordBuffer
, "exist") == 0)) {
186 // Reset External Command / Program Location
189 while ((cmdLoc
< lengthLine
) &&
190 (isspacechar(lineBuffer
[cmdLoc
]))) {
194 while ((cmdLoc
< lengthLine
) &&
195 (!isspacechar(lineBuffer
[cmdLoc
]))) {
199 while ((cmdLoc
< lengthLine
) &&
200 (isspacechar(lineBuffer
[cmdLoc
]))) {
203 // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH
204 } else if ((CompareCaseInsensitive(wordBuffer
, "call") == 0) ||
205 (CompareCaseInsensitive(wordBuffer
, "do") == 0) ||
206 (CompareCaseInsensitive(wordBuffer
, "loadhigh") == 0) ||
207 (CompareCaseInsensitive(wordBuffer
, "lh") == 0)) {
208 // Reset External Command / Program Location
211 while ((cmdLoc
< lengthLine
) &&
212 (isspacechar(lineBuffer
[cmdLoc
]))) {
216 // Colorize Regular keyword
217 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_WORD
);
218 // No need to Reset Offset
219 // Check for Special Keyword in list, External Command / Program, or Default Text
220 } else if ((wordBuffer
[0] != '%') &&
221 (wordBuffer
[0] != '!') &&
222 (!IsBOperator(wordBuffer
[0])) &&
223 (continueProcessing
)) {
224 // Check for Special Keyword
225 // Affected Commands are in Length range 2-6
226 // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected
227 sKeywordFound
= false;
228 for (unsigned int keywordLength
= 2; keywordLength
< wbl
&& keywordLength
< 7 && !sKeywordFound
; keywordLength
++) {
230 // Copy Keyword Length from Word Buffer into Special Keyword Buffer
231 for (; wbo
< keywordLength
; wbo
++) {
232 sKeywordBuffer
[wbo
] = static_cast<char>(wordBuffer
[wbo
]);
234 sKeywordBuffer
[wbo
] = '\0';
235 // Check for Special Keyword in list
236 if ((keywords
.InList(sKeywordBuffer
)) &&
237 ((IsBOperator(wordBuffer
[wbo
])) ||
238 (IsBSeparator(wordBuffer
[wbo
])))) {
239 sKeywordFound
= true;
240 // ECHO requires no further Regular Keyword Checking
241 if (CompareCaseInsensitive(sKeywordBuffer
, "echo") == 0) {
242 continueProcessing
= false;
244 // Colorize Special Keyword as Regular Keyword
245 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_WORD
);
246 // Reset Offset to re-process remainder of word
247 offset
-= (wbl
- wbo
);
250 // Check for External Command / Program or Default Text
251 if (!sKeywordFound
) {
253 // Check for External Command / Program
254 if (cmdLoc
== offset
- wbl
) {
255 // Read up to %, Operator or Separator
256 while ((wbo
< wbl
) &&
257 (wordBuffer
[wbo
] != '%') &&
258 (wordBuffer
[wbo
] != '!') &&
259 (!IsBOperator(wordBuffer
[wbo
])) &&
260 (!IsBSeparator(wordBuffer
[wbo
]))) {
263 // Reset External Command / Program Location
264 cmdLoc
= offset
- (wbl
- wbo
);
265 // Reset Offset to re-process remainder of word
266 offset
-= (wbl
- wbo
);
267 // CHOICE requires no further Regular Keyword Checking
268 if (CompareCaseInsensitive(wordBuffer
, "choice") == 0) {
269 continueProcessing
= false;
271 // Check for START (and its switches) - What follows is External Command \ Program
272 if (CompareCaseInsensitive(wordBuffer
, "start") == 0) {
273 // Reset External Command / Program Location
276 while ((cmdLoc
< lengthLine
) &&
277 (isspacechar(lineBuffer
[cmdLoc
]))) {
280 // Reset External Command / Program Location if command switch detected
281 if (lineBuffer
[cmdLoc
] == '/') {
282 // Skip command switch
283 while ((cmdLoc
< lengthLine
) &&
284 (!isspacechar(lineBuffer
[cmdLoc
]))) {
288 while ((cmdLoc
< lengthLine
) &&
289 (isspacechar(lineBuffer
[cmdLoc
]))) {
294 // Colorize External Command / Program
296 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
297 } else if (keywords2
.InList(wordBuffer
)) {
298 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
300 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
302 // No need to Reset Offset
303 // Check for Default Text
305 // Read up to %, Operator or Separator
306 while ((wbo
< wbl
) &&
307 (wordBuffer
[wbo
] != '%') &&
308 (wordBuffer
[wbo
] != '!') &&
309 (!IsBOperator(wordBuffer
[wbo
])) &&
310 (!IsBSeparator(wordBuffer
[wbo
]))) {
313 // Colorize Default Text
314 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_DEFAULT
);
315 // Reset Offset to re-process remainder of word
316 offset
-= (wbl
- wbo
);
319 // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a)
320 } else if (wordBuffer
[0] == '%') {
321 // Colorize Default Text
322 styler
.ColourTo(startLine
+ offset
- 1 - wbl
, SCE_BAT_DEFAULT
);
324 // Search to end of word for second % (can be a long path)
325 while ((wbo
< wbl
) &&
326 (wordBuffer
[wbo
] != '%') &&
327 (!IsBOperator(wordBuffer
[wbo
])) &&
328 (!IsBSeparator(wordBuffer
[wbo
]))) {
331 // Check for Argument (%n) or (%*)
332 if (((Is0To9(wordBuffer
[1])) || (wordBuffer
[1] == '*')) &&
333 (wordBuffer
[wbo
] != '%')) {
334 // Check for External Command / Program
335 if (cmdLoc
== offset
- wbl
) {
336 cmdLoc
= offset
- (wbl
- 2);
339 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 2), SCE_BAT_IDENTIFIER
);
340 // Reset Offset to re-process remainder of word
342 // Check for Expanded Argument (%~...) / Variable (%%~...)
343 } else if (((wbl
> 1) && (wordBuffer
[1] == '~')) ||
344 ((wbl
> 2) && (wordBuffer
[1] == '%') && (wordBuffer
[2] == '~'))) {
345 // Check for External Command / Program
346 if (cmdLoc
== offset
- wbl
) {
347 cmdLoc
= offset
- (wbl
- wbo
);
349 // Colorize Expanded Argument / Variable
350 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_IDENTIFIER
);
351 // Reset Offset to re-process remainder of word
352 offset
-= (wbl
- wbo
);
353 // Check for Environment Variable (%x...%)
354 } else if ((wordBuffer
[1] != '%') &&
355 (wordBuffer
[wbo
] == '%')) {
357 // Check for External Command / Program
358 if (cmdLoc
== offset
- wbl
) {
359 cmdLoc
= offset
- (wbl
- wbo
);
361 // Colorize Environment Variable
362 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_IDENTIFIER
);
363 // Reset Offset to re-process remainder of word
364 offset
-= (wbl
- wbo
);
365 // Check for Local Variable (%%a)
368 (wordBuffer
[1] == '%') &&
369 (wordBuffer
[2] != '%') &&
370 (!IsBOperator(wordBuffer
[2])) &&
371 (!IsBSeparator(wordBuffer
[2]))) {
372 // Check for External Command / Program
373 if (cmdLoc
== offset
- wbl
) {
374 cmdLoc
= offset
- (wbl
- 3);
376 // Colorize Local Variable
377 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 3), SCE_BAT_IDENTIFIER
);
378 // Reset Offset to re-process remainder of word
381 // Check for Environment Variable (!x...!)
382 } else if (wordBuffer
[0] == '!') {
383 // Colorize Default Text
384 styler
.ColourTo(startLine
+ offset
- 1 - wbl
, SCE_BAT_DEFAULT
);
386 // Search to end of word for second ! (can be a long path)
387 while ((wbo
< wbl
) &&
388 (wordBuffer
[wbo
] != '!') &&
389 (!IsBOperator(wordBuffer
[wbo
])) &&
390 (!IsBSeparator(wordBuffer
[wbo
]))) {
393 if (wordBuffer
[wbo
] == '!') {
395 // Check for External Command / Program
396 if (cmdLoc
== offset
- wbl
) {
397 cmdLoc
= offset
- (wbl
- wbo
);
399 // Colorize Environment Variable
400 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_IDENTIFIER
);
401 // Reset Offset to re-process remainder of word
402 offset
-= (wbl
- wbo
);
404 // Check for Operator
405 } else if (IsBOperator(wordBuffer
[0])) {
406 // Colorize Default Text
407 styler
.ColourTo(startLine
+ offset
- 1 - wbl
, SCE_BAT_DEFAULT
);
408 // Check for Comparison Operator
409 if ((wordBuffer
[0] == '=') && (wordBuffer
[1] == '=')) {
410 // Identify External Command / Program Location for IF
413 while ((cmdLoc
< lengthLine
) &&
414 (isspacechar(lineBuffer
[cmdLoc
]))) {
417 // Colorize Comparison Operator
418 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 2), SCE_BAT_OPERATOR
);
419 // Reset Offset to re-process remainder of word
421 // Check for Pipe Operator
422 } else if (wordBuffer
[0] == '|') {
423 // Reset External Command / Program Location
424 cmdLoc
= offset
- wbl
+ 1;
426 while ((cmdLoc
< lengthLine
) &&
427 (isspacechar(lineBuffer
[cmdLoc
]))) {
430 // Colorize Pipe Operator
431 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 1), SCE_BAT_OPERATOR
);
432 // Reset Offset to re-process remainder of word
434 // Check for Other Operator
436 // Check for > Operator
437 if (wordBuffer
[0] == '>') {
438 // Turn Keyword and External Command / Program checking back on
439 continueProcessing
= true;
441 // Colorize Other Operator
442 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 1), SCE_BAT_OPERATOR
);
443 // Reset Offset to re-process remainder of word
446 // Check for Default Text
448 // Read up to %, Operator or Separator
449 while ((wbo
< wbl
) &&
450 (wordBuffer
[wbo
] != '%') &&
451 (wordBuffer
[wbo
] != '!') &&
452 (!IsBOperator(wordBuffer
[wbo
])) &&
453 (!IsBSeparator(wordBuffer
[wbo
]))) {
456 // Colorize Default Text
457 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_DEFAULT
);
458 // Reset Offset to re-process remainder of word
459 offset
-= (wbl
- wbo
);
461 // Skip next spaces - nothing happens if Offset was Reset
462 while ((offset
< lengthLine
) && (isspacechar(lineBuffer
[offset
]))) {
466 // Colorize Default Text for remainder of line - currently not lexed
467 styler
.ColourTo(endPos
, SCE_BAT_DEFAULT
);
470 static void ColouriseBatchDoc(
471 unsigned int startPos
,
474 WordList
*keywordlists
[],
477 char lineBuffer
[1024];
479 styler
.StartAt(startPos
);
480 styler
.StartSegment(startPos
);
481 unsigned int linePos
= 0;
482 unsigned int startLine
= startPos
;
483 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
484 lineBuffer
[linePos
++] = styler
[i
];
485 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
486 // End of line (or of line buffer) met, colourise it
487 lineBuffer
[linePos
] = '\0';
488 ColouriseBatchLine(lineBuffer
, linePos
, startLine
, i
, keywordlists
, styler
);
493 if (linePos
> 0) { // Last line does not have ending characters
494 lineBuffer
[linePos
] = '\0';
495 ColouriseBatchLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1,
496 keywordlists
, styler
);
500 static void ColouriseDiffLine(char *lineBuffer
, int endLine
, Accessor
&styler
) {
501 // It is needed to remember the current state to recognize starting
502 // comment lines before the first "diff " or "--- ". If a real
503 // difference starts then each line starting with ' ' is a whitespace
504 // otherwise it is considered a comment (Only in..., Binary file...)
505 if (0 == strncmp(lineBuffer
, "diff ", 5)) {
506 styler
.ColourTo(endLine
, SCE_DIFF_COMMAND
);
507 } else if (0 == strncmp(lineBuffer
, "Index: ", 7)) { // For subversion's diff
508 styler
.ColourTo(endLine
, SCE_DIFF_COMMAND
);
509 } else if (0 == strncmp(lineBuffer
, "---", 3)) {
510 // In a context diff, --- appears in both the header and the position markers
511 if (lineBuffer
[3] == ' ' && atoi(lineBuffer
+ 4) && !strchr(lineBuffer
, '/'))
512 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
513 else if (lineBuffer
[3] == '\r' || lineBuffer
[3] == '\n')
514 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
516 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
517 } else if (0 == strncmp(lineBuffer
, "+++ ", 4)) {
518 // I don't know of any diff where "+++ " is a position marker, but for
519 // consistency, do the same as with "--- " and "*** ".
520 if (atoi(lineBuffer
+4) && !strchr(lineBuffer
, '/'))
521 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
523 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
524 } else if (0 == strncmp(lineBuffer
, "====", 4)) { // For p4's diff
525 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
526 } else if (0 == strncmp(lineBuffer
, "***", 3)) {
527 // In a context diff, *** appears in both the header and the position markers.
528 // Also ******** is a chunk header, but here it's treated as part of the
529 // position marker since there is no separate style for a chunk header.
530 if (lineBuffer
[3] == ' ' && atoi(lineBuffer
+4) && !strchr(lineBuffer
, '/'))
531 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
532 else if (lineBuffer
[3] == '*')
533 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
535 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
536 } else if (0 == strncmp(lineBuffer
, "? ", 2)) { // For difflib
537 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
538 } else if (lineBuffer
[0] == '@') {
539 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
540 } else if (lineBuffer
[0] >= '0' && lineBuffer
[0] <= '9') {
541 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
542 } else if (lineBuffer
[0] == '-' || lineBuffer
[0] == '<') {
543 styler
.ColourTo(endLine
, SCE_DIFF_DELETED
);
544 } else if (lineBuffer
[0] == '+' || lineBuffer
[0] == '>') {
545 styler
.ColourTo(endLine
, SCE_DIFF_ADDED
);
546 } else if (lineBuffer
[0] == '!') {
547 styler
.ColourTo(endLine
, SCE_DIFF_CHANGED
);
548 } else if (lineBuffer
[0] != ' ') {
549 styler
.ColourTo(endLine
, SCE_DIFF_COMMENT
);
551 styler
.ColourTo(endLine
, SCE_DIFF_DEFAULT
);
555 static void ColouriseDiffDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
556 char lineBuffer
[1024];
557 styler
.StartAt(startPos
);
558 styler
.StartSegment(startPos
);
559 unsigned int linePos
= 0;
560 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
561 lineBuffer
[linePos
++] = styler
[i
];
562 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
563 // End of line (or of line buffer) met, colourise it
564 lineBuffer
[linePos
] = '\0';
565 ColouriseDiffLine(lineBuffer
, i
, styler
);
569 if (linePos
> 0) { // Last line does not have ending characters
570 ColouriseDiffLine(lineBuffer
, startPos
+ length
- 1, styler
);
574 static void FoldDiffDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
575 int curLine
= styler
.GetLine(startPos
);
576 int curLineStart
= styler
.LineStart(curLine
);
577 int prevLevel
= curLine
> 0 ? styler
.LevelAt(curLine
- 1) : SC_FOLDLEVELBASE
;
581 int lineType
= styler
.StyleAt(curLineStart
);
582 if (lineType
== SCE_DIFF_COMMAND
)
583 nextLevel
= SC_FOLDLEVELBASE
| SC_FOLDLEVELHEADERFLAG
;
584 else if (lineType
== SCE_DIFF_HEADER
)
585 nextLevel
= (SC_FOLDLEVELBASE
+ 1) | SC_FOLDLEVELHEADERFLAG
;
586 else if (lineType
== SCE_DIFF_POSITION
&& styler
[curLineStart
] != '-')
587 nextLevel
= (SC_FOLDLEVELBASE
+ 2) | SC_FOLDLEVELHEADERFLAG
;
588 else if (prevLevel
& SC_FOLDLEVELHEADERFLAG
)
589 nextLevel
= (prevLevel
& SC_FOLDLEVELNUMBERMASK
) + 1;
591 nextLevel
= prevLevel
;
593 if ((nextLevel
& SC_FOLDLEVELHEADERFLAG
) && (nextLevel
== prevLevel
))
594 styler
.SetLevel(curLine
-1, prevLevel
& ~SC_FOLDLEVELHEADERFLAG
);
596 styler
.SetLevel(curLine
, nextLevel
);
597 prevLevel
= nextLevel
;
599 curLineStart
= styler
.LineStart(++curLine
);
600 } while (static_cast<int>(startPos
) + length
> curLineStart
);
603 static void ColourisePoLine(
605 unsigned int lengthLine
,
606 unsigned int startLine
,
611 static unsigned int state
= SCE_PO_DEFAULT
;
612 unsigned int state_start
= SCE_PO_DEFAULT
;
614 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) // Skip initial spaces
616 if (i
< lengthLine
) {
617 if (lineBuffer
[i
] == '#') {
618 // check if the comment contains any flags ("#, ") and
619 // then whether the flags contain "fuzzy"
620 if (strstart(lineBuffer
, "#, ") && strstr(lineBuffer
, "fuzzy"))
621 styler
.ColourTo(endPos
, SCE_PO_FUZZY
);
623 styler
.ColourTo(endPos
, SCE_PO_COMMENT
);
625 if (lineBuffer
[0] == '"') {
626 // line continuation, use previous style
627 styler
.ColourTo(endPos
, state
);
629 // this implicitly also matches "msgid_plural"
630 } else if (strstart(lineBuffer
, "msgid")) {
631 state_start
= SCE_PO_MSGID
;
632 state
= SCE_PO_MSGID_TEXT
;
633 } else if (strstart(lineBuffer
, "msgstr")) {
634 state_start
= SCE_PO_MSGSTR
;
635 state
= SCE_PO_MSGSTR_TEXT
;
636 } else if (strstart(lineBuffer
, "msgctxt")) {
637 state_start
= SCE_PO_MSGCTXT
;
638 state
= SCE_PO_MSGCTXT_TEXT
;
640 if (state_start
!= SCE_PO_DEFAULT
) {
641 // find the next space
642 while ((i
< lengthLine
) && ! isspacechar(lineBuffer
[i
]))
644 styler
.ColourTo(startLine
+ i
- 1, state_start
);
645 styler
.ColourTo(startLine
+ i
, SCE_PO_DEFAULT
);
646 styler
.ColourTo(endPos
, state
);
650 styler
.ColourTo(endPos
, SCE_PO_DEFAULT
);
654 static void ColourisePoDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
655 char lineBuffer
[1024];
656 styler
.StartAt(startPos
);
657 styler
.StartSegment(startPos
);
658 unsigned int linePos
= 0;
659 unsigned int startLine
= startPos
;
660 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
661 lineBuffer
[linePos
++] = styler
[i
];
662 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
663 // End of line (or of line buffer) met, colourise it
664 lineBuffer
[linePos
] = '\0';
665 ColourisePoLine(lineBuffer
, linePos
, startLine
, i
, styler
);
670 if (linePos
> 0) { // Last line does not have ending characters
671 ColourisePoLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
);
675 static inline bool isassignchar(unsigned char ch
) {
676 return (ch
== '=') || (ch
== ':');
679 static void ColourisePropsLine(
681 unsigned int lengthLine
,
682 unsigned int startLine
,
685 bool allowInitialSpaces
) {
688 if (allowInitialSpaces
) {
689 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) // Skip initial spaces
692 if (isspacechar(lineBuffer
[i
])) // don't allow initial spaces
696 if (i
< lengthLine
) {
697 if (lineBuffer
[i
] == '#' || lineBuffer
[i
] == '!' || lineBuffer
[i
] == ';') {
698 styler
.ColourTo(endPos
, SCE_PROPS_COMMENT
);
699 } else if (lineBuffer
[i
] == '[') {
700 styler
.ColourTo(endPos
, SCE_PROPS_SECTION
);
701 } else if (lineBuffer
[i
] == '@') {
702 styler
.ColourTo(startLine
+ i
, SCE_PROPS_DEFVAL
);
703 if (isassignchar(lineBuffer
[i
++]))
704 styler
.ColourTo(startLine
+ i
, SCE_PROPS_ASSIGNMENT
);
705 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
707 // Search for the '=' character
708 while ((i
< lengthLine
) && !isassignchar(lineBuffer
[i
]))
710 if ((i
< lengthLine
) && isassignchar(lineBuffer
[i
])) {
711 styler
.ColourTo(startLine
+ i
- 1, SCE_PROPS_KEY
);
712 styler
.ColourTo(startLine
+ i
, SCE_PROPS_ASSIGNMENT
);
713 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
715 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
719 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
723 static void ColourisePropsDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
724 char lineBuffer
[1024];
725 styler
.StartAt(startPos
);
726 styler
.StartSegment(startPos
);
727 unsigned int linePos
= 0;
728 unsigned int startLine
= startPos
;
730 // property lexer.props.allow.initial.spaces
731 // For properties files, set to 0 to style all lines that start with whitespace in the default style.
732 // This is not suitable for SciTE .properties files which use indentation for flow control but
733 // can be used for RFC2822 text where indentation is used for continuation lines.
734 bool allowInitialSpaces
= styler
.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0;
736 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
737 lineBuffer
[linePos
++] = styler
[i
];
738 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
739 // End of line (or of line buffer) met, colourise it
740 lineBuffer
[linePos
] = '\0';
741 ColourisePropsLine(lineBuffer
, linePos
, startLine
, i
, styler
, allowInitialSpaces
);
746 if (linePos
> 0) { // Last line does not have ending characters
747 ColourisePropsLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
, allowInitialSpaces
);
751 // adaption by ksc, using the "} else {" trick of 1.53
753 static void FoldPropsDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
754 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
756 unsigned int endPos
= startPos
+ length
;
757 int visibleChars
= 0;
758 int lineCurrent
= styler
.GetLine(startPos
);
760 char chNext
= styler
[startPos
];
761 int styleNext
= styler
.StyleAt(startPos
);
762 bool headerPoint
= false;
765 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
767 chNext
= styler
[i
+1];
769 int style
= styleNext
;
770 styleNext
= styler
.StyleAt(i
+ 1);
771 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
773 if (style
== SCE_PROPS_SECTION
) {
778 lev
= SC_FOLDLEVELBASE
;
780 if (lineCurrent
> 0) {
781 int levelPrevious
= styler
.LevelAt(lineCurrent
- 1);
783 if (levelPrevious
& SC_FOLDLEVELHEADERFLAG
) {
784 lev
= SC_FOLDLEVELBASE
+ 1;
786 lev
= levelPrevious
& SC_FOLDLEVELNUMBERMASK
;
791 lev
= SC_FOLDLEVELBASE
;
793 if (visibleChars
== 0 && foldCompact
)
794 lev
|= SC_FOLDLEVELWHITEFLAG
;
797 lev
|= SC_FOLDLEVELHEADERFLAG
;
799 if (lev
!= styler
.LevelAt(lineCurrent
)) {
800 styler
.SetLevel(lineCurrent
, lev
);
807 if (!isspacechar(ch
))
811 if (lineCurrent
> 0) {
812 int levelPrevious
= styler
.LevelAt(lineCurrent
- 1);
813 if (levelPrevious
& SC_FOLDLEVELHEADERFLAG
) {
814 lev
= SC_FOLDLEVELBASE
+ 1;
816 lev
= levelPrevious
& SC_FOLDLEVELNUMBERMASK
;
819 lev
= SC_FOLDLEVELBASE
;
821 int flagsNext
= styler
.LevelAt(lineCurrent
);
822 styler
.SetLevel(lineCurrent
, lev
| (flagsNext
& ~SC_FOLDLEVELNUMBERMASK
));
825 static void ColouriseMakeLine(
827 unsigned int lengthLine
,
828 unsigned int startLine
,
833 int lastNonSpace
= -1;
834 unsigned int state
= SCE_MAKE_DEFAULT
;
835 bool bSpecial
= false;
837 // check for a tab character in column 0 indicating a command
838 bool bCommand
= false;
839 if ((lengthLine
> 0) && (lineBuffer
[0] == '\t'))
842 // Skip initial spaces
843 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) {
846 if (lineBuffer
[i
] == '#') { // Comment
847 styler
.ColourTo(endPos
, SCE_MAKE_COMMENT
);
850 if (lineBuffer
[i
] == '!') { // Special directive
851 styler
.ColourTo(endPos
, SCE_MAKE_PREPROCESSOR
);
854 while (i
< lengthLine
) {
855 if (lineBuffer
[i
] == '$' && lineBuffer
[i
+ 1] == '(') {
856 styler
.ColourTo(startLine
+ i
- 1, state
);
857 state
= SCE_MAKE_IDENTIFIER
;
858 } else if (state
== SCE_MAKE_IDENTIFIER
&& lineBuffer
[i
] == ')') {
859 styler
.ColourTo(startLine
+ i
, state
);
860 state
= SCE_MAKE_DEFAULT
;
863 // skip identifier and target styling if this is a command line
864 if (!bSpecial
&& !bCommand
) {
865 if (lineBuffer
[i
] == ':') {
866 if (((i
+ 1) < lengthLine
) && (lineBuffer
[i
+ 1] == '=')) {
867 // it's a ':=', so style as an identifier
868 if (lastNonSpace
>= 0)
869 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
870 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
871 styler
.ColourTo(startLine
+ i
+ 1, SCE_MAKE_OPERATOR
);
873 // We should check that no colouring was made since the beginning of the line,
874 // to avoid colouring stuff like /OUT:file
875 if (lastNonSpace
>= 0)
876 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_TARGET
);
877 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
878 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
880 bSpecial
= true; // Only react to the first ':' of the line
881 state
= SCE_MAKE_DEFAULT
;
882 } else if (lineBuffer
[i
] == '=') {
883 if (lastNonSpace
>= 0)
884 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
885 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
886 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
887 bSpecial
= true; // Only react to the first '=' of the line
888 state
= SCE_MAKE_DEFAULT
;
891 if (!isspacechar(lineBuffer
[i
])) {
896 if (state
== SCE_MAKE_IDENTIFIER
) {
897 styler
.ColourTo(endPos
, SCE_MAKE_IDEOL
); // Error, variable reference not ended
899 styler
.ColourTo(endPos
, SCE_MAKE_DEFAULT
);
903 static void ColouriseMakeDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
904 char lineBuffer
[1024];
905 styler
.StartAt(startPos
);
906 styler
.StartSegment(startPos
);
907 unsigned int linePos
= 0;
908 unsigned int startLine
= startPos
;
909 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
910 lineBuffer
[linePos
++] = styler
[i
];
911 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
912 // End of line (or of line buffer) met, colourise it
913 lineBuffer
[linePos
] = '\0';
914 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, i
, styler
);
919 if (linePos
> 0) { // Last line does not have ending characters
920 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
);
924 static int RecogniseErrorListLine(const char *lineBuffer
, unsigned int lengthLine
, int &startValue
) {
925 if (lineBuffer
[0] == '>') {
926 // Command or return status
928 } else if (lineBuffer
[0] == '<') {
929 // Diff removal, but not interested. Trapped to avoid hitting CTAG cases.
930 return SCE_ERR_DEFAULT
;
931 } else if (lineBuffer
[0] == '!') {
932 return SCE_ERR_DIFF_CHANGED
;
933 } else if (lineBuffer
[0] == '+') {
934 if (strstart(lineBuffer
, "+++ ")) {
935 return SCE_ERR_DIFF_MESSAGE
;
937 return SCE_ERR_DIFF_ADDITION
;
939 } else if (lineBuffer
[0] == '-') {
940 if (strstart(lineBuffer
, "--- ")) {
941 return SCE_ERR_DIFF_MESSAGE
;
943 return SCE_ERR_DIFF_DELETION
;
945 } else if (strstart(lineBuffer
, "cf90-")) {
946 // Absoft Pro Fortran 90/95 v8.2 error and/or warning message
948 } else if (strstart(lineBuffer
, "fortcom:")) {
949 // Intel Fortran Compiler v8.0 error/warning message
950 return SCE_ERR_IFORT
;
951 } else if (strstr(lineBuffer
, "File \"") && strstr(lineBuffer
, ", line ")) {
952 return SCE_ERR_PYTHON
;
953 } else if (strstr(lineBuffer
, " in ") && strstr(lineBuffer
, " on line ")) {
955 } else if ((strstart(lineBuffer
, "Error ") ||
956 strstart(lineBuffer
, "Warning ")) &&
957 strstr(lineBuffer
, " at (") &&
958 strstr(lineBuffer
, ") : ") &&
959 (strstr(lineBuffer
, " at (") < strstr(lineBuffer
, ") : "))) {
960 // Intel Fortran Compiler error/warning message
962 } else if (strstart(lineBuffer
, "Error ")) {
963 // Borland error message
964 return SCE_ERR_BORLAND
;
965 } else if (strstart(lineBuffer
, "Warning ")) {
966 // Borland warning message
967 return SCE_ERR_BORLAND
;
968 } else if (strstr(lineBuffer
, "at line ") &&
969 (strstr(lineBuffer
, "at line ") < (lineBuffer
+ lengthLine
)) &&
970 strstr(lineBuffer
, "file ") &&
971 (strstr(lineBuffer
, "file ") < (lineBuffer
+ lengthLine
))) {
972 // Lua 4 error message
974 } else if (strstr(lineBuffer
, " at ") &&
975 (strstr(lineBuffer
, " at ") < (lineBuffer
+ lengthLine
)) &&
976 strstr(lineBuffer
, " line ") &&
977 (strstr(lineBuffer
, " line ") < (lineBuffer
+ lengthLine
)) &&
978 (strstr(lineBuffer
, " at ") < (strstr(lineBuffer
, " line ")))) {
979 // perl error message
981 } else if ((memcmp(lineBuffer
, " at ", 6) == 0) &&
982 strstr(lineBuffer
, ":line ")) {
985 } else if (strstart(lineBuffer
, "Line ") &&
986 strstr(lineBuffer
, ", file ")) {
987 // Essential Lahey Fortran error message
989 } else if (strstart(lineBuffer
, "line ") &&
990 strstr(lineBuffer
, " column ")) {
991 // HTML tidy style: line 42 column 1
993 } else if (strstart(lineBuffer
, "\tat ") &&
994 strstr(lineBuffer
, "(") &&
995 strstr(lineBuffer
, ".java:")) {
996 // Java stack back trace
997 return SCE_ERR_JAVA_STACK
;
999 // Look for one of the following formats:
1000 // GCC: <filename>:<line>:<message>
1001 // Microsoft: <filename>(<line>) :<message>
1002 // Common: <filename>(<line>): warning|error|note|remark|catastrophic|fatal
1003 // Common: <filename>(<line>) warning|error|note|remark|catastrophic|fatal
1004 // Microsoft: <filename>(<line>,<column>)<message>
1005 // CTags: \t<message>
1006 // Lua 5 traceback: \t<filename>:<line>:<message>
1007 // Lua 5.1: <exe>: <filename>:<line>:<message>
1008 bool initialTab
= (lineBuffer
[0] == '\t');
1009 bool initialColonPart
= false;
1011 stGccStart
, stGccDigit
, stGcc
,
1012 stMsStart
, stMsDigit
, stMsBracket
, stMsVc
, stMsDigitComma
, stMsDotNet
,
1013 stCtagsStart
, stCtagsStartString
, stCtagsStringDollar
, stCtags
,
1015 } state
= stInitial
;
1016 for (unsigned int i
= 0; i
< lengthLine
; i
++) {
1017 char ch
= lineBuffer
[i
];
1019 if ((i
+ 1) < lengthLine
)
1020 chNext
= lineBuffer
[i
+ 1];
1021 if (state
== stInitial
) {
1023 // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix)
1024 if ((chNext
!= '\\') && (chNext
!= '/') && (chNext
!= ' ')) {
1025 // This check is not completely accurate as may be on
1026 // GTK+ with a file name that includes ':'.
1028 } else if (chNext
== ' ') { // indicates a Lua 5.1 error message
1029 initialColonPart
= true;
1031 } else if ((ch
== '(') && Is1To9(chNext
) && (!initialTab
)) {
1033 // Check against '0' often removes phone numbers
1035 } else if ((ch
== '\t') && (!initialTab
)) {
1037 state
= stCtagsStart
;
1039 } else if (state
== stGccStart
) { // <filename>:
1040 state
= Is1To9(ch
) ? stGccDigit
: stUnrecognized
;
1041 } else if (state
== stGccDigit
) { // <filename>:<line>
1043 state
= stGcc
; // :9.*: is GCC
1046 } else if (!Is0To9(ch
)) {
1047 state
= stUnrecognized
;
1049 } else if (state
== stMsStart
) { // <filename>(
1050 state
= Is0To9(ch
) ? stMsDigit
: stUnrecognized
;
1051 } else if (state
== stMsDigit
) { // <filename>(<line>
1053 state
= stMsDigitComma
;
1054 } else if (ch
== ')') {
1055 state
= stMsBracket
;
1056 } else if ((ch
!= ' ') && !Is0To9(ch
)) {
1057 state
= stUnrecognized
;
1059 } else if (state
== stMsBracket
) { // <filename>(<line>)
1060 if ((ch
== ' ') && (chNext
== ':')) {
1062 } else if ((ch
== ':' && chNext
== ' ') || (ch
== ' ')) {
1063 // Possibly Delphi.. don't test against chNext as it's one of the strings below.
1065 unsigned int j
, chPos
;
1069 numstep
= 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i.
1071 numstep
= 2; // otherwise add 2.
1072 for (j
= i
+ numstep
; j
< lengthLine
&& IsAlphabetic(lineBuffer
[j
]) && chPos
< sizeof(word
) - 1; j
++)
1073 word
[chPos
++] = lineBuffer
[j
];
1075 if (!CompareCaseInsensitive(word
, "error") || !CompareCaseInsensitive(word
, "warning") ||
1076 !CompareCaseInsensitive(word
, "fatal") || !CompareCaseInsensitive(word
, "catastrophic") ||
1077 !CompareCaseInsensitive(word
, "note") || !CompareCaseInsensitive(word
, "remark")) {
1080 state
= stUnrecognized
;
1082 state
= stUnrecognized
;
1084 } else if (state
== stMsDigitComma
) { // <filename>(<line>,
1088 } else if ((ch
!= ' ') && !Is0To9(ch
)) {
1089 state
= stUnrecognized
;
1091 } else if (state
== stCtagsStart
) {
1092 if ((lineBuffer
[i
- 1] == '\t') &&
1093 ((ch
== '/' && lineBuffer
[i
+ 1] == '^') || Is0To9(ch
))) {
1096 } else if ((ch
== '/') && (lineBuffer
[i
+ 1] == '^')) {
1097 state
= stCtagsStartString
;
1099 } else if ((state
== stCtagsStartString
) && ((lineBuffer
[i
] == '$') && (lineBuffer
[i
+ 1] == '/'))) {
1100 state
= stCtagsStringDollar
;
1104 if (state
== stGcc
) {
1105 return initialColonPart
? SCE_ERR_LUA
: SCE_ERR_GCC
;
1106 } else if ((state
== stMsVc
) || (state
== stMsDotNet
)) {
1108 } else if ((state
== stCtagsStringDollar
) || (state
== stCtags
)) {
1109 return SCE_ERR_CTAG
;
1111 return SCE_ERR_DEFAULT
;
1116 static void ColouriseErrorListLine(
1118 unsigned int lengthLine
,
1119 unsigned int endPos
,
1121 bool valueSeparate
) {
1122 int startValue
= -1;
1123 int style
= RecogniseErrorListLine(lineBuffer
, lengthLine
, startValue
);
1124 if (valueSeparate
&& (startValue
>= 0)) {
1125 styler
.ColourTo(endPos
- (lengthLine
- startValue
), style
);
1126 styler
.ColourTo(endPos
, SCE_ERR_VALUE
);
1128 styler
.ColourTo(endPos
, style
);
1132 static void ColouriseErrorListDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
1133 char lineBuffer
[10000];
1134 styler
.StartAt(startPos
);
1135 styler
.StartSegment(startPos
);
1136 unsigned int linePos
= 0;
1138 // property lexer.errorlist.value.separate
1139 // For lines in the output pane that are matches from Find in Files or GCC-style
1140 // diagnostics, style the path and line number separately from the rest of the
1141 // line with style 21 used for the rest of the line.
1142 // This allows matched text to be more easily distinguished from its location.
1143 bool valueSeparate
= styler
.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0;
1144 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
1145 lineBuffer
[linePos
++] = styler
[i
];
1146 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
1147 // End of line (or of line buffer) met, colourise it
1148 lineBuffer
[linePos
] = '\0';
1149 ColouriseErrorListLine(lineBuffer
, linePos
, i
, styler
, valueSeparate
);
1153 if (linePos
> 0) { // Last line does not have ending characters
1154 ColouriseErrorListLine(lineBuffer
, linePos
, startPos
+ length
- 1, styler
, valueSeparate
);
1158 static int isSpecial(char s
) {
1159 return (s
== '\\') || (s
== ',') || (s
== ';') || (s
== '\'') || (s
== ' ') ||
1160 (s
== '\"') || (s
== '`') || (s
== '^') || (s
== '~');
1163 static int isTag(int start
, Accessor
&styler
) {
1165 unsigned int i
= 0, e
= 1;
1166 while (i
< 5 && e
) {
1167 s
[i
] = styler
[start
+ i
];
1169 e
= styler
[start
+ i
] != '{';
1172 return (strcmp(s
, "begin") == 0) || (strcmp(s
, "end") == 0);
1175 static void ColouriseLatexDoc(unsigned int startPos
, int length
, int initStyle
,
1176 WordList
*[], Accessor
&styler
) {
1178 styler
.StartAt(startPos
);
1180 int state
= initStyle
;
1181 char chNext
= styler
[startPos
];
1182 styler
.StartSegment(startPos
);
1183 int lengthDoc
= startPos
+ length
;
1185 for (int i
= startPos
; i
< lengthDoc
; i
++) {
1187 chNext
= styler
.SafeGetCharAt(i
+ 1);
1189 if (styler
.IsLeadByte(ch
)) {
1190 chNext
= styler
.SafeGetCharAt(i
+ 2);
1195 case SCE_L_DEFAULT
:
1198 styler
.ColourTo(i
- 1, state
);
1199 if (isSpecial(styler
[i
+ 1])) {
1200 styler
.ColourTo(i
+ 1, SCE_L_COMMAND
);
1202 chNext
= styler
.SafeGetCharAt(i
+ 1);
1204 if (isTag(i
+ 1, styler
))
1207 state
= SCE_L_COMMAND
;
1211 styler
.ColourTo(i
- 1, state
);
1213 if (chNext
== '$') {
1215 chNext
= styler
.SafeGetCharAt(i
+ 1);
1219 styler
.ColourTo(i
- 1, state
);
1220 state
= SCE_L_COMMENT
;
1224 case SCE_L_COMMAND
:
1225 if (chNext
== '[' || chNext
== '{' || chNext
== '}' ||
1226 chNext
== ' ' || chNext
== '\r' || chNext
== '\n') {
1227 styler
.ColourTo(i
, state
);
1228 state
= SCE_L_DEFAULT
;
1230 chNext
= styler
.SafeGetCharAt(i
+ 1);
1235 styler
.ColourTo(i
, state
);
1236 state
= SCE_L_DEFAULT
;
1241 if (chNext
== '$') {
1243 chNext
= styler
.SafeGetCharAt(i
+ 1);
1245 styler
.ColourTo(i
, state
);
1246 state
= SCE_L_DEFAULT
;
1249 case SCE_L_COMMENT
:
1250 if (ch
== '\r' || ch
== '\n') {
1251 styler
.ColourTo(i
- 1, state
);
1252 state
= SCE_L_DEFAULT
;
1256 styler
.ColourTo(lengthDoc
-1, state
);
1259 static const char *const batchWordListDesc
[] = {
1260 "Internal Commands",
1261 "External Commands",
1265 static const char *const emptyWordListDesc
[] = {
1269 static void ColouriseNullDoc(unsigned int startPos
, int length
, int, WordList
*[],
1271 // Null language means all style bytes are 0 so just mark the end - no need to fill in.
1273 styler
.StartAt(startPos
+ length
- 1);
1274 styler
.StartSegment(startPos
+ length
- 1);
1275 styler
.ColourTo(startPos
+ length
- 1, 0);
1279 LexerModule
lmBatch(SCLEX_BATCH
, ColouriseBatchDoc
, "batch", 0, batchWordListDesc
);
1280 LexerModule
lmDiff(SCLEX_DIFF
, ColouriseDiffDoc
, "diff", FoldDiffDoc
, emptyWordListDesc
);
1281 LexerModule
lmPo(SCLEX_PO
, ColourisePoDoc
, "po", 0, emptyWordListDesc
);
1282 LexerModule
lmProps(SCLEX_PROPERTIES
, ColourisePropsDoc
, "props", FoldPropsDoc
, emptyWordListDesc
);
1283 LexerModule
lmMake(SCLEX_MAKEFILE
, ColouriseMakeDoc
, "makefile", 0, emptyWordListDesc
);
1284 LexerModule
lmErrorList(SCLEX_ERRORLIST
, ColouriseErrorListDoc
, "errorlist", 0, emptyWordListDesc
);
1285 LexerModule
lmLatex(SCLEX_LATEX
, ColouriseLatexDoc
, "latex", 0, emptyWordListDesc
);
1286 LexerModule
lmNull(SCLEX_NULL
, ColouriseNullDoc
, "null");