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.
20 #include "Scintilla.h"
24 using namespace Scintilla
;
27 static bool strstart(const char *haystack
, const char *needle
) {
28 return strncmp(haystack
, needle
, strlen(needle
)) == 0;
31 static bool Is0To9(char ch
) {
32 return (ch
>= '0') && (ch
<= '9');
35 static bool Is1To9(char ch
) {
36 return (ch
>= '1') && (ch
<= '9');
39 static inline bool AtEOL(Accessor
&styler
, unsigned int i
) {
40 return (styler
[i
] == '\n') ||
41 ((styler
[i
] == '\r') && (styler
.SafeGetCharAt(i
+ 1) != '\n'));
44 // Tests for BATCH Operators
45 static bool IsBOperator(char ch
) {
46 return (ch
== '=') || (ch
== '+') || (ch
== '>') || (ch
== '<') ||
47 (ch
== '|') || (ch
== '?') || (ch
== '*');
50 // Tests for BATCH Separators
51 static bool IsBSeparator(char ch
) {
52 return (ch
== '\\') || (ch
== '.') || (ch
== ';') ||
53 (ch
== '\"') || (ch
== '\'') || (ch
== '/') || (ch
== ')');
56 static void ColouriseBatchLine(
58 unsigned int lengthLine
,
59 unsigned int startLine
,
61 WordList
*keywordlists
[],
64 unsigned int offset
= 0; // Line Buffer Offset
65 unsigned int cmdLoc
; // External Command / Program Location
66 char wordBuffer
[81]; // Word Buffer - large to catch long paths
67 unsigned int wbl
; // Word Buffer Length
68 unsigned int wbo
; // Word Buffer Offset - also Special Keyword Buffer Length
69 WordList
&keywords
= *keywordlists
[0]; // Internal Commands
70 WordList
&keywords2
= *keywordlists
[1]; // External Commands (optional)
72 // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords
73 // Toggling Regular Keyword Checking off improves readability
74 // Other Regular Keywords and External Commands / Programs might also benefit from toggling
75 // Need a more robust algorithm to properly toggle Regular Keyword Checking
76 bool continueProcessing
= true; // Used to toggle Regular Keyword Checking
77 // Special Keywords are those that allow certain characters without whitespace after the command
78 // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path=
79 // Special Keyword Buffer used to determine if the first n characters is a Keyword
80 char sKeywordBuffer
[10]; // Special Keyword Buffer
81 bool sKeywordFound
; // Exit Special Keyword for-loop if found
83 // Skip initial spaces
84 while ((offset
< lengthLine
) && (isspacechar(lineBuffer
[offset
]))) {
87 // Colorize Default Text
88 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
89 // Set External Command / Program Location
92 // Check for Fake Label (Comment) or Real Label - return if found
93 if (lineBuffer
[offset
] == ':') {
94 if (lineBuffer
[offset
+ 1] == ':') {
95 // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
96 styler
.ColourTo(endPos
, SCE_BAT_COMMENT
);
98 // Colorize Real Label
99 styler
.ColourTo(endPos
, SCE_BAT_LABEL
);
102 // Check for Drive Change (Drive Change is internal command) - return if found
103 } else if ((isalpha(lineBuffer
[offset
])) &&
104 (lineBuffer
[offset
+ 1] == ':') &&
105 ((isspacechar(lineBuffer
[offset
+ 2])) ||
106 (((lineBuffer
[offset
+ 2] == '\\')) &&
107 (isspacechar(lineBuffer
[offset
+ 3]))))) {
108 // Colorize Regular Keyword
109 styler
.ColourTo(endPos
, SCE_BAT_WORD
);
113 // Check for Hide Command (@ECHO OFF/ON)
114 if (lineBuffer
[offset
] == '@') {
115 styler
.ColourTo(startLine
+ offset
, SCE_BAT_HIDE
);
119 while ((offset
< lengthLine
) && (isspacechar(lineBuffer
[offset
]))) {
123 // Read remainder of line word-at-a-time or remainder-of-word-at-a-time
124 while (offset
< lengthLine
) {
125 if (offset
> startLine
) {
126 // Colorize Default Text
127 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
129 // Copy word from Line Buffer into Word Buffer
131 for (; offset
< lengthLine
&& wbl
< 80 &&
132 !isspacechar(lineBuffer
[offset
]); wbl
++, offset
++) {
133 wordBuffer
[wbl
] = static_cast<char>(tolower(lineBuffer
[offset
]));
135 wordBuffer
[wbl
] = '\0';
138 // Check for Comment - return if found
139 if (CompareCaseInsensitive(wordBuffer
, "rem") == 0) {
140 styler
.ColourTo(endPos
, SCE_BAT_COMMENT
);
143 // Check for Separator
144 if (IsBSeparator(wordBuffer
[0])) {
145 // Check for External Command / Program
146 if ((cmdLoc
== offset
- wbl
) &&
147 ((wordBuffer
[0] == ':') ||
148 (wordBuffer
[0] == '\\') ||
149 (wordBuffer
[0] == '.'))) {
150 // Reset Offset to re-process remainder of word
152 // Colorize External Command / Program
154 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
155 } else if (keywords2
.InList(wordBuffer
)) {
156 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
158 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
160 // Reset External Command / Program Location
163 // Reset Offset to re-process remainder of word
165 // Colorize Default Text
166 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
168 // Check for Regular Keyword in list
169 } else if ((keywords
.InList(wordBuffer
)) &&
170 (continueProcessing
)) {
171 // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking
172 if ((CompareCaseInsensitive(wordBuffer
, "echo") == 0) ||
173 (CompareCaseInsensitive(wordBuffer
, "goto") == 0) ||
174 (CompareCaseInsensitive(wordBuffer
, "prompt") == 0) ||
175 (CompareCaseInsensitive(wordBuffer
, "set") == 0)) {
176 continueProcessing
= false;
178 // Identify External Command / Program Location for ERRORLEVEL, and EXIST
179 if ((CompareCaseInsensitive(wordBuffer
, "errorlevel") == 0) ||
180 (CompareCaseInsensitive(wordBuffer
, "exist") == 0)) {
181 // Reset External Command / Program Location
184 while ((cmdLoc
< lengthLine
) &&
185 (isspacechar(lineBuffer
[cmdLoc
]))) {
189 while ((cmdLoc
< lengthLine
) &&
190 (!isspacechar(lineBuffer
[cmdLoc
]))) {
194 while ((cmdLoc
< lengthLine
) &&
195 (isspacechar(lineBuffer
[cmdLoc
]))) {
198 // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH
199 } else if ((CompareCaseInsensitive(wordBuffer
, "call") == 0) ||
200 (CompareCaseInsensitive(wordBuffer
, "do") == 0) ||
201 (CompareCaseInsensitive(wordBuffer
, "loadhigh") == 0) ||
202 (CompareCaseInsensitive(wordBuffer
, "lh") == 0)) {
203 // Reset External Command / Program Location
206 while ((cmdLoc
< lengthLine
) &&
207 (isspacechar(lineBuffer
[cmdLoc
]))) {
211 // Colorize Regular keyword
212 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_WORD
);
213 // No need to Reset Offset
214 // Check for Special Keyword in list, External Command / Program, or Default Text
215 } else if ((wordBuffer
[0] != '%') &&
216 (!IsBOperator(wordBuffer
[0])) &&
217 (continueProcessing
)) {
218 // Check for Special Keyword
219 // Affected Commands are in Length range 2-6
220 // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected
221 sKeywordFound
= false;
222 for (unsigned int keywordLength
= 2; keywordLength
< wbl
&& keywordLength
< 7 && !sKeywordFound
; keywordLength
++) {
224 // Copy Keyword Length from Word Buffer into Special Keyword Buffer
225 for (; wbo
< keywordLength
; wbo
++) {
226 sKeywordBuffer
[wbo
] = static_cast<char>(wordBuffer
[wbo
]);
228 sKeywordBuffer
[wbo
] = '\0';
229 // Check for Special Keyword in list
230 if ((keywords
.InList(sKeywordBuffer
)) &&
231 ((IsBOperator(wordBuffer
[wbo
])) ||
232 (IsBSeparator(wordBuffer
[wbo
])))) {
233 sKeywordFound
= true;
234 // ECHO requires no further Regular Keyword Checking
235 if (CompareCaseInsensitive(sKeywordBuffer
, "echo") == 0) {
236 continueProcessing
= false;
238 // Colorize Special Keyword as Regular Keyword
239 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_WORD
);
240 // Reset Offset to re-process remainder of word
241 offset
-= (wbl
- wbo
);
244 // Check for External Command / Program or Default Text
245 if (!sKeywordFound
) {
247 // Check for External Command / Program
248 if (cmdLoc
== offset
- wbl
) {
249 // Read up to %, Operator or Separator
250 while ((wbo
< wbl
) &&
251 (wordBuffer
[wbo
] != '%') &&
252 (!IsBOperator(wordBuffer
[wbo
])) &&
253 (!IsBSeparator(wordBuffer
[wbo
]))) {
256 // Reset External Command / Program Location
257 cmdLoc
= offset
- (wbl
- wbo
);
258 // Reset Offset to re-process remainder of word
259 offset
-= (wbl
- wbo
);
260 // CHOICE requires no further Regular Keyword Checking
261 if (CompareCaseInsensitive(wordBuffer
, "choice") == 0) {
262 continueProcessing
= false;
264 // Check for START (and its switches) - What follows is External Command \ Program
265 if (CompareCaseInsensitive(wordBuffer
, "start") == 0) {
266 // Reset External Command / Program Location
269 while ((cmdLoc
< lengthLine
) &&
270 (isspacechar(lineBuffer
[cmdLoc
]))) {
273 // Reset External Command / Program Location if command switch detected
274 if (lineBuffer
[cmdLoc
] == '/') {
275 // Skip command switch
276 while ((cmdLoc
< lengthLine
) &&
277 (!isspacechar(lineBuffer
[cmdLoc
]))) {
281 while ((cmdLoc
< lengthLine
) &&
282 (isspacechar(lineBuffer
[cmdLoc
]))) {
287 // Colorize External Command / Program
289 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
290 } else if (keywords2
.InList(wordBuffer
)) {
291 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
293 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
295 // No need to Reset Offset
296 // Check for Default Text
298 // Read up to %, Operator or Separator
299 while ((wbo
< wbl
) &&
300 (wordBuffer
[wbo
] != '%') &&
301 (!IsBOperator(wordBuffer
[wbo
])) &&
302 (!IsBSeparator(wordBuffer
[wbo
]))) {
305 // Colorize Default Text
306 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_DEFAULT
);
307 // Reset Offset to re-process remainder of word
308 offset
-= (wbl
- wbo
);
311 // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a)
312 } else if (wordBuffer
[0] == '%') {
313 // Colorize Default Text
314 styler
.ColourTo(startLine
+ offset
- 1 - wbl
, SCE_BAT_DEFAULT
);
316 // Search to end of word for second % (can be a long path)
317 while ((wbo
< wbl
) &&
318 (wordBuffer
[wbo
] != '%') &&
319 (!IsBOperator(wordBuffer
[wbo
])) &&
320 (!IsBSeparator(wordBuffer
[wbo
]))) {
323 // Check for Argument (%n) or (%*)
324 if (((Is0To9(wordBuffer
[1])) || (wordBuffer
[1] == '*')) &&
325 (wordBuffer
[wbo
] != '%')) {
326 // Check for External Command / Program
327 if (cmdLoc
== offset
- wbl
) {
328 cmdLoc
= offset
- (wbl
- 2);
331 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 2), SCE_BAT_IDENTIFIER
);
332 // Reset Offset to re-process remainder of word
334 // Check for Expanded Argument (%~...) / Variable (%%~...)
335 } else if (((wbl
> 1) && (wordBuffer
[1] == '~')) ||
336 ((wbl
> 2) && (wordBuffer
[1] == '%') && (wordBuffer
[2] == '~'))) {
337 // Check for External Command / Program
338 if (cmdLoc
== offset
- wbl
) {
339 cmdLoc
= offset
- (wbl
- wbo
);
341 // Colorize Expanded Argument / Variable
342 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_IDENTIFIER
);
343 // Reset Offset to re-process remainder of word
344 offset
-= (wbl
- wbo
);
345 // Check for Environment Variable (%x...%)
346 } else if ((wordBuffer
[1] != '%') &&
347 (wordBuffer
[wbo
] == '%')) {
349 // Check for External Command / Program
350 if (cmdLoc
== offset
- wbl
) {
351 cmdLoc
= offset
- (wbl
- wbo
);
353 // Colorize Environment Variable
354 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_IDENTIFIER
);
355 // Reset Offset to re-process remainder of word
356 offset
-= (wbl
- wbo
);
357 // Check for Local Variable (%%a)
360 (wordBuffer
[1] == '%') &&
361 (wordBuffer
[2] != '%') &&
362 (!IsBOperator(wordBuffer
[2])) &&
363 (!IsBSeparator(wordBuffer
[2]))) {
364 // Check for External Command / Program
365 if (cmdLoc
== offset
- wbl
) {
366 cmdLoc
= offset
- (wbl
- 3);
368 // Colorize Local Variable
369 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 3), SCE_BAT_IDENTIFIER
);
370 // Reset Offset to re-process remainder of word
373 // Check for Operator
374 } else if (IsBOperator(wordBuffer
[0])) {
375 // Colorize Default Text
376 styler
.ColourTo(startLine
+ offset
- 1 - wbl
, SCE_BAT_DEFAULT
);
377 // Check for Comparison Operator
378 if ((wordBuffer
[0] == '=') && (wordBuffer
[1] == '=')) {
379 // Identify External Command / Program Location for IF
382 while ((cmdLoc
< lengthLine
) &&
383 (isspacechar(lineBuffer
[cmdLoc
]))) {
386 // Colorize Comparison Operator
387 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 2), SCE_BAT_OPERATOR
);
388 // Reset Offset to re-process remainder of word
390 // Check for Pipe Operator
391 } else if (wordBuffer
[0] == '|') {
392 // Reset External Command / Program Location
393 cmdLoc
= offset
- wbl
+ 1;
395 while ((cmdLoc
< lengthLine
) &&
396 (isspacechar(lineBuffer
[cmdLoc
]))) {
399 // Colorize Pipe Operator
400 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 1), SCE_BAT_OPERATOR
);
401 // Reset Offset to re-process remainder of word
403 // Check for Other Operator
405 // Check for > Operator
406 if (wordBuffer
[0] == '>') {
407 // Turn Keyword and External Command / Program checking back on
408 continueProcessing
= true;
410 // Colorize Other Operator
411 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 1), SCE_BAT_OPERATOR
);
412 // Reset Offset to re-process remainder of word
415 // Check for Default Text
417 // Read up to %, Operator or Separator
418 while ((wbo
< wbl
) &&
419 (wordBuffer
[wbo
] != '%') &&
420 (!IsBOperator(wordBuffer
[wbo
])) &&
421 (!IsBSeparator(wordBuffer
[wbo
]))) {
424 // Colorize Default Text
425 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_DEFAULT
);
426 // Reset Offset to re-process remainder of word
427 offset
-= (wbl
- wbo
);
429 // Skip next spaces - nothing happens if Offset was Reset
430 while ((offset
< lengthLine
) && (isspacechar(lineBuffer
[offset
]))) {
434 // Colorize Default Text for remainder of line - currently not lexed
435 styler
.ColourTo(endPos
, SCE_BAT_DEFAULT
);
438 static void ColouriseBatchDoc(
439 unsigned int startPos
,
442 WordList
*keywordlists
[],
445 char lineBuffer
[1024];
447 styler
.StartAt(startPos
);
448 styler
.StartSegment(startPos
);
449 unsigned int linePos
= 0;
450 unsigned int startLine
= startPos
;
451 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
452 lineBuffer
[linePos
++] = styler
[i
];
453 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
454 // End of line (or of line buffer) met, colourise it
455 lineBuffer
[linePos
] = '\0';
456 ColouriseBatchLine(lineBuffer
, linePos
, startLine
, i
, keywordlists
, styler
);
461 if (linePos
> 0) { // Last line does not have ending characters
462 lineBuffer
[linePos
] = '\0';
463 ColouriseBatchLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1,
464 keywordlists
, styler
);
468 static void ColouriseDiffLine(char *lineBuffer
, int endLine
, Accessor
&styler
) {
469 // It is needed to remember the current state to recognize starting
470 // comment lines before the first "diff " or "--- ". If a real
471 // difference starts then each line starting with ' ' is a whitespace
472 // otherwise it is considered a comment (Only in..., Binary file...)
473 if (0 == strncmp(lineBuffer
, "diff ", 5)) {
474 styler
.ColourTo(endLine
, SCE_DIFF_COMMAND
);
475 } else if (0 == strncmp(lineBuffer
, "Index: ", 7)) { // For subversion's diff
476 styler
.ColourTo(endLine
, SCE_DIFF_COMMAND
);
477 } else if (0 == strncmp(lineBuffer
, "---", 3)) {
478 // In a context diff, --- appears in both the header and the position markers
479 if (lineBuffer
[3] == ' ' && atoi(lineBuffer
+ 4) && !strchr(lineBuffer
, '/'))
480 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
481 else if (lineBuffer
[3] == '\r' || lineBuffer
[3] == '\n')
482 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
484 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
485 } else if (0 == strncmp(lineBuffer
, "+++ ", 4)) {
486 // I don't know of any diff where "+++ " is a position marker, but for
487 // consistency, do the same as with "--- " and "*** ".
488 if (atoi(lineBuffer
+4) && !strchr(lineBuffer
, '/'))
489 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
491 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
492 } else if (0 == strncmp(lineBuffer
, "====", 4)) { // For p4's diff
493 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
494 } else if (0 == strncmp(lineBuffer
, "***", 3)) {
495 // In a context diff, *** appears in both the header and the position markers.
496 // Also ******** is a chunk header, but here it's treated as part of the
497 // position marker since there is no separate style for a chunk header.
498 if (lineBuffer
[3] == ' ' && atoi(lineBuffer
+4) && !strchr(lineBuffer
, '/'))
499 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
500 else if (lineBuffer
[3] == '*')
501 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
503 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
504 } else if (0 == strncmp(lineBuffer
, "? ", 2)) { // For difflib
505 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
506 } else if (lineBuffer
[0] == '@') {
507 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
508 } else if (lineBuffer
[0] >= '0' && lineBuffer
[0] <= '9') {
509 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
510 } else if (lineBuffer
[0] == '-' || lineBuffer
[0] == '<') {
511 styler
.ColourTo(endLine
, SCE_DIFF_DELETED
);
512 } else if (lineBuffer
[0] == '+' || lineBuffer
[0] == '>') {
513 styler
.ColourTo(endLine
, SCE_DIFF_ADDED
);
514 } else if (lineBuffer
[0] == '!') {
515 styler
.ColourTo(endLine
, SCE_DIFF_CHANGED
);
516 } else if (lineBuffer
[0] != ' ') {
517 styler
.ColourTo(endLine
, SCE_DIFF_COMMENT
);
519 styler
.ColourTo(endLine
, SCE_DIFF_DEFAULT
);
523 static void ColouriseDiffDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
524 char lineBuffer
[1024];
525 styler
.StartAt(startPos
);
526 styler
.StartSegment(startPos
);
527 unsigned int linePos
= 0;
528 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
529 lineBuffer
[linePos
++] = styler
[i
];
530 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
531 // End of line (or of line buffer) met, colourise it
532 lineBuffer
[linePos
] = '\0';
533 ColouriseDiffLine(lineBuffer
, i
, styler
);
537 if (linePos
> 0) { // Last line does not have ending characters
538 ColouriseDiffLine(lineBuffer
, startPos
+ length
- 1, styler
);
542 static void FoldDiffDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
543 int curLine
= styler
.GetLine(startPos
);
544 int curLineStart
= styler
.LineStart(curLine
);
545 int prevLevel
= curLine
> 0 ? styler
.LevelAt(curLine
- 1) : SC_FOLDLEVELBASE
;
549 int lineType
= styler
.StyleAt(curLineStart
);
550 if (lineType
== SCE_DIFF_COMMAND
)
551 nextLevel
= SC_FOLDLEVELBASE
| SC_FOLDLEVELHEADERFLAG
;
552 else if (lineType
== SCE_DIFF_HEADER
)
553 nextLevel
= (SC_FOLDLEVELBASE
+ 1) | SC_FOLDLEVELHEADERFLAG
;
554 else if (lineType
== SCE_DIFF_POSITION
&& styler
[curLineStart
] != '-')
555 nextLevel
= (SC_FOLDLEVELBASE
+ 2) | SC_FOLDLEVELHEADERFLAG
;
556 else if (prevLevel
& SC_FOLDLEVELHEADERFLAG
)
557 nextLevel
= (prevLevel
& SC_FOLDLEVELNUMBERMASK
) + 1;
559 nextLevel
= prevLevel
;
561 if ((nextLevel
& SC_FOLDLEVELHEADERFLAG
) && (nextLevel
== prevLevel
))
562 styler
.SetLevel(curLine
-1, prevLevel
& ~SC_FOLDLEVELHEADERFLAG
);
564 styler
.SetLevel(curLine
, nextLevel
);
565 prevLevel
= nextLevel
;
567 curLineStart
= styler
.LineStart(++curLine
);
568 } while (static_cast<int>(startPos
) + length
> curLineStart
);
571 static void ColourisePoLine(
573 unsigned int lengthLine
,
574 unsigned int startLine
,
579 static unsigned int state
= SCE_PO_DEFAULT
;
580 unsigned int state_start
= SCE_PO_DEFAULT
;
582 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) // Skip initial spaces
584 if (i
< lengthLine
) {
585 if (lineBuffer
[i
] == '#') {
586 // check if the comment contains any flags ("#, ") and
587 // then whether the flags contain "fuzzy"
588 if (strstart(lineBuffer
, "#, ") && strstr(lineBuffer
, "fuzzy"))
589 styler
.ColourTo(endPos
, SCE_PO_FUZZY
);
591 styler
.ColourTo(endPos
, SCE_PO_COMMENT
);
593 if (lineBuffer
[0] == '"') {
594 // line continuation, use previous style
595 styler
.ColourTo(endPos
, state
);
597 // this implicitly also matches "msgid_plural"
598 } else if (strstart(lineBuffer
, "msgid")) {
599 state_start
= SCE_PO_MSGID
;
600 state
= SCE_PO_MSGID_TEXT
;
601 } else if (strstart(lineBuffer
, "msgstr")) {
602 state_start
= SCE_PO_MSGSTR
;
603 state
= SCE_PO_MSGSTR_TEXT
;
604 } else if (strstart(lineBuffer
, "msgctxt")) {
605 state_start
= SCE_PO_MSGCTXT
;
606 state
= SCE_PO_MSGCTXT_TEXT
;
608 if (state_start
!= SCE_PO_DEFAULT
) {
609 // find the next space
610 while ((i
< lengthLine
) && ! isspacechar(lineBuffer
[i
]))
612 styler
.ColourTo(startLine
+ i
- 1, state_start
);
613 styler
.ColourTo(startLine
+ i
, SCE_PO_DEFAULT
);
614 styler
.ColourTo(endPos
, state
);
618 styler
.ColourTo(endPos
, SCE_PO_DEFAULT
);
622 static void ColourisePoDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
623 char lineBuffer
[1024];
624 styler
.StartAt(startPos
);
625 styler
.StartSegment(startPos
);
626 unsigned int linePos
= 0;
627 unsigned int startLine
= startPos
;
628 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
629 lineBuffer
[linePos
++] = styler
[i
];
630 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
631 // End of line (or of line buffer) met, colourise it
632 lineBuffer
[linePos
] = '\0';
633 ColourisePoLine(lineBuffer
, linePos
, startLine
, i
, styler
);
638 if (linePos
> 0) { // Last line does not have ending characters
639 ColourisePoLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
);
644 static void ColourisePropsLine(
646 unsigned int lengthLine
,
647 unsigned int startLine
,
652 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) // Skip initial spaces
654 if (i
< lengthLine
) {
655 if (lineBuffer
[i
] == '#' || lineBuffer
[i
] == '!' || lineBuffer
[i
] == ';') {
656 styler
.ColourTo(endPos
, SCE_PROPS_COMMENT
);
657 } else if (lineBuffer
[i
] == '[') {
658 styler
.ColourTo(endPos
, SCE_PROPS_SECTION
);
659 } else if (lineBuffer
[i
] == '@') {
660 styler
.ColourTo(startLine
+ i
, SCE_PROPS_DEFVAL
);
661 if (lineBuffer
[++i
] == '=')
662 styler
.ColourTo(startLine
+ i
, SCE_PROPS_ASSIGNMENT
);
663 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
665 // Search for the '=' character
666 while ((i
< lengthLine
) && (lineBuffer
[i
] != '='))
668 if ((i
< lengthLine
) && (lineBuffer
[i
] == '=')) {
669 styler
.ColourTo(startLine
+ i
- 1, SCE_PROPS_KEY
);
670 styler
.ColourTo(startLine
+ i
, SCE_PROPS_ASSIGNMENT
);
671 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
673 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
677 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
681 static void ColourisePropsDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
682 char lineBuffer
[1024];
683 styler
.StartAt(startPos
);
684 styler
.StartSegment(startPos
);
685 unsigned int linePos
= 0;
686 unsigned int startLine
= startPos
;
687 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
688 lineBuffer
[linePos
++] = styler
[i
];
689 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
690 // End of line (or of line buffer) met, colourise it
691 lineBuffer
[linePos
] = '\0';
692 ColourisePropsLine(lineBuffer
, linePos
, startLine
, i
, styler
);
697 if (linePos
> 0) { // Last line does not have ending characters
698 ColourisePropsLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
);
702 // adaption by ksc, using the "} else {" trick of 1.53
704 static void FoldPropsDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
705 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
707 unsigned int endPos
= startPos
+ length
;
708 int visibleChars
= 0;
709 int lineCurrent
= styler
.GetLine(startPos
);
711 char chNext
= styler
[startPos
];
712 int styleNext
= styler
.StyleAt(startPos
);
713 bool headerPoint
= false;
716 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
718 chNext
= styler
[i
+1];
720 int style
= styleNext
;
721 styleNext
= styler
.StyleAt(i
+ 1);
722 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
724 if (style
== SCE_PROPS_SECTION
) {
729 lev
= SC_FOLDLEVELBASE
;
731 if (lineCurrent
> 0) {
732 int levelPrevious
= styler
.LevelAt(lineCurrent
- 1);
734 if (levelPrevious
& SC_FOLDLEVELHEADERFLAG
) {
735 lev
= SC_FOLDLEVELBASE
+ 1;
737 lev
= levelPrevious
& SC_FOLDLEVELNUMBERMASK
;
742 lev
= SC_FOLDLEVELBASE
;
744 if (visibleChars
== 0 && foldCompact
)
745 lev
|= SC_FOLDLEVELWHITEFLAG
;
748 lev
|= SC_FOLDLEVELHEADERFLAG
;
750 if (lev
!= styler
.LevelAt(lineCurrent
)) {
751 styler
.SetLevel(lineCurrent
, lev
);
758 if (!isspacechar(ch
))
762 if (lineCurrent
> 0) {
763 int levelPrevious
= styler
.LevelAt(lineCurrent
- 1);
764 if (levelPrevious
& SC_FOLDLEVELHEADERFLAG
) {
765 lev
= SC_FOLDLEVELBASE
+ 1;
767 lev
= levelPrevious
& SC_FOLDLEVELNUMBERMASK
;
770 lev
= SC_FOLDLEVELBASE
;
772 int flagsNext
= styler
.LevelAt(lineCurrent
);
773 styler
.SetLevel(lineCurrent
, lev
| flagsNext
& ~SC_FOLDLEVELNUMBERMASK
);
776 static void ColouriseMakeLine(
778 unsigned int lengthLine
,
779 unsigned int startLine
,
784 int lastNonSpace
= -1;
785 unsigned int state
= SCE_MAKE_DEFAULT
;
786 bool bSpecial
= false;
788 // check for a tab character in column 0 indicating a command
789 bool bCommand
= false;
790 if ((lengthLine
> 0) && (lineBuffer
[0] == '\t'))
793 // Skip initial spaces
794 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) {
797 if (lineBuffer
[i
] == '#') { // Comment
798 styler
.ColourTo(endPos
, SCE_MAKE_COMMENT
);
801 if (lineBuffer
[i
] == '!') { // Special directive
802 styler
.ColourTo(endPos
, SCE_MAKE_PREPROCESSOR
);
805 while (i
< lengthLine
) {
806 if (lineBuffer
[i
] == '$' && lineBuffer
[i
+ 1] == '(') {
807 styler
.ColourTo(startLine
+ i
- 1, state
);
808 state
= SCE_MAKE_IDENTIFIER
;
809 } else if (state
== SCE_MAKE_IDENTIFIER
&& lineBuffer
[i
] == ')') {
810 styler
.ColourTo(startLine
+ i
, state
);
811 state
= SCE_MAKE_DEFAULT
;
814 // skip identifier and target styling if this is a command line
815 if (!bSpecial
&& !bCommand
) {
816 if (lineBuffer
[i
] == ':') {
817 if (((i
+ 1) < lengthLine
) && (lineBuffer
[i
+ 1] == '=')) {
818 // it's a ':=', so style as an identifier
819 if (lastNonSpace
>= 0)
820 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
821 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
822 styler
.ColourTo(startLine
+ i
+ 1, SCE_MAKE_OPERATOR
);
824 // We should check that no colouring was made since the beginning of the line,
825 // to avoid colouring stuff like /OUT:file
826 if (lastNonSpace
>= 0)
827 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_TARGET
);
828 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
829 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
831 bSpecial
= true; // Only react to the first ':' of the line
832 state
= SCE_MAKE_DEFAULT
;
833 } else if (lineBuffer
[i
] == '=') {
834 if (lastNonSpace
>= 0)
835 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
836 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
837 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
838 bSpecial
= true; // Only react to the first '=' of the line
839 state
= SCE_MAKE_DEFAULT
;
842 if (!isspacechar(lineBuffer
[i
])) {
847 if (state
== SCE_MAKE_IDENTIFIER
) {
848 styler
.ColourTo(endPos
, SCE_MAKE_IDEOL
); // Error, variable reference not ended
850 styler
.ColourTo(endPos
, SCE_MAKE_DEFAULT
);
854 static void ColouriseMakeDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
855 char lineBuffer
[1024];
856 styler
.StartAt(startPos
);
857 styler
.StartSegment(startPos
);
858 unsigned int linePos
= 0;
859 unsigned int startLine
= startPos
;
860 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
861 lineBuffer
[linePos
++] = styler
[i
];
862 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
863 // End of line (or of line buffer) met, colourise it
864 lineBuffer
[linePos
] = '\0';
865 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, i
, styler
);
870 if (linePos
> 0) { // Last line does not have ending characters
871 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
);
875 static int RecogniseErrorListLine(const char *lineBuffer
, unsigned int lengthLine
, int &startValue
) {
876 if (lineBuffer
[0] == '>') {
877 // Command or return status
879 } else if (lineBuffer
[0] == '<') {
880 // Diff removal, but not interested. Trapped to avoid hitting CTAG cases.
881 return SCE_ERR_DEFAULT
;
882 } else if (lineBuffer
[0] == '!') {
883 return SCE_ERR_DIFF_CHANGED
;
884 } else if (lineBuffer
[0] == '+') {
885 if (strstart(lineBuffer
, "+++ ")) {
886 return SCE_ERR_DIFF_MESSAGE
;
888 return SCE_ERR_DIFF_ADDITION
;
890 } else if (lineBuffer
[0] == '-') {
891 if (strstart(lineBuffer
, "--- ")) {
892 return SCE_ERR_DIFF_MESSAGE
;
894 return SCE_ERR_DIFF_DELETION
;
896 } else if (strstart(lineBuffer
, "cf90-")) {
897 // Absoft Pro Fortran 90/95 v8.2 error and/or warning message
899 } else if (strstart(lineBuffer
, "fortcom:")) {
900 // Intel Fortran Compiler v8.0 error/warning message
901 return SCE_ERR_IFORT
;
902 } else if (strstr(lineBuffer
, "File \"") && strstr(lineBuffer
, ", line ")) {
903 return SCE_ERR_PYTHON
;
904 } else if (strstr(lineBuffer
, " in ") && strstr(lineBuffer
, " on line ")) {
906 } else if ((strstart(lineBuffer
, "Error ") ||
907 strstart(lineBuffer
, "Warning ")) &&
908 strstr(lineBuffer
, " at (") &&
909 strstr(lineBuffer
, ") : ") &&
910 (strstr(lineBuffer
, " at (") < strstr(lineBuffer
, ") : "))) {
911 // Intel Fortran Compiler error/warning message
913 } else if (strstart(lineBuffer
, "Error ")) {
914 // Borland error message
915 return SCE_ERR_BORLAND
;
916 } else if (strstart(lineBuffer
, "Warning ")) {
917 // Borland warning message
918 return SCE_ERR_BORLAND
;
919 } else if (strstr(lineBuffer
, "at line " ) &&
920 (strstr(lineBuffer
, "at line " ) < (lineBuffer
+ lengthLine
)) &&
921 strstr(lineBuffer
, "file ") &&
922 (strstr(lineBuffer
, "file ") < (lineBuffer
+ lengthLine
))) {
923 // Lua 4 error message
925 } else if (strstr(lineBuffer
, " at " ) &&
926 (strstr(lineBuffer
, " at " ) < (lineBuffer
+ lengthLine
)) &&
927 strstr(lineBuffer
, " line ") &&
928 (strstr(lineBuffer
, " line ") < (lineBuffer
+ lengthLine
)) &&
929 (strstr(lineBuffer
, " at " ) < (strstr(lineBuffer
, " line ")))) {
930 // perl error message
932 } else if ((memcmp(lineBuffer
, " at ", 6) == 0) &&
933 strstr(lineBuffer
, ":line ")) {
936 } else if (strstart(lineBuffer
, "Line ") &&
937 strstr(lineBuffer
, ", file ")) {
938 // Essential Lahey Fortran error message
940 } else if (strstart(lineBuffer
, "line ") &&
941 strstr(lineBuffer
, " column ")) {
942 // HTML tidy style: line 42 column 1
944 } else if (strstart(lineBuffer
, "\tat ") &&
945 strstr(lineBuffer
, "(") &&
946 strstr(lineBuffer
, ".java:")) {
947 // Java stack back trace
948 return SCE_ERR_JAVA_STACK
;
950 // Look for one of the following formats:
951 // GCC: <filename>:<line>:<message>
952 // Microsoft: <filename>(<line>) :<message>
953 // Common: <filename>(<line>): warning|error|note|remark|catastrophic|fatal
954 // Common: <filename>(<line>) warning|error|note|remark|catastrophic|fatal
955 // Microsoft: <filename>(<line>,<column>)<message>
956 // CTags: \t<message>
957 // Lua 5 traceback: \t<filename>:<line>:<message>
958 // Lua 5.1: <exe>: <filename>:<line>:<message>
959 bool initialTab
= (lineBuffer
[0] == '\t');
960 bool initialColonPart
= false;
962 stGccStart
, stGccDigit
, stGcc
,
963 stMsStart
, stMsDigit
, stMsBracket
, stMsVc
, stMsDigitComma
, stMsDotNet
,
964 stCtagsStart
, stCtagsStartString
, stCtagsStringDollar
, stCtags
,
967 for (unsigned int i
= 0; i
< lengthLine
; i
++) {
968 char ch
= lineBuffer
[i
];
970 if ((i
+ 1) < lengthLine
)
971 chNext
= lineBuffer
[i
+ 1];
972 if (state
== stInitial
) {
974 // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix)
975 if ((chNext
!= '\\') && (chNext
!= '/') && (chNext
!= ' ')) {
976 // This check is not completely accurate as may be on
977 // GTK+ with a file name that includes ':'.
979 } else if (chNext
== ' ') { // indicates a Lua 5.1 error message
980 initialColonPart
= true;
982 } else if ((ch
== '(') && Is1To9(chNext
) && (!initialTab
)) {
984 // Check against '0' often removes phone numbers
986 } else if ((ch
== '\t') && (!initialTab
)) {
988 state
= stCtagsStart
;
990 } else if (state
== stGccStart
) { // <filename>:
991 state
= Is1To9(ch
) ? stGccDigit
: stUnrecognized
;
992 } else if (state
== stGccDigit
) { // <filename>:<line>
994 state
= stGcc
; // :9.*: is GCC
997 } else if (!Is0To9(ch
)) {
998 state
= stUnrecognized
;
1000 } else if (state
== stMsStart
) { // <filename>(
1001 state
= Is0To9(ch
) ? stMsDigit
: stUnrecognized
;
1002 } else if (state
== stMsDigit
) { // <filename>(<line>
1004 state
= stMsDigitComma
;
1005 } else if (ch
== ')') {
1006 state
= stMsBracket
;
1007 } else if ((ch
!= ' ') && !Is0To9(ch
)) {
1008 state
= stUnrecognized
;
1010 } else if (state
== stMsBracket
) { // <filename>(<line>)
1011 if ((ch
== ' ') && (chNext
== ':')) {
1013 } else if ((ch
== ':' && chNext
== ' ') || (ch
== ' ')) {
1014 // Possibly Delphi.. don't test against chNext as it's one of the strings below.
1016 unsigned int j
, chPos
;
1020 numstep
= 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i.
1022 numstep
= 2; // otherwise add 2.
1023 for (j
= i
+ numstep
; j
< lengthLine
&& isalpha(lineBuffer
[j
]) && chPos
< sizeof(word
) - 1; j
++)
1024 word
[chPos
++] = lineBuffer
[j
];
1026 if (!CompareCaseInsensitive(word
, "error") || !CompareCaseInsensitive(word
, "warning") ||
1027 !CompareCaseInsensitive(word
, "fatal") || !CompareCaseInsensitive(word
, "catastrophic") ||
1028 !CompareCaseInsensitive(word
, "note") || !CompareCaseInsensitive(word
, "remark")) {
1031 state
= stUnrecognized
;
1033 state
= stUnrecognized
;
1035 } else if (state
== stMsDigitComma
) { // <filename>(<line>,
1039 } else if ((ch
!= ' ') && !Is0To9(ch
)) {
1040 state
= stUnrecognized
;
1042 } else if (state
== stCtagsStart
) {
1043 if ((lineBuffer
[i
- 1] == '\t') &&
1044 ((ch
== '/' && lineBuffer
[i
+ 1] == '^') || Is0To9(ch
))) {
1047 } else if ((ch
== '/') && (lineBuffer
[i
+ 1] == '^')) {
1048 state
= stCtagsStartString
;
1050 } else if ((state
== stCtagsStartString
) && ((lineBuffer
[i
] == '$') && (lineBuffer
[i
+ 1] == '/'))) {
1051 state
= stCtagsStringDollar
;
1055 if (state
== stGcc
) {
1056 return initialColonPart
? SCE_ERR_LUA
: SCE_ERR_GCC
;
1057 } else if ((state
== stMsVc
) || (state
== stMsDotNet
)) {
1059 } else if ((state
== stCtagsStringDollar
) || (state
== stCtags
)) {
1060 return SCE_ERR_CTAG
;
1062 return SCE_ERR_DEFAULT
;
1067 static void ColouriseErrorListLine(
1069 unsigned int lengthLine
,
1070 unsigned int endPos
,
1072 bool valueSeparate
) {
1073 int startValue
= -1;
1074 int style
= RecogniseErrorListLine(lineBuffer
, lengthLine
, startValue
);
1075 if (valueSeparate
&& (startValue
>= 0)) {
1076 styler
.ColourTo(endPos
- (lengthLine
- startValue
), style
);
1077 styler
.ColourTo(endPos
, SCE_ERR_VALUE
);
1079 styler
.ColourTo(endPos
, style
);
1083 static void ColouriseErrorListDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
1084 char lineBuffer
[10000];
1085 styler
.StartAt(startPos
);
1086 styler
.StartSegment(startPos
);
1087 unsigned int linePos
= 0;
1088 bool valueSeparate
= styler
.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0;
1089 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
1090 lineBuffer
[linePos
++] = styler
[i
];
1091 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
1092 // End of line (or of line buffer) met, colourise it
1093 lineBuffer
[linePos
] = '\0';
1094 ColouriseErrorListLine(lineBuffer
, linePos
, i
, styler
, valueSeparate
);
1098 if (linePos
> 0) { // Last line does not have ending characters
1099 ColouriseErrorListLine(lineBuffer
, linePos
, startPos
+ length
- 1, styler
, valueSeparate
);
1103 static int isSpecial(char s
) {
1104 return (s
== '\\') || (s
== ',') || (s
== ';') || (s
== '\'') || (s
== ' ') ||
1105 (s
== '\"') || (s
== '`') || (s
== '^') || (s
== '~');
1108 static int isTag(int start
, Accessor
&styler
) {
1110 unsigned int i
= 0, e
= 1;
1111 while (i
< 5 && e
) {
1112 s
[i
] = styler
[start
+ i
];
1114 e
= styler
[start
+ i
] != '{';
1117 return (strcmp(s
, "begin") == 0) || (strcmp(s
, "end") == 0);
1120 static void ColouriseLatexDoc(unsigned int startPos
, int length
, int initStyle
,
1121 WordList
*[], Accessor
&styler
) {
1123 styler
.StartAt(startPos
);
1125 int state
= initStyle
;
1126 char chNext
= styler
[startPos
];
1127 styler
.StartSegment(startPos
);
1128 int lengthDoc
= startPos
+ length
;
1130 for (int i
= startPos
; i
< lengthDoc
; i
++) {
1132 chNext
= styler
.SafeGetCharAt(i
+ 1);
1134 if (styler
.IsLeadByte(ch
)) {
1135 chNext
= styler
.SafeGetCharAt(i
+ 2);
1140 case SCE_L_DEFAULT
:
1143 styler
.ColourTo(i
- 1, state
);
1144 if (isSpecial(styler
[i
+ 1])) {
1145 styler
.ColourTo(i
+ 1, SCE_L_COMMAND
);
1147 chNext
= styler
.SafeGetCharAt(i
+ 1);
1149 if (isTag(i
+ 1, styler
))
1152 state
= SCE_L_COMMAND
;
1156 styler
.ColourTo(i
- 1, state
);
1158 if (chNext
== '$') {
1160 chNext
= styler
.SafeGetCharAt(i
+ 1);
1164 styler
.ColourTo(i
- 1, state
);
1165 state
= SCE_L_COMMENT
;
1169 case SCE_L_COMMAND
:
1170 if (chNext
== '[' || chNext
== '{' || chNext
== '}' ||
1171 chNext
== ' ' || chNext
== '\r' || chNext
== '\n') {
1172 styler
.ColourTo(i
, state
);
1173 state
= SCE_L_DEFAULT
;
1175 chNext
= styler
.SafeGetCharAt(i
+ 1);
1180 styler
.ColourTo(i
, state
);
1181 state
= SCE_L_DEFAULT
;
1186 if (chNext
== '$') {
1188 chNext
= styler
.SafeGetCharAt(i
+ 1);
1190 styler
.ColourTo(i
, state
);
1191 state
= SCE_L_DEFAULT
;
1194 case SCE_L_COMMENT
:
1195 if (ch
== '\r' || ch
== '\n') {
1196 styler
.ColourTo(i
- 1, state
);
1197 state
= SCE_L_DEFAULT
;
1201 styler
.ColourTo(lengthDoc
-1, state
);
1204 static const char * const batchWordListDesc
[] = {
1205 "Internal Commands",
1206 "External Commands",
1210 static const char * const emptyWordListDesc
[] = {
1214 static void ColouriseNullDoc(unsigned int startPos
, int length
, int, WordList
*[],
1216 // Null language means all style bytes are 0 so just mark the end - no need to fill in.
1218 styler
.StartAt(startPos
+ length
- 1);
1219 styler
.StartSegment(startPos
+ length
- 1);
1220 styler
.ColourTo(startPos
+ length
- 1, 0);
1224 LexerModule
lmBatch(SCLEX_BATCH
, ColouriseBatchDoc
, "batch", 0, batchWordListDesc
);
1225 LexerModule
lmDiff(SCLEX_DIFF
, ColouriseDiffDoc
, "diff", FoldDiffDoc
, emptyWordListDesc
);
1226 LexerModule
lmPo(SCLEX_PO
, ColourisePoDoc
, "po", 0, emptyWordListDesc
);
1227 LexerModule
lmProps(SCLEX_PROPERTIES
, ColourisePropsDoc
, "props", FoldPropsDoc
, emptyWordListDesc
);
1228 LexerModule
lmMake(SCLEX_MAKEFILE
, ColouriseMakeDoc
, "makefile", 0, emptyWordListDesc
);
1229 LexerModule
lmErrorList(SCLEX_ERRORLIST
, ColouriseErrorListDoc
, "errorlist", 0, emptyWordListDesc
);
1230 LexerModule
lmLatex(SCLEX_LATEX
, ColouriseLatexDoc
, "latex", 0, emptyWordListDesc
);
1231 LexerModule
lmNull(SCLEX_NULL
, ColouriseNullDoc
, "null");