]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexOthers.cxx
75458f6d59ec3a7f1105bec9c5b3afd60a1c212c
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 inline bool AtEOL(Accessor
&styler
, unsigned int i
) {
41 return (styler
[i
] == '\n') ||
42 ((styler
[i
] == '\r') && (styler
.SafeGetCharAt(i
+ 1) != '\n'));
45 // Tests for BATCH Operators
46 static bool IsBOperator(char ch
) {
47 return (ch
== '=') || (ch
== '+') || (ch
== '>') || (ch
== '<') ||
48 (ch
== '|') || (ch
== '?') || (ch
== '*');
51 // Tests for BATCH Separators
52 static bool IsBSeparator(char ch
) {
53 return (ch
== '\\') || (ch
== '.') || (ch
== ';') ||
54 (ch
== '\"') || (ch
== '\'') || (ch
== '/') || (ch
== ')');
57 static void ColouriseBatchLine(
59 unsigned int lengthLine
,
60 unsigned int startLine
,
62 WordList
*keywordlists
[],
65 unsigned int offset
= 0; // Line Buffer Offset
66 unsigned int cmdLoc
; // External Command / Program Location
67 char wordBuffer
[81]; // Word Buffer - large to catch long paths
68 unsigned int wbl
; // Word Buffer Length
69 unsigned int wbo
; // Word Buffer Offset - also Special Keyword Buffer Length
70 WordList
&keywords
= *keywordlists
[0]; // Internal Commands
71 WordList
&keywords2
= *keywordlists
[1]; // External Commands (optional)
73 // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords
74 // Toggling Regular Keyword Checking off improves readability
75 // Other Regular Keywords and External Commands / Programs might also benefit from toggling
76 // Need a more robust algorithm to properly toggle Regular Keyword Checking
77 bool continueProcessing
= true; // Used to toggle Regular Keyword Checking
78 // Special Keywords are those that allow certain characters without whitespace after the command
79 // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path=
80 // Special Keyword Buffer used to determine if the first n characters is a Keyword
81 char sKeywordBuffer
[10]; // Special Keyword Buffer
82 bool sKeywordFound
; // Exit Special Keyword for-loop if found
84 // Skip initial spaces
85 while ((offset
< lengthLine
) && (isspacechar(lineBuffer
[offset
]))) {
88 // Colorize Default Text
89 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
90 // Set External Command / Program Location
93 // Check for Fake Label (Comment) or Real Label - return if found
94 if (lineBuffer
[offset
] == ':') {
95 if (lineBuffer
[offset
+ 1] == ':') {
96 // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
97 styler
.ColourTo(endPos
, SCE_BAT_COMMENT
);
99 // Colorize Real Label
100 styler
.ColourTo(endPos
, SCE_BAT_LABEL
);
103 // Check for Drive Change (Drive Change is internal command) - return if found
104 } else if ((isalpha(lineBuffer
[offset
])) &&
105 (lineBuffer
[offset
+ 1] == ':') &&
106 ((isspacechar(lineBuffer
[offset
+ 2])) ||
107 (((lineBuffer
[offset
+ 2] == '\\')) &&
108 (isspacechar(lineBuffer
[offset
+ 3]))))) {
109 // Colorize Regular Keyword
110 styler
.ColourTo(endPos
, SCE_BAT_WORD
);
114 // Check for Hide Command (@ECHO OFF/ON)
115 if (lineBuffer
[offset
] == '@') {
116 styler
.ColourTo(startLine
+ offset
, SCE_BAT_HIDE
);
120 while ((offset
< lengthLine
) && (isspacechar(lineBuffer
[offset
]))) {
124 // Read remainder of line word-at-a-time or remainder-of-word-at-a-time
125 while (offset
< lengthLine
) {
126 if (offset
> startLine
) {
127 // Colorize Default Text
128 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
130 // Copy word from Line Buffer into Word Buffer
132 for (; offset
< lengthLine
&& wbl
< 80 &&
133 !isspacechar(lineBuffer
[offset
]); wbl
++, offset
++) {
134 wordBuffer
[wbl
] = static_cast<char>(tolower(lineBuffer
[offset
]));
136 wordBuffer
[wbl
] = '\0';
139 // Check for Comment - return if found
140 if (CompareCaseInsensitive(wordBuffer
, "rem") == 0) {
141 styler
.ColourTo(endPos
, SCE_BAT_COMMENT
);
144 // Check for Separator
145 if (IsBSeparator(wordBuffer
[0])) {
146 // Check for External Command / Program
147 if ((cmdLoc
== offset
- wbl
) &&
148 ((wordBuffer
[0] == ':') ||
149 (wordBuffer
[0] == '\\') ||
150 (wordBuffer
[0] == '.'))) {
151 // Reset Offset to re-process remainder of word
153 // Colorize External Command / Program
155 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
156 } else if (keywords2
.InList(wordBuffer
)) {
157 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
159 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
161 // Reset External Command / Program Location
164 // Reset Offset to re-process remainder of word
166 // Colorize Default Text
167 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
169 // Check for Regular Keyword in list
170 } else if ((keywords
.InList(wordBuffer
)) &&
171 (continueProcessing
)) {
172 // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking
173 if ((CompareCaseInsensitive(wordBuffer
, "echo") == 0) ||
174 (CompareCaseInsensitive(wordBuffer
, "goto") == 0) ||
175 (CompareCaseInsensitive(wordBuffer
, "prompt") == 0) ||
176 (CompareCaseInsensitive(wordBuffer
, "set") == 0)) {
177 continueProcessing
= false;
179 // Identify External Command / Program Location for ERRORLEVEL, and EXIST
180 if ((CompareCaseInsensitive(wordBuffer
, "errorlevel") == 0) ||
181 (CompareCaseInsensitive(wordBuffer
, "exist") == 0)) {
182 // Reset External Command / Program Location
185 while ((cmdLoc
< lengthLine
) &&
186 (isspacechar(lineBuffer
[cmdLoc
]))) {
190 while ((cmdLoc
< lengthLine
) &&
191 (!isspacechar(lineBuffer
[cmdLoc
]))) {
195 while ((cmdLoc
< lengthLine
) &&
196 (isspacechar(lineBuffer
[cmdLoc
]))) {
199 // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH
200 } else if ((CompareCaseInsensitive(wordBuffer
, "call") == 0) ||
201 (CompareCaseInsensitive(wordBuffer
, "do") == 0) ||
202 (CompareCaseInsensitive(wordBuffer
, "loadhigh") == 0) ||
203 (CompareCaseInsensitive(wordBuffer
, "lh") == 0)) {
204 // Reset External Command / Program Location
207 while ((cmdLoc
< lengthLine
) &&
208 (isspacechar(lineBuffer
[cmdLoc
]))) {
212 // Colorize Regular keyword
213 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_WORD
);
214 // No need to Reset Offset
215 // Check for Special Keyword in list, External Command / Program, or Default Text
216 } else if ((wordBuffer
[0] != '%') &&
217 (wordBuffer
[0] != '!') &&
218 (!IsBOperator(wordBuffer
[0])) &&
219 (continueProcessing
)) {
220 // Check for Special Keyword
221 // Affected Commands are in Length range 2-6
222 // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected
223 sKeywordFound
= false;
224 for (unsigned int keywordLength
= 2; keywordLength
< wbl
&& keywordLength
< 7 && !sKeywordFound
; keywordLength
++) {
226 // Copy Keyword Length from Word Buffer into Special Keyword Buffer
227 for (; wbo
< keywordLength
; wbo
++) {
228 sKeywordBuffer
[wbo
] = static_cast<char>(wordBuffer
[wbo
]);
230 sKeywordBuffer
[wbo
] = '\0';
231 // Check for Special Keyword in list
232 if ((keywords
.InList(sKeywordBuffer
)) &&
233 ((IsBOperator(wordBuffer
[wbo
])) ||
234 (IsBSeparator(wordBuffer
[wbo
])))) {
235 sKeywordFound
= true;
236 // ECHO requires no further Regular Keyword Checking
237 if (CompareCaseInsensitive(sKeywordBuffer
, "echo") == 0) {
238 continueProcessing
= false;
240 // Colorize Special Keyword as Regular Keyword
241 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_WORD
);
242 // Reset Offset to re-process remainder of word
243 offset
-= (wbl
- wbo
);
246 // Check for External Command / Program or Default Text
247 if (!sKeywordFound
) {
249 // Check for External Command / Program
250 if (cmdLoc
== offset
- wbl
) {
251 // Read up to %, Operator or Separator
252 while ((wbo
< wbl
) &&
253 (wordBuffer
[wbo
] != '%') &&
254 (wordBuffer
[wbo
] != '!') &&
255 (!IsBOperator(wordBuffer
[wbo
])) &&
256 (!IsBSeparator(wordBuffer
[wbo
]))) {
259 // Reset External Command / Program Location
260 cmdLoc
= offset
- (wbl
- wbo
);
261 // Reset Offset to re-process remainder of word
262 offset
-= (wbl
- wbo
);
263 // CHOICE requires no further Regular Keyword Checking
264 if (CompareCaseInsensitive(wordBuffer
, "choice") == 0) {
265 continueProcessing
= false;
267 // Check for START (and its switches) - What follows is External Command \ Program
268 if (CompareCaseInsensitive(wordBuffer
, "start") == 0) {
269 // Reset External Command / Program Location
272 while ((cmdLoc
< lengthLine
) &&
273 (isspacechar(lineBuffer
[cmdLoc
]))) {
276 // Reset External Command / Program Location if command switch detected
277 if (lineBuffer
[cmdLoc
] == '/') {
278 // Skip command switch
279 while ((cmdLoc
< lengthLine
) &&
280 (!isspacechar(lineBuffer
[cmdLoc
]))) {
284 while ((cmdLoc
< lengthLine
) &&
285 (isspacechar(lineBuffer
[cmdLoc
]))) {
290 // Colorize External Command / Program
292 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
293 } else if (keywords2
.InList(wordBuffer
)) {
294 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_COMMAND
);
296 styler
.ColourTo(startLine
+ offset
- 1, SCE_BAT_DEFAULT
);
298 // No need to Reset Offset
299 // Check for Default Text
301 // Read up to %, Operator or Separator
302 while ((wbo
< wbl
) &&
303 (wordBuffer
[wbo
] != '%') &&
304 (wordBuffer
[wbo
] != '!') &&
305 (!IsBOperator(wordBuffer
[wbo
])) &&
306 (!IsBSeparator(wordBuffer
[wbo
]))) {
309 // Colorize Default Text
310 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_DEFAULT
);
311 // Reset Offset to re-process remainder of word
312 offset
-= (wbl
- wbo
);
315 // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a)
316 } else if (wordBuffer
[0] == '%') {
317 // Colorize Default Text
318 styler
.ColourTo(startLine
+ offset
- 1 - wbl
, SCE_BAT_DEFAULT
);
320 // Search to end of word for second % (can be a long path)
321 while ((wbo
< wbl
) &&
322 (wordBuffer
[wbo
] != '%') &&
323 (!IsBOperator(wordBuffer
[wbo
])) &&
324 (!IsBSeparator(wordBuffer
[wbo
]))) {
327 // Check for Argument (%n) or (%*)
328 if (((Is0To9(wordBuffer
[1])) || (wordBuffer
[1] == '*')) &&
329 (wordBuffer
[wbo
] != '%')) {
330 // Check for External Command / Program
331 if (cmdLoc
== offset
- wbl
) {
332 cmdLoc
= offset
- (wbl
- 2);
335 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 2), SCE_BAT_IDENTIFIER
);
336 // Reset Offset to re-process remainder of word
338 // Check for Expanded Argument (%~...) / Variable (%%~...)
339 } else if (((wbl
> 1) && (wordBuffer
[1] == '~')) ||
340 ((wbl
> 2) && (wordBuffer
[1] == '%') && (wordBuffer
[2] == '~'))) {
341 // Check for External Command / Program
342 if (cmdLoc
== offset
- wbl
) {
343 cmdLoc
= offset
- (wbl
- wbo
);
345 // Colorize Expanded Argument / Variable
346 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_IDENTIFIER
);
347 // Reset Offset to re-process remainder of word
348 offset
-= (wbl
- wbo
);
349 // Check for Environment Variable (%x...%)
350 } else if ((wordBuffer
[1] != '%') &&
351 (wordBuffer
[wbo
] == '%')) {
353 // Check for External Command / Program
354 if (cmdLoc
== offset
- wbl
) {
355 cmdLoc
= offset
- (wbl
- wbo
);
357 // Colorize Environment Variable
358 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_IDENTIFIER
);
359 // Reset Offset to re-process remainder of word
360 offset
-= (wbl
- wbo
);
361 // Check for Local Variable (%%a)
364 (wordBuffer
[1] == '%') &&
365 (wordBuffer
[2] != '%') &&
366 (!IsBOperator(wordBuffer
[2])) &&
367 (!IsBSeparator(wordBuffer
[2]))) {
368 // Check for External Command / Program
369 if (cmdLoc
== offset
- wbl
) {
370 cmdLoc
= offset
- (wbl
- 3);
372 // Colorize Local Variable
373 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 3), SCE_BAT_IDENTIFIER
);
374 // Reset Offset to re-process remainder of word
377 // Check for Environment Variable (!x...!)
378 } else if (wordBuffer
[0] == '!') {
379 // Colorize Default Text
380 styler
.ColourTo(startLine
+ offset
- 1 - wbl
, SCE_BAT_DEFAULT
);
382 // Search to end of word for second ! (can be a long path)
383 while ((wbo
< wbl
) &&
384 (wordBuffer
[wbo
] != '!') &&
385 (!IsBOperator(wordBuffer
[wbo
])) &&
386 (!IsBSeparator(wordBuffer
[wbo
]))) {
389 if (wordBuffer
[wbo
] == '!') {
391 // Check for External Command / Program
392 if (cmdLoc
== offset
- wbl
) {
393 cmdLoc
= offset
- (wbl
- wbo
);
395 // Colorize Environment Variable
396 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_IDENTIFIER
);
397 // Reset Offset to re-process remainder of word
398 offset
-= (wbl
- wbo
);
400 // Check for Operator
401 } else if (IsBOperator(wordBuffer
[0])) {
402 // Colorize Default Text
403 styler
.ColourTo(startLine
+ offset
- 1 - wbl
, SCE_BAT_DEFAULT
);
404 // Check for Comparison Operator
405 if ((wordBuffer
[0] == '=') && (wordBuffer
[1] == '=')) {
406 // Identify External Command / Program Location for IF
409 while ((cmdLoc
< lengthLine
) &&
410 (isspacechar(lineBuffer
[cmdLoc
]))) {
413 // Colorize Comparison Operator
414 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 2), SCE_BAT_OPERATOR
);
415 // Reset Offset to re-process remainder of word
417 // Check for Pipe Operator
418 } else if (wordBuffer
[0] == '|') {
419 // Reset External Command / Program Location
420 cmdLoc
= offset
- wbl
+ 1;
422 while ((cmdLoc
< lengthLine
) &&
423 (isspacechar(lineBuffer
[cmdLoc
]))) {
426 // Colorize Pipe Operator
427 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 1), SCE_BAT_OPERATOR
);
428 // Reset Offset to re-process remainder of word
430 // Check for Other Operator
432 // Check for > Operator
433 if (wordBuffer
[0] == '>') {
434 // Turn Keyword and External Command / Program checking back on
435 continueProcessing
= true;
437 // Colorize Other Operator
438 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- 1), SCE_BAT_OPERATOR
);
439 // Reset Offset to re-process remainder of word
442 // Check for Default Text
444 // Read up to %, Operator or Separator
445 while ((wbo
< wbl
) &&
446 (wordBuffer
[wbo
] != '%') &&
447 (wordBuffer
[wbo
] != '!') &&
448 (!IsBOperator(wordBuffer
[wbo
])) &&
449 (!IsBSeparator(wordBuffer
[wbo
]))) {
452 // Colorize Default Text
453 styler
.ColourTo(startLine
+ offset
- 1 - (wbl
- wbo
), SCE_BAT_DEFAULT
);
454 // Reset Offset to re-process remainder of word
455 offset
-= (wbl
- wbo
);
457 // Skip next spaces - nothing happens if Offset was Reset
458 while ((offset
< lengthLine
) && (isspacechar(lineBuffer
[offset
]))) {
462 // Colorize Default Text for remainder of line - currently not lexed
463 styler
.ColourTo(endPos
, SCE_BAT_DEFAULT
);
466 static void ColouriseBatchDoc(
467 unsigned int startPos
,
470 WordList
*keywordlists
[],
473 char lineBuffer
[1024];
475 styler
.StartAt(startPos
);
476 styler
.StartSegment(startPos
);
477 unsigned int linePos
= 0;
478 unsigned int startLine
= startPos
;
479 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
480 lineBuffer
[linePos
++] = styler
[i
];
481 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
482 // End of line (or of line buffer) met, colourise it
483 lineBuffer
[linePos
] = '\0';
484 ColouriseBatchLine(lineBuffer
, linePos
, startLine
, i
, keywordlists
, styler
);
489 if (linePos
> 0) { // Last line does not have ending characters
490 lineBuffer
[linePos
] = '\0';
491 ColouriseBatchLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1,
492 keywordlists
, styler
);
496 static void ColouriseDiffLine(char *lineBuffer
, int endLine
, Accessor
&styler
) {
497 // It is needed to remember the current state to recognize starting
498 // comment lines before the first "diff " or "--- ". If a real
499 // difference starts then each line starting with ' ' is a whitespace
500 // otherwise it is considered a comment (Only in..., Binary file...)
501 if (0 == strncmp(lineBuffer
, "diff ", 5)) {
502 styler
.ColourTo(endLine
, SCE_DIFF_COMMAND
);
503 } else if (0 == strncmp(lineBuffer
, "Index: ", 7)) { // For subversion's diff
504 styler
.ColourTo(endLine
, SCE_DIFF_COMMAND
);
505 } else if (0 == strncmp(lineBuffer
, "---", 3)) {
506 // In a context diff, --- appears in both the header and the position markers
507 if (lineBuffer
[3] == ' ' && atoi(lineBuffer
+ 4) && !strchr(lineBuffer
, '/'))
508 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
509 else if (lineBuffer
[3] == '\r' || lineBuffer
[3] == '\n')
510 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
512 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
513 } else if (0 == strncmp(lineBuffer
, "+++ ", 4)) {
514 // I don't know of any diff where "+++ " is a position marker, but for
515 // consistency, do the same as with "--- " and "*** ".
516 if (atoi(lineBuffer
+4) && !strchr(lineBuffer
, '/'))
517 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
519 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
520 } else if (0 == strncmp(lineBuffer
, "====", 4)) { // For p4's diff
521 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
522 } else if (0 == strncmp(lineBuffer
, "***", 3)) {
523 // In a context diff, *** appears in both the header and the position markers.
524 // Also ******** is a chunk header, but here it's treated as part of the
525 // position marker since there is no separate style for a chunk header.
526 if (lineBuffer
[3] == ' ' && atoi(lineBuffer
+4) && !strchr(lineBuffer
, '/'))
527 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
528 else if (lineBuffer
[3] == '*')
529 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
531 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
532 } else if (0 == strncmp(lineBuffer
, "? ", 2)) { // For difflib
533 styler
.ColourTo(endLine
, SCE_DIFF_HEADER
);
534 } else if (lineBuffer
[0] == '@') {
535 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
536 } else if (lineBuffer
[0] >= '0' && lineBuffer
[0] <= '9') {
537 styler
.ColourTo(endLine
, SCE_DIFF_POSITION
);
538 } else if (lineBuffer
[0] == '-' || lineBuffer
[0] == '<') {
539 styler
.ColourTo(endLine
, SCE_DIFF_DELETED
);
540 } else if (lineBuffer
[0] == '+' || lineBuffer
[0] == '>') {
541 styler
.ColourTo(endLine
, SCE_DIFF_ADDED
);
542 } else if (lineBuffer
[0] == '!') {
543 styler
.ColourTo(endLine
, SCE_DIFF_CHANGED
);
544 } else if (lineBuffer
[0] != ' ') {
545 styler
.ColourTo(endLine
, SCE_DIFF_COMMENT
);
547 styler
.ColourTo(endLine
, SCE_DIFF_DEFAULT
);
551 static void ColouriseDiffDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
552 char lineBuffer
[1024];
553 styler
.StartAt(startPos
);
554 styler
.StartSegment(startPos
);
555 unsigned int linePos
= 0;
556 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
557 lineBuffer
[linePos
++] = styler
[i
];
558 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
559 // End of line (or of line buffer) met, colourise it
560 lineBuffer
[linePos
] = '\0';
561 ColouriseDiffLine(lineBuffer
, i
, styler
);
565 if (linePos
> 0) { // Last line does not have ending characters
566 ColouriseDiffLine(lineBuffer
, startPos
+ length
- 1, styler
);
570 static void FoldDiffDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
571 int curLine
= styler
.GetLine(startPos
);
572 int curLineStart
= styler
.LineStart(curLine
);
573 int prevLevel
= curLine
> 0 ? styler
.LevelAt(curLine
- 1) : SC_FOLDLEVELBASE
;
577 int lineType
= styler
.StyleAt(curLineStart
);
578 if (lineType
== SCE_DIFF_COMMAND
)
579 nextLevel
= SC_FOLDLEVELBASE
| SC_FOLDLEVELHEADERFLAG
;
580 else if (lineType
== SCE_DIFF_HEADER
)
581 nextLevel
= (SC_FOLDLEVELBASE
+ 1) | SC_FOLDLEVELHEADERFLAG
;
582 else if (lineType
== SCE_DIFF_POSITION
&& styler
[curLineStart
] != '-')
583 nextLevel
= (SC_FOLDLEVELBASE
+ 2) | SC_FOLDLEVELHEADERFLAG
;
584 else if (prevLevel
& SC_FOLDLEVELHEADERFLAG
)
585 nextLevel
= (prevLevel
& SC_FOLDLEVELNUMBERMASK
) + 1;
587 nextLevel
= prevLevel
;
589 if ((nextLevel
& SC_FOLDLEVELHEADERFLAG
) && (nextLevel
== prevLevel
))
590 styler
.SetLevel(curLine
-1, prevLevel
& ~SC_FOLDLEVELHEADERFLAG
);
592 styler
.SetLevel(curLine
, nextLevel
);
593 prevLevel
= nextLevel
;
595 curLineStart
= styler
.LineStart(++curLine
);
596 } while (static_cast<int>(startPos
) + length
> curLineStart
);
599 static void ColourisePoLine(
601 unsigned int lengthLine
,
602 unsigned int startLine
,
607 static unsigned int state
= SCE_PO_DEFAULT
;
608 unsigned int state_start
= SCE_PO_DEFAULT
;
610 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) // Skip initial spaces
612 if (i
< lengthLine
) {
613 if (lineBuffer
[i
] == '#') {
614 // check if the comment contains any flags ("#, ") and
615 // then whether the flags contain "fuzzy"
616 if (strstart(lineBuffer
, "#, ") && strstr(lineBuffer
, "fuzzy"))
617 styler
.ColourTo(endPos
, SCE_PO_FUZZY
);
619 styler
.ColourTo(endPos
, SCE_PO_COMMENT
);
621 if (lineBuffer
[0] == '"') {
622 // line continuation, use previous style
623 styler
.ColourTo(endPos
, state
);
625 // this implicitly also matches "msgid_plural"
626 } else if (strstart(lineBuffer
, "msgid")) {
627 state_start
= SCE_PO_MSGID
;
628 state
= SCE_PO_MSGID_TEXT
;
629 } else if (strstart(lineBuffer
, "msgstr")) {
630 state_start
= SCE_PO_MSGSTR
;
631 state
= SCE_PO_MSGSTR_TEXT
;
632 } else if (strstart(lineBuffer
, "msgctxt")) {
633 state_start
= SCE_PO_MSGCTXT
;
634 state
= SCE_PO_MSGCTXT_TEXT
;
636 if (state_start
!= SCE_PO_DEFAULT
) {
637 // find the next space
638 while ((i
< lengthLine
) && ! isspacechar(lineBuffer
[i
]))
640 styler
.ColourTo(startLine
+ i
- 1, state_start
);
641 styler
.ColourTo(startLine
+ i
, SCE_PO_DEFAULT
);
642 styler
.ColourTo(endPos
, state
);
646 styler
.ColourTo(endPos
, SCE_PO_DEFAULT
);
650 static void ColourisePoDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
651 char lineBuffer
[1024];
652 styler
.StartAt(startPos
);
653 styler
.StartSegment(startPos
);
654 unsigned int linePos
= 0;
655 unsigned int startLine
= startPos
;
656 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
657 lineBuffer
[linePos
++] = styler
[i
];
658 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
659 // End of line (or of line buffer) met, colourise it
660 lineBuffer
[linePos
] = '\0';
661 ColourisePoLine(lineBuffer
, linePos
, startLine
, i
, styler
);
666 if (linePos
> 0) { // Last line does not have ending characters
667 ColourisePoLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
);
671 static inline bool isassignchar(unsigned char ch
) {
672 return (ch
== '=') || (ch
== ':');
675 static void ColourisePropsLine(
677 unsigned int lengthLine
,
678 unsigned int startLine
,
681 bool allowInitialSpaces
) {
684 if (allowInitialSpaces
) {
685 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) // Skip initial spaces
688 if (isspacechar(lineBuffer
[i
])) // don't allow initial spaces
692 if (i
< lengthLine
) {
693 if (lineBuffer
[i
] == '#' || lineBuffer
[i
] == '!' || lineBuffer
[i
] == ';') {
694 styler
.ColourTo(endPos
, SCE_PROPS_COMMENT
);
695 } else if (lineBuffer
[i
] == '[') {
696 styler
.ColourTo(endPos
, SCE_PROPS_SECTION
);
697 } else if (lineBuffer
[i
] == '@') {
698 styler
.ColourTo(startLine
+ i
, SCE_PROPS_DEFVAL
);
699 if (isassignchar(lineBuffer
[i
++]))
700 styler
.ColourTo(startLine
+ i
, SCE_PROPS_ASSIGNMENT
);
701 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
703 // Search for the '=' character
704 while ((i
< lengthLine
) && !isassignchar(lineBuffer
[i
]))
706 if ((i
< lengthLine
) && isassignchar(lineBuffer
[i
])) {
707 styler
.ColourTo(startLine
+ i
- 1, SCE_PROPS_KEY
);
708 styler
.ColourTo(startLine
+ i
, SCE_PROPS_ASSIGNMENT
);
709 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
711 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
715 styler
.ColourTo(endPos
, SCE_PROPS_DEFAULT
);
719 static void ColourisePropsDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
720 char lineBuffer
[1024];
721 styler
.StartAt(startPos
);
722 styler
.StartSegment(startPos
);
723 unsigned int linePos
= 0;
724 unsigned int startLine
= startPos
;
726 // property lexer.props.allow.initial.spaces
727 // For properties files, set to 0 to style all lines that start with whitespace in the default style.
728 // This is not suitable for SciTE .properties files which use indentation for flow control but
729 // can be used for RFC2822 text where indentation is used for continuation lines.
730 bool allowInitialSpaces
= styler
.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0;
732 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
733 lineBuffer
[linePos
++] = styler
[i
];
734 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
735 // End of line (or of line buffer) met, colourise it
736 lineBuffer
[linePos
] = '\0';
737 ColourisePropsLine(lineBuffer
, linePos
, startLine
, i
, styler
, allowInitialSpaces
);
742 if (linePos
> 0) { // Last line does not have ending characters
743 ColourisePropsLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
, allowInitialSpaces
);
747 // adaption by ksc, using the "} else {" trick of 1.53
749 static void FoldPropsDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
750 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
752 unsigned int endPos
= startPos
+ length
;
753 int visibleChars
= 0;
754 int lineCurrent
= styler
.GetLine(startPos
);
756 char chNext
= styler
[startPos
];
757 int styleNext
= styler
.StyleAt(startPos
);
758 bool headerPoint
= false;
761 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
763 chNext
= styler
[i
+1];
765 int style
= styleNext
;
766 styleNext
= styler
.StyleAt(i
+ 1);
767 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
769 if (style
== SCE_PROPS_SECTION
) {
774 lev
= SC_FOLDLEVELBASE
;
776 if (lineCurrent
> 0) {
777 int levelPrevious
= styler
.LevelAt(lineCurrent
- 1);
779 if (levelPrevious
& SC_FOLDLEVELHEADERFLAG
) {
780 lev
= SC_FOLDLEVELBASE
+ 1;
782 lev
= levelPrevious
& SC_FOLDLEVELNUMBERMASK
;
787 lev
= SC_FOLDLEVELBASE
;
789 if (visibleChars
== 0 && foldCompact
)
790 lev
|= SC_FOLDLEVELWHITEFLAG
;
793 lev
|= SC_FOLDLEVELHEADERFLAG
;
795 if (lev
!= styler
.LevelAt(lineCurrent
)) {
796 styler
.SetLevel(lineCurrent
, lev
);
803 if (!isspacechar(ch
))
807 if (lineCurrent
> 0) {
808 int levelPrevious
= styler
.LevelAt(lineCurrent
- 1);
809 if (levelPrevious
& SC_FOLDLEVELHEADERFLAG
) {
810 lev
= SC_FOLDLEVELBASE
+ 1;
812 lev
= levelPrevious
& SC_FOLDLEVELNUMBERMASK
;
815 lev
= SC_FOLDLEVELBASE
;
817 int flagsNext
= styler
.LevelAt(lineCurrent
);
818 styler
.SetLevel(lineCurrent
, lev
| (flagsNext
& ~SC_FOLDLEVELNUMBERMASK
));
821 static void ColouriseMakeLine(
823 unsigned int lengthLine
,
824 unsigned int startLine
,
829 int lastNonSpace
= -1;
830 unsigned int state
= SCE_MAKE_DEFAULT
;
831 bool bSpecial
= false;
833 // check for a tab character in column 0 indicating a command
834 bool bCommand
= false;
835 if ((lengthLine
> 0) && (lineBuffer
[0] == '\t'))
838 // Skip initial spaces
839 while ((i
< lengthLine
) && isspacechar(lineBuffer
[i
])) {
842 if (lineBuffer
[i
] == '#') { // Comment
843 styler
.ColourTo(endPos
, SCE_MAKE_COMMENT
);
846 if (lineBuffer
[i
] == '!') { // Special directive
847 styler
.ColourTo(endPos
, SCE_MAKE_PREPROCESSOR
);
850 while (i
< lengthLine
) {
851 if (lineBuffer
[i
] == '$' && lineBuffer
[i
+ 1] == '(') {
852 styler
.ColourTo(startLine
+ i
- 1, state
);
853 state
= SCE_MAKE_IDENTIFIER
;
854 } else if (state
== SCE_MAKE_IDENTIFIER
&& lineBuffer
[i
] == ')') {
855 styler
.ColourTo(startLine
+ i
, state
);
856 state
= SCE_MAKE_DEFAULT
;
859 // skip identifier and target styling if this is a command line
860 if (!bSpecial
&& !bCommand
) {
861 if (lineBuffer
[i
] == ':') {
862 if (((i
+ 1) < lengthLine
) && (lineBuffer
[i
+ 1] == '=')) {
863 // it's a ':=', so style as an identifier
864 if (lastNonSpace
>= 0)
865 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
866 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
867 styler
.ColourTo(startLine
+ i
+ 1, SCE_MAKE_OPERATOR
);
869 // We should check that no colouring was made since the beginning of the line,
870 // to avoid colouring stuff like /OUT:file
871 if (lastNonSpace
>= 0)
872 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_TARGET
);
873 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
874 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
876 bSpecial
= true; // Only react to the first ':' of the line
877 state
= SCE_MAKE_DEFAULT
;
878 } else if (lineBuffer
[i
] == '=') {
879 if (lastNonSpace
>= 0)
880 styler
.ColourTo(startLine
+ lastNonSpace
, SCE_MAKE_IDENTIFIER
);
881 styler
.ColourTo(startLine
+ i
- 1, SCE_MAKE_DEFAULT
);
882 styler
.ColourTo(startLine
+ i
, SCE_MAKE_OPERATOR
);
883 bSpecial
= true; // Only react to the first '=' of the line
884 state
= SCE_MAKE_DEFAULT
;
887 if (!isspacechar(lineBuffer
[i
])) {
892 if (state
== SCE_MAKE_IDENTIFIER
) {
893 styler
.ColourTo(endPos
, SCE_MAKE_IDEOL
); // Error, variable reference not ended
895 styler
.ColourTo(endPos
, SCE_MAKE_DEFAULT
);
899 static void ColouriseMakeDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
900 char lineBuffer
[1024];
901 styler
.StartAt(startPos
);
902 styler
.StartSegment(startPos
);
903 unsigned int linePos
= 0;
904 unsigned int startLine
= startPos
;
905 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
906 lineBuffer
[linePos
++] = styler
[i
];
907 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
908 // End of line (or of line buffer) met, colourise it
909 lineBuffer
[linePos
] = '\0';
910 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, i
, styler
);
915 if (linePos
> 0) { // Last line does not have ending characters
916 ColouriseMakeLine(lineBuffer
, linePos
, startLine
, startPos
+ length
- 1, styler
);
920 static int RecogniseErrorListLine(const char *lineBuffer
, unsigned int lengthLine
, int &startValue
) {
921 if (lineBuffer
[0] == '>') {
922 // Command or return status
924 } else if (lineBuffer
[0] == '<') {
925 // Diff removal, but not interested. Trapped to avoid hitting CTAG cases.
926 return SCE_ERR_DEFAULT
;
927 } else if (lineBuffer
[0] == '!') {
928 return SCE_ERR_DIFF_CHANGED
;
929 } else if (lineBuffer
[0] == '+') {
930 if (strstart(lineBuffer
, "+++ ")) {
931 return SCE_ERR_DIFF_MESSAGE
;
933 return SCE_ERR_DIFF_ADDITION
;
935 } else if (lineBuffer
[0] == '-') {
936 if (strstart(lineBuffer
, "--- ")) {
937 return SCE_ERR_DIFF_MESSAGE
;
939 return SCE_ERR_DIFF_DELETION
;
941 } else if (strstart(lineBuffer
, "cf90-")) {
942 // Absoft Pro Fortran 90/95 v8.2 error and/or warning message
944 } else if (strstart(lineBuffer
, "fortcom:")) {
945 // Intel Fortran Compiler v8.0 error/warning message
946 return SCE_ERR_IFORT
;
947 } else if (strstr(lineBuffer
, "File \"") && strstr(lineBuffer
, ", line ")) {
948 return SCE_ERR_PYTHON
;
949 } else if (strstr(lineBuffer
, " in ") && strstr(lineBuffer
, " on line ")) {
951 } else if ((strstart(lineBuffer
, "Error ") ||
952 strstart(lineBuffer
, "Warning ")) &&
953 strstr(lineBuffer
, " at (") &&
954 strstr(lineBuffer
, ") : ") &&
955 (strstr(lineBuffer
, " at (") < strstr(lineBuffer
, ") : "))) {
956 // Intel Fortran Compiler error/warning message
958 } else if (strstart(lineBuffer
, "Error ")) {
959 // Borland error message
960 return SCE_ERR_BORLAND
;
961 } else if (strstart(lineBuffer
, "Warning ")) {
962 // Borland warning message
963 return SCE_ERR_BORLAND
;
964 } else if (strstr(lineBuffer
, "at line " ) &&
965 (strstr(lineBuffer
, "at line " ) < (lineBuffer
+ lengthLine
)) &&
966 strstr(lineBuffer
, "file ") &&
967 (strstr(lineBuffer
, "file ") < (lineBuffer
+ lengthLine
))) {
968 // Lua 4 error message
970 } else if (strstr(lineBuffer
, " at " ) &&
971 (strstr(lineBuffer
, " at " ) < (lineBuffer
+ lengthLine
)) &&
972 strstr(lineBuffer
, " line ") &&
973 (strstr(lineBuffer
, " line ") < (lineBuffer
+ lengthLine
)) &&
974 (strstr(lineBuffer
, " at " ) < (strstr(lineBuffer
, " line ")))) {
975 // perl error message
977 } else if ((memcmp(lineBuffer
, " at ", 6) == 0) &&
978 strstr(lineBuffer
, ":line ")) {
981 } else if (strstart(lineBuffer
, "Line ") &&
982 strstr(lineBuffer
, ", file ")) {
983 // Essential Lahey Fortran error message
985 } else if (strstart(lineBuffer
, "line ") &&
986 strstr(lineBuffer
, " column ")) {
987 // HTML tidy style: line 42 column 1
989 } else if (strstart(lineBuffer
, "\tat ") &&
990 strstr(lineBuffer
, "(") &&
991 strstr(lineBuffer
, ".java:")) {
992 // Java stack back trace
993 return SCE_ERR_JAVA_STACK
;
995 // Look for one of the following formats:
996 // GCC: <filename>:<line>:<message>
997 // Microsoft: <filename>(<line>) :<message>
998 // Common: <filename>(<line>): warning|error|note|remark|catastrophic|fatal
999 // Common: <filename>(<line>) warning|error|note|remark|catastrophic|fatal
1000 // Microsoft: <filename>(<line>,<column>)<message>
1001 // CTags: \t<message>
1002 // Lua 5 traceback: \t<filename>:<line>:<message>
1003 // Lua 5.1: <exe>: <filename>:<line>:<message>
1004 bool initialTab
= (lineBuffer
[0] == '\t');
1005 bool initialColonPart
= false;
1007 stGccStart
, stGccDigit
, stGcc
,
1008 stMsStart
, stMsDigit
, stMsBracket
, stMsVc
, stMsDigitComma
, stMsDotNet
,
1009 stCtagsStart
, stCtagsStartString
, stCtagsStringDollar
, stCtags
,
1011 } state
= stInitial
;
1012 for (unsigned int i
= 0; i
< lengthLine
; i
++) {
1013 char ch
= lineBuffer
[i
];
1015 if ((i
+ 1) < lengthLine
)
1016 chNext
= lineBuffer
[i
+ 1];
1017 if (state
== stInitial
) {
1019 // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix)
1020 if ((chNext
!= '\\') && (chNext
!= '/') && (chNext
!= ' ')) {
1021 // This check is not completely accurate as may be on
1022 // GTK+ with a file name that includes ':'.
1024 } else if (chNext
== ' ') { // indicates a Lua 5.1 error message
1025 initialColonPart
= true;
1027 } else if ((ch
== '(') && Is1To9(chNext
) && (!initialTab
)) {
1029 // Check against '0' often removes phone numbers
1031 } else if ((ch
== '\t') && (!initialTab
)) {
1033 state
= stCtagsStart
;
1035 } else if (state
== stGccStart
) { // <filename>:
1036 state
= Is1To9(ch
) ? stGccDigit
: stUnrecognized
;
1037 } else if (state
== stGccDigit
) { // <filename>:<line>
1039 state
= stGcc
; // :9.*: is GCC
1042 } else if (!Is0To9(ch
)) {
1043 state
= stUnrecognized
;
1045 } else if (state
== stMsStart
) { // <filename>(
1046 state
= Is0To9(ch
) ? stMsDigit
: stUnrecognized
;
1047 } else if (state
== stMsDigit
) { // <filename>(<line>
1049 state
= stMsDigitComma
;
1050 } else if (ch
== ')') {
1051 state
= stMsBracket
;
1052 } else if ((ch
!= ' ') && !Is0To9(ch
)) {
1053 state
= stUnrecognized
;
1055 } else if (state
== stMsBracket
) { // <filename>(<line>)
1056 if ((ch
== ' ') && (chNext
== ':')) {
1058 } else if ((ch
== ':' && chNext
== ' ') || (ch
== ' ')) {
1059 // Possibly Delphi.. don't test against chNext as it's one of the strings below.
1061 unsigned int j
, chPos
;
1065 numstep
= 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i.
1067 numstep
= 2; // otherwise add 2.
1068 for (j
= i
+ numstep
; j
< lengthLine
&& isalpha(lineBuffer
[j
]) && chPos
< sizeof(word
) - 1; j
++)
1069 word
[chPos
++] = lineBuffer
[j
];
1071 if (!CompareCaseInsensitive(word
, "error") || !CompareCaseInsensitive(word
, "warning") ||
1072 !CompareCaseInsensitive(word
, "fatal") || !CompareCaseInsensitive(word
, "catastrophic") ||
1073 !CompareCaseInsensitive(word
, "note") || !CompareCaseInsensitive(word
, "remark")) {
1076 state
= stUnrecognized
;
1078 state
= stUnrecognized
;
1080 } else if (state
== stMsDigitComma
) { // <filename>(<line>,
1084 } else if ((ch
!= ' ') && !Is0To9(ch
)) {
1085 state
= stUnrecognized
;
1087 } else if (state
== stCtagsStart
) {
1088 if ((lineBuffer
[i
- 1] == '\t') &&
1089 ((ch
== '/' && lineBuffer
[i
+ 1] == '^') || Is0To9(ch
))) {
1092 } else if ((ch
== '/') && (lineBuffer
[i
+ 1] == '^')) {
1093 state
= stCtagsStartString
;
1095 } else if ((state
== stCtagsStartString
) && ((lineBuffer
[i
] == '$') && (lineBuffer
[i
+ 1] == '/'))) {
1096 state
= stCtagsStringDollar
;
1100 if (state
== stGcc
) {
1101 return initialColonPart
? SCE_ERR_LUA
: SCE_ERR_GCC
;
1102 } else if ((state
== stMsVc
) || (state
== stMsDotNet
)) {
1104 } else if ((state
== stCtagsStringDollar
) || (state
== stCtags
)) {
1105 return SCE_ERR_CTAG
;
1107 return SCE_ERR_DEFAULT
;
1112 static void ColouriseErrorListLine(
1114 unsigned int lengthLine
,
1115 unsigned int endPos
,
1117 bool valueSeparate
) {
1118 int startValue
= -1;
1119 int style
= RecogniseErrorListLine(lineBuffer
, lengthLine
, startValue
);
1120 if (valueSeparate
&& (startValue
>= 0)) {
1121 styler
.ColourTo(endPos
- (lengthLine
- startValue
), style
);
1122 styler
.ColourTo(endPos
, SCE_ERR_VALUE
);
1124 styler
.ColourTo(endPos
, style
);
1128 static void ColouriseErrorListDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
) {
1129 char lineBuffer
[10000];
1130 styler
.StartAt(startPos
);
1131 styler
.StartSegment(startPos
);
1132 unsigned int linePos
= 0;
1134 // property lexer.errorlist.value.separate
1135 // For lines in the output pane that are matches from Find in Files or GCC-style
1136 // diagnostics, style the path and line number separately from the rest of the
1137 // line with style 21 used for the rest of the line.
1138 // This allows matched text to be more easily distinguished from its location.
1139 bool valueSeparate
= styler
.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0;
1140 for (unsigned int i
= startPos
; i
< startPos
+ length
; i
++) {
1141 lineBuffer
[linePos
++] = styler
[i
];
1142 if (AtEOL(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
1143 // End of line (or of line buffer) met, colourise it
1144 lineBuffer
[linePos
] = '\0';
1145 ColouriseErrorListLine(lineBuffer
, linePos
, i
, styler
, valueSeparate
);
1149 if (linePos
> 0) { // Last line does not have ending characters
1150 ColouriseErrorListLine(lineBuffer
, linePos
, startPos
+ length
- 1, styler
, valueSeparate
);
1154 static int isSpecial(char s
) {
1155 return (s
== '\\') || (s
== ',') || (s
== ';') || (s
== '\'') || (s
== ' ') ||
1156 (s
== '\"') || (s
== '`') || (s
== '^') || (s
== '~');
1159 static int isTag(int start
, Accessor
&styler
) {
1161 unsigned int i
= 0, e
= 1;
1162 while (i
< 5 && e
) {
1163 s
[i
] = styler
[start
+ i
];
1165 e
= styler
[start
+ i
] != '{';
1168 return (strcmp(s
, "begin") == 0) || (strcmp(s
, "end") == 0);
1171 static void ColouriseLatexDoc(unsigned int startPos
, int length
, int initStyle
,
1172 WordList
*[], Accessor
&styler
) {
1174 styler
.StartAt(startPos
);
1176 int state
= initStyle
;
1177 char chNext
= styler
[startPos
];
1178 styler
.StartSegment(startPos
);
1179 int lengthDoc
= startPos
+ length
;
1181 for (int i
= startPos
; i
< lengthDoc
; i
++) {
1183 chNext
= styler
.SafeGetCharAt(i
+ 1);
1185 if (styler
.IsLeadByte(ch
)) {
1186 chNext
= styler
.SafeGetCharAt(i
+ 2);
1191 case SCE_L_DEFAULT
:
1194 styler
.ColourTo(i
- 1, state
);
1195 if (isSpecial(styler
[i
+ 1])) {
1196 styler
.ColourTo(i
+ 1, SCE_L_COMMAND
);
1198 chNext
= styler
.SafeGetCharAt(i
+ 1);
1200 if (isTag(i
+ 1, styler
))
1203 state
= SCE_L_COMMAND
;
1207 styler
.ColourTo(i
- 1, state
);
1209 if (chNext
== '$') {
1211 chNext
= styler
.SafeGetCharAt(i
+ 1);
1215 styler
.ColourTo(i
- 1, state
);
1216 state
= SCE_L_COMMENT
;
1220 case SCE_L_COMMAND
:
1221 if (chNext
== '[' || chNext
== '{' || chNext
== '}' ||
1222 chNext
== ' ' || chNext
== '\r' || chNext
== '\n') {
1223 styler
.ColourTo(i
, state
);
1224 state
= SCE_L_DEFAULT
;
1226 chNext
= styler
.SafeGetCharAt(i
+ 1);
1231 styler
.ColourTo(i
, state
);
1232 state
= SCE_L_DEFAULT
;
1237 if (chNext
== '$') {
1239 chNext
= styler
.SafeGetCharAt(i
+ 1);
1241 styler
.ColourTo(i
, state
);
1242 state
= SCE_L_DEFAULT
;
1245 case SCE_L_COMMENT
:
1246 if (ch
== '\r' || ch
== '\n') {
1247 styler
.ColourTo(i
- 1, state
);
1248 state
= SCE_L_DEFAULT
;
1252 styler
.ColourTo(lengthDoc
-1, state
);
1255 static const char * const batchWordListDesc
[] = {
1256 "Internal Commands",
1257 "External Commands",
1261 static const char * const emptyWordListDesc
[] = {
1265 static void ColouriseNullDoc(unsigned int startPos
, int length
, int, WordList
*[],
1267 // Null language means all style bytes are 0 so just mark the end - no need to fill in.
1269 styler
.StartAt(startPos
+ length
- 1);
1270 styler
.StartSegment(startPos
+ length
- 1);
1271 styler
.ColourTo(startPos
+ length
- 1, 0);
1275 LexerModule
lmBatch(SCLEX_BATCH
, ColouriseBatchDoc
, "batch", 0, batchWordListDesc
);
1276 LexerModule
lmDiff(SCLEX_DIFF
, ColouriseDiffDoc
, "diff", FoldDiffDoc
, emptyWordListDesc
);
1277 LexerModule
lmPo(SCLEX_PO
, ColourisePoDoc
, "po", 0, emptyWordListDesc
);
1278 LexerModule
lmProps(SCLEX_PROPERTIES
, ColourisePropsDoc
, "props", FoldPropsDoc
, emptyWordListDesc
);
1279 LexerModule
lmMake(SCLEX_MAKEFILE
, ColouriseMakeDoc
, "makefile", 0, emptyWordListDesc
);
1280 LexerModule
lmErrorList(SCLEX_ERRORLIST
, ColouriseErrorListDoc
, "errorlist", 0, emptyWordListDesc
);
1281 LexerModule
lmLatex(SCLEX_LATEX
, ColouriseLatexDoc
, "latex", 0, emptyWordListDesc
);
1282 LexerModule
lmNull(SCLEX_NULL
, ColouriseNullDoc
, "null");