]>
Commit | Line | Data |
---|---|---|
65ec6247 RD |
1 | // Scintilla source code edit control |
2 | /** @file LexOthers.cxx | |
3 | ** Lexers for batch files, diff results, properties files, make files and error lists. | |
4 | ** Also lexer for LaTeX documents. | |
5 | **/ | |
6 | // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> | |
f6bcfd97 BP |
7 | // The License.txt file describes the conditions under which this software may be distributed. |
8 | ||
65ec6247 RD |
9 | #include <stdlib.h> |
10 | #include <string.h> | |
65ec6247 RD |
11 | #include <stdio.h> |
12 | #include <stdarg.h> | |
1dcf666d RD |
13 | #include <assert.h> |
14 | #include <ctype.h> | |
f6bcfd97 | 15 | |
1dcf666d | 16 | #include "ILexer.h" |
f6bcfd97 BP |
17 | #include "Scintilla.h" |
18 | #include "SciLexer.h" | |
19 | ||
1dcf666d RD |
20 | #include "WordList.h" |
21 | #include "LexAccessor.h" | |
22 | #include "Accessor.h" | |
23 | #include "StyleContext.h" | |
24 | #include "CharacterSet.h" | |
25 | #include "LexerModule.h" | |
26 | ||
7e0c58e9 RD |
27 | #ifdef SCI_NAMESPACE |
28 | using namespace Scintilla; | |
29 | #endif | |
30 | ||
9e96e16f RD |
31 | static bool strstart(const char *haystack, const char *needle) { |
32 | return strncmp(haystack, needle, strlen(needle)) == 0; | |
33 | } | |
34 | ||
9e730a78 RD |
35 | static bool Is0To9(char ch) { |
36 | return (ch >= '0') && (ch <= '9'); | |
37 | } | |
38 | ||
39 | static bool Is1To9(char ch) { | |
40 | return (ch >= '1') && (ch <= '9'); | |
41 | } | |
42 | ||
1dcf666d RD |
43 | static bool IsAlphabetic(int ch) { |
44 | return isascii(ch) && isalpha(ch); | |
45 | } | |
46 | ||
1a2fb4cd RD |
47 | static inline bool AtEOL(Accessor &styler, unsigned int i) { |
48 | return (styler[i] == '\n') || | |
1e9bafca RD |
49 | ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); |
50 | } | |
51 | ||
52 | // Tests for BATCH Operators | |
53 | static bool IsBOperator(char ch) { | |
54 | return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') || | |
55 | (ch == '|') || (ch == '?') || (ch == '*'); | |
56 | } | |
57 | ||
58 | // Tests for BATCH Separators | |
59 | static bool IsBSeparator(char ch) { | |
b8193d80 | 60 | return (ch == '\\') || (ch == '.') || (ch == ';') || |
1dcf666d | 61 | (ch == '\"') || (ch == '\'') || (ch == '/'); |
1a2fb4cd RD |
62 | } |
63 | ||
65ec6247 RD |
64 | static void ColouriseBatchLine( |
65 | char *lineBuffer, | |
66 | unsigned int lengthLine, | |
67 | unsigned int startLine, | |
68 | unsigned int endPos, | |
b8193d80 | 69 | WordList *keywordlists[], |
65ec6247 RD |
70 | Accessor &styler) { |
71 | ||
1e9bafca | 72 | unsigned int offset = 0; // Line Buffer Offset |
1e9bafca RD |
73 | unsigned int cmdLoc; // External Command / Program Location |
74 | char wordBuffer[81]; // Word Buffer - large to catch long paths | |
75 | unsigned int wbl; // Word Buffer Length | |
76 | unsigned int wbo; // Word Buffer Offset - also Special Keyword Buffer Length | |
b8193d80 RD |
77 | WordList &keywords = *keywordlists[0]; // Internal Commands |
78 | WordList &keywords2 = *keywordlists[1]; // External Commands (optional) | |
79 | ||
1e9bafca RD |
80 | // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords |
81 | // Toggling Regular Keyword Checking off improves readability | |
82 | // Other Regular Keywords and External Commands / Programs might also benefit from toggling | |
83 | // Need a more robust algorithm to properly toggle Regular Keyword Checking | |
84 | bool continueProcessing = true; // Used to toggle Regular Keyword Checking | |
85 | // Special Keywords are those that allow certain characters without whitespace after the command | |
86 | // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path= | |
87 | // Special Keyword Buffer used to determine if the first n characters is a Keyword | |
88 | char sKeywordBuffer[10]; // Special Keyword Buffer | |
89 | bool sKeywordFound; // Exit Special Keyword for-loop if found | |
65ec6247 | 90 | |
1e9bafca RD |
91 | // Skip initial spaces |
92 | while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { | |
93 | offset++; | |
65ec6247 | 94 | } |
1e9bafca RD |
95 | // Colorize Default Text |
96 | styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); | |
97 | // Set External Command / Program Location | |
98 | cmdLoc = offset; | |
99 | ||
100 | // Check for Fake Label (Comment) or Real Label - return if found | |
101 | if (lineBuffer[offset] == ':') { | |
102 | if (lineBuffer[offset + 1] == ':') { | |
103 | // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm | |
65ec6247 | 104 | styler.ColourTo(endPos, SCE_BAT_COMMENT); |
1e9bafca RD |
105 | } else { |
106 | // Colorize Real Label | |
65ec6247 RD |
107 | styler.ColourTo(endPos, SCE_BAT_LABEL); |
108 | } | |
1e9bafca RD |
109 | return; |
110 | // Check for Drive Change (Drive Change is internal command) - return if found | |
1dcf666d | 111 | } else if ((IsAlphabetic(lineBuffer[offset])) && |
1e9bafca RD |
112 | (lineBuffer[offset + 1] == ':') && |
113 | ((isspacechar(lineBuffer[offset + 2])) || | |
114 | (((lineBuffer[offset + 2] == '\\')) && | |
115 | (isspacechar(lineBuffer[offset + 3]))))) { | |
116 | // Colorize Regular Keyword | |
117 | styler.ColourTo(endPos, SCE_BAT_WORD); | |
118 | return; | |
119 | } | |
120 | ||
121 | // Check for Hide Command (@ECHO OFF/ON) | |
122 | if (lineBuffer[offset] == '@') { | |
123 | styler.ColourTo(startLine + offset, SCE_BAT_HIDE); | |
124 | offset++; | |
1e9bafca RD |
125 | } |
126 | // Skip next spaces | |
127 | while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { | |
128 | offset++; | |
129 | } | |
130 | ||
131 | // Read remainder of line word-at-a-time or remainder-of-word-at-a-time | |
132 | while (offset < lengthLine) { | |
133 | if (offset > startLine) { | |
134 | // Colorize Default Text | |
135 | styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); | |
136 | } | |
137 | // Copy word from Line Buffer into Word Buffer | |
138 | wbl = 0; | |
139 | for (; offset < lengthLine && wbl < 80 && | |
65ec6247 RD |
140 | !isspacechar(lineBuffer[offset]); wbl++, offset++) { |
141 | wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset])); | |
142 | } | |
143 | wordBuffer[wbl] = '\0'; | |
1e9bafca RD |
144 | wbo = 0; |
145 | ||
146 | // Check for Comment - return if found | |
65ec6247 RD |
147 | if (CompareCaseInsensitive(wordBuffer, "rem") == 0) { |
148 | styler.ColourTo(endPos, SCE_BAT_COMMENT); | |
1e9bafca | 149 | return; |
65ec6247 | 150 | } |
1e9bafca RD |
151 | // Check for Separator |
152 | if (IsBSeparator(wordBuffer[0])) { | |
153 | // Check for External Command / Program | |
154 | if ((cmdLoc == offset - wbl) && | |
155 | ((wordBuffer[0] == ':') || | |
156 | (wordBuffer[0] == '\\') || | |
157 | (wordBuffer[0] == '.'))) { | |
158 | // Reset Offset to re-process remainder of word | |
159 | offset -= (wbl - 1); | |
160 | // Colorize External Command / Program | |
b8193d80 RD |
161 | if (!keywords2) { |
162 | styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); | |
163 | } else if (keywords2.InList(wordBuffer)) { | |
164 | styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); | |
165 | } else { | |
166 | styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); | |
167 | } | |
1e9bafca RD |
168 | // Reset External Command / Program Location |
169 | cmdLoc = offset; | |
170 | } else { | |
171 | // Reset Offset to re-process remainder of word | |
172 | offset -= (wbl - 1); | |
173 | // Colorize Default Text | |
174 | styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); | |
175 | } | |
176 | // Check for Regular Keyword in list | |
177 | } else if ((keywords.InList(wordBuffer)) && | |
178 | (continueProcessing)) { | |
1e9bafca RD |
179 | // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking |
180 | if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) || | |
181 | (CompareCaseInsensitive(wordBuffer, "goto") == 0) || | |
182 | (CompareCaseInsensitive(wordBuffer, "prompt") == 0) || | |
183 | (CompareCaseInsensitive(wordBuffer, "set") == 0)) { | |
184 | continueProcessing = false; | |
185 | } | |
186 | // Identify External Command / Program Location for ERRORLEVEL, and EXIST | |
187 | if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) || | |
188 | (CompareCaseInsensitive(wordBuffer, "exist") == 0)) { | |
189 | // Reset External Command / Program Location | |
190 | cmdLoc = offset; | |
191 | // Skip next spaces | |
192 | while ((cmdLoc < lengthLine) && | |
193 | (isspacechar(lineBuffer[cmdLoc]))) { | |
194 | cmdLoc++; | |
195 | } | |
196 | // Skip comparison | |
197 | while ((cmdLoc < lengthLine) && | |
198 | (!isspacechar(lineBuffer[cmdLoc]))) { | |
199 | cmdLoc++; | |
200 | } | |
201 | // Skip next spaces | |
202 | while ((cmdLoc < lengthLine) && | |
203 | (isspacechar(lineBuffer[cmdLoc]))) { | |
204 | cmdLoc++; | |
205 | } | |
206 | // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH | |
207 | } else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) || | |
208 | (CompareCaseInsensitive(wordBuffer, "do") == 0) || | |
209 | (CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) || | |
210 | (CompareCaseInsensitive(wordBuffer, "lh") == 0)) { | |
211 | // Reset External Command / Program Location | |
212 | cmdLoc = offset; | |
213 | // Skip next spaces | |
214 | while ((cmdLoc < lengthLine) && | |
215 | (isspacechar(lineBuffer[cmdLoc]))) { | |
216 | cmdLoc++; | |
217 | } | |
218 | } | |
219 | // Colorize Regular keyword | |
220 | styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD); | |
221 | // No need to Reset Offset | |
222 | // Check for Special Keyword in list, External Command / Program, or Default Text | |
223 | } else if ((wordBuffer[0] != '%') && | |
9e96e16f | 224 | (wordBuffer[0] != '!') && |
1e9bafca RD |
225 | (!IsBOperator(wordBuffer[0])) && |
226 | (continueProcessing)) { | |
227 | // Check for Special Keyword | |
228 | // Affected Commands are in Length range 2-6 | |
229 | // Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected | |
230 | sKeywordFound = false; | |
231 | for (unsigned int keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) { | |
232 | wbo = 0; | |
233 | // Copy Keyword Length from Word Buffer into Special Keyword Buffer | |
234 | for (; wbo < keywordLength; wbo++) { | |
235 | sKeywordBuffer[wbo] = static_cast<char>(wordBuffer[wbo]); | |
236 | } | |
237 | sKeywordBuffer[wbo] = '\0'; | |
238 | // Check for Special Keyword in list | |
239 | if ((keywords.InList(sKeywordBuffer)) && | |
240 | ((IsBOperator(wordBuffer[wbo])) || | |
241 | (IsBSeparator(wordBuffer[wbo])))) { | |
242 | sKeywordFound = true; | |
243 | // ECHO requires no further Regular Keyword Checking | |
244 | if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) { | |
245 | continueProcessing = false; | |
246 | } | |
247 | // Colorize Special Keyword as Regular Keyword | |
248 | styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD); | |
249 | // Reset Offset to re-process remainder of word | |
250 | offset -= (wbl - wbo); | |
b8193d80 | 251 | } |
65ec6247 | 252 | } |
1e9bafca RD |
253 | // Check for External Command / Program or Default Text |
254 | if (!sKeywordFound) { | |
255 | wbo = 0; | |
256 | // Check for External Command / Program | |
257 | if (cmdLoc == offset - wbl) { | |
258 | // Read up to %, Operator or Separator | |
259 | while ((wbo < wbl) && | |
260 | (wordBuffer[wbo] != '%') && | |
9e96e16f | 261 | (wordBuffer[wbo] != '!') && |
1e9bafca RD |
262 | (!IsBOperator(wordBuffer[wbo])) && |
263 | (!IsBSeparator(wordBuffer[wbo]))) { | |
264 | wbo++; | |
265 | } | |
266 | // Reset External Command / Program Location | |
267 | cmdLoc = offset - (wbl - wbo); | |
268 | // Reset Offset to re-process remainder of word | |
269 | offset -= (wbl - wbo); | |
270 | // CHOICE requires no further Regular Keyword Checking | |
271 | if (CompareCaseInsensitive(wordBuffer, "choice") == 0) { | |
272 | continueProcessing = false; | |
273 | } | |
274 | // Check for START (and its switches) - What follows is External Command \ Program | |
275 | if (CompareCaseInsensitive(wordBuffer, "start") == 0) { | |
276 | // Reset External Command / Program Location | |
277 | cmdLoc = offset; | |
278 | // Skip next spaces | |
279 | while ((cmdLoc < lengthLine) && | |
280 | (isspacechar(lineBuffer[cmdLoc]))) { | |
281 | cmdLoc++; | |
282 | } | |
283 | // Reset External Command / Program Location if command switch detected | |
284 | if (lineBuffer[cmdLoc] == '/') { | |
285 | // Skip command switch | |
286 | while ((cmdLoc < lengthLine) && | |
287 | (!isspacechar(lineBuffer[cmdLoc]))) { | |
288 | cmdLoc++; | |
289 | } | |
290 | // Skip next spaces | |
291 | while ((cmdLoc < lengthLine) && | |
292 | (isspacechar(lineBuffer[cmdLoc]))) { | |
293 | cmdLoc++; | |
294 | } | |
295 | } | |
296 | } | |
b8193d80 RD |
297 | // Colorize External Command / Program |
298 | if (!keywords2) { | |
299 | styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); | |
300 | } else if (keywords2.InList(wordBuffer)) { | |
301 | styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND); | |
302 | } else { | |
303 | styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); | |
304 | } | |
1e9bafca RD |
305 | // No need to Reset Offset |
306 | // Check for Default Text | |
65ec6247 | 307 | } else { |
1e9bafca RD |
308 | // Read up to %, Operator or Separator |
309 | while ((wbo < wbl) && | |
310 | (wordBuffer[wbo] != '%') && | |
9e96e16f | 311 | (wordBuffer[wbo] != '!') && |
1e9bafca RD |
312 | (!IsBOperator(wordBuffer[wbo])) && |
313 | (!IsBSeparator(wordBuffer[wbo]))) { | |
314 | wbo++; | |
315 | } | |
316 | // Colorize Default Text | |
317 | styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); | |
318 | // Reset Offset to re-process remainder of word | |
319 | offset -= (wbl - wbo); | |
320 | } | |
321 | } | |
322 | // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a) | |
323 | } else if (wordBuffer[0] == '%') { | |
324 | // Colorize Default Text | |
325 | styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); | |
326 | wbo++; | |
327 | // Search to end of word for second % (can be a long path) | |
328 | while ((wbo < wbl) && | |
329 | (wordBuffer[wbo] != '%') && | |
330 | (!IsBOperator(wordBuffer[wbo])) && | |
331 | (!IsBSeparator(wordBuffer[wbo]))) { | |
332 | wbo++; | |
333 | } | |
9e96e16f RD |
334 | // Check for Argument (%n) or (%*) |
335 | if (((Is0To9(wordBuffer[1])) || (wordBuffer[1] == '*')) && | |
1e9bafca RD |
336 | (wordBuffer[wbo] != '%')) { |
337 | // Check for External Command / Program | |
338 | if (cmdLoc == offset - wbl) { | |
339 | cmdLoc = offset - (wbl - 2); | |
65ec6247 | 340 | } |
1e9bafca RD |
341 | // Colorize Argument |
342 | styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER); | |
343 | // Reset Offset to re-process remainder of word | |
344 | offset -= (wbl - 2); | |
9e96e16f RD |
345 | // Check for Expanded Argument (%~...) / Variable (%%~...) |
346 | } else if (((wbl > 1) && (wordBuffer[1] == '~')) || | |
347 | ((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) { | |
348 | // Check for External Command / Program | |
349 | if (cmdLoc == offset - wbl) { | |
350 | cmdLoc = offset - (wbl - wbo); | |
351 | } | |
352 | // Colorize Expanded Argument / Variable | |
353 | styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); | |
354 | // Reset Offset to re-process remainder of word | |
355 | offset -= (wbl - wbo); | |
1e9bafca RD |
356 | // Check for Environment Variable (%x...%) |
357 | } else if ((wordBuffer[1] != '%') && | |
358 | (wordBuffer[wbo] == '%')) { | |
359 | wbo++; | |
360 | // Check for External Command / Program | |
361 | if (cmdLoc == offset - wbl) { | |
362 | cmdLoc = offset - (wbl - wbo); | |
b8193d80 | 363 | } |
1e9bafca RD |
364 | // Colorize Environment Variable |
365 | styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); | |
366 | // Reset Offset to re-process remainder of word | |
367 | offset -= (wbl - wbo); | |
368 | // Check for Local Variable (%%a) | |
b8193d80 | 369 | } else if ( |
7e0c58e9 | 370 | (wbl > 2) && |
1e9bafca RD |
371 | (wordBuffer[1] == '%') && |
372 | (wordBuffer[2] != '%') && | |
373 | (!IsBOperator(wordBuffer[2])) && | |
374 | (!IsBSeparator(wordBuffer[2]))) { | |
375 | // Check for External Command / Program | |
376 | if (cmdLoc == offset - wbl) { | |
377 | cmdLoc = offset - (wbl - 3); | |
378 | } | |
379 | // Colorize Local Variable | |
380 | styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER); | |
381 | // Reset Offset to re-process remainder of word | |
382 | offset -= (wbl - 3); | |
383 | } | |
9e96e16f RD |
384 | // Check for Environment Variable (!x...!) |
385 | } else if (wordBuffer[0] == '!') { | |
386 | // Colorize Default Text | |
387 | styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); | |
388 | wbo++; | |
389 | // Search to end of word for second ! (can be a long path) | |
390 | while ((wbo < wbl) && | |
391 | (wordBuffer[wbo] != '!') && | |
392 | (!IsBOperator(wordBuffer[wbo])) && | |
393 | (!IsBSeparator(wordBuffer[wbo]))) { | |
394 | wbo++; | |
395 | } | |
396 | if (wordBuffer[wbo] == '!') { | |
397 | wbo++; | |
398 | // Check for External Command / Program | |
399 | if (cmdLoc == offset - wbl) { | |
400 | cmdLoc = offset - (wbl - wbo); | |
401 | } | |
402 | // Colorize Environment Variable | |
403 | styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER); | |
404 | // Reset Offset to re-process remainder of word | |
405 | offset -= (wbl - wbo); | |
406 | } | |
1e9bafca RD |
407 | // Check for Operator |
408 | } else if (IsBOperator(wordBuffer[0])) { | |
409 | // Colorize Default Text | |
410 | styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT); | |
411 | // Check for Comparison Operator | |
412 | if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) { | |
413 | // Identify External Command / Program Location for IF | |
414 | cmdLoc = offset; | |
415 | // Skip next spaces | |
416 | while ((cmdLoc < lengthLine) && | |
417 | (isspacechar(lineBuffer[cmdLoc]))) { | |
418 | cmdLoc++; | |
419 | } | |
420 | // Colorize Comparison Operator | |
421 | styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR); | |
422 | // Reset Offset to re-process remainder of word | |
423 | offset -= (wbl - 2); | |
424 | // Check for Pipe Operator | |
425 | } else if (wordBuffer[0] == '|') { | |
426 | // Reset External Command / Program Location | |
427 | cmdLoc = offset - wbl + 1; | |
428 | // Skip next spaces | |
429 | while ((cmdLoc < lengthLine) && | |
430 | (isspacechar(lineBuffer[cmdLoc]))) { | |
431 | cmdLoc++; | |
432 | } | |
433 | // Colorize Pipe Operator | |
434 | styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); | |
435 | // Reset Offset to re-process remainder of word | |
436 | offset -= (wbl - 1); | |
437 | // Check for Other Operator | |
438 | } else { | |
439 | // Check for > Operator | |
440 | if (wordBuffer[0] == '>') { | |
441 | // Turn Keyword and External Command / Program checking back on | |
442 | continueProcessing = true; | |
443 | } | |
444 | // Colorize Other Operator | |
445 | styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR); | |
446 | // Reset Offset to re-process remainder of word | |
447 | offset -= (wbl - 1); | |
448 | } | |
449 | // Check for Default Text | |
450 | } else { | |
451 | // Read up to %, Operator or Separator | |
452 | while ((wbo < wbl) && | |
453 | (wordBuffer[wbo] != '%') && | |
9e96e16f | 454 | (wordBuffer[wbo] != '!') && |
1e9bafca RD |
455 | (!IsBOperator(wordBuffer[wbo])) && |
456 | (!IsBSeparator(wordBuffer[wbo]))) { | |
457 | wbo++; | |
458 | } | |
459 | // Colorize Default Text | |
460 | styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT); | |
461 | // Reset Offset to re-process remainder of word | |
462 | offset -= (wbl - wbo); | |
463 | } | |
464 | // Skip next spaces - nothing happens if Offset was Reset | |
465 | while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { | |
65ec6247 RD |
466 | offset++; |
467 | } | |
f6bcfd97 | 468 | } |
1e9bafca RD |
469 | // Colorize Default Text for remainder of line - currently not lexed |
470 | styler.ColourTo(endPos, SCE_BAT_DEFAULT); | |
f6bcfd97 | 471 | } |
65ec6247 RD |
472 | |
473 | static void ColouriseBatchDoc( | |
474 | unsigned int startPos, | |
475 | int length, | |
476 | int /*initStyle*/, | |
477 | WordList *keywordlists[], | |
478 | Accessor &styler) { | |
f6bcfd97 | 479 | |
f6bcfd97 | 480 | char lineBuffer[1024]; |
65ec6247 | 481 | |
f6bcfd97 BP |
482 | styler.StartAt(startPos); |
483 | styler.StartSegment(startPos); | |
1a2fb4cd RD |
484 | unsigned int linePos = 0; |
485 | unsigned int startLine = startPos; | |
486 | for (unsigned int i = startPos; i < startPos + length; i++) { | |
f6bcfd97 | 487 | lineBuffer[linePos++] = styler[i]; |
1a2fb4cd | 488 | if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { |
65ec6247 | 489 | // End of line (or of line buffer) met, colourise it |
65ec6247 | 490 | lineBuffer[linePos] = '\0'; |
b8193d80 | 491 | ColouriseBatchLine(lineBuffer, linePos, startLine, i, keywordlists, styler); |
f6bcfd97 | 492 | linePos = 0; |
65ec6247 | 493 | startLine = i + 1; |
f6bcfd97 BP |
494 | } |
495 | } | |
1a2fb4cd | 496 | if (linePos > 0) { // Last line does not have ending characters |
7e0c58e9 | 497 | lineBuffer[linePos] = '\0'; |
1a2fb4cd | 498 | ColouriseBatchLine(lineBuffer, linePos, startLine, startPos + length - 1, |
b8193d80 | 499 | keywordlists, styler); |
65ec6247 | 500 | } |
f6bcfd97 BP |
501 | } |
502 | ||
1dcf666d RD |
503 | #define DIFF_BUFFER_START_SIZE 16 |
504 | // Note that ColouriseDiffLine analyzes only the first DIFF_BUFFER_START_SIZE | |
505 | // characters of each line to classify the line. | |
506 | ||
d134f170 RD |
507 | static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) { |
508 | // It is needed to remember the current state to recognize starting | |
509 | // comment lines before the first "diff " or "--- ". If a real | |
510 | // difference starts then each line starting with ' ' is a whitespace | |
511 | // otherwise it is considered a comment (Only in..., Binary file...) | |
591d01be | 512 | if (0 == strncmp(lineBuffer, "diff ", 5)) { |
a834585d | 513 | styler.ColourTo(endLine, SCE_DIFF_COMMAND); |
9e96e16f RD |
514 | } else if (0 == strncmp(lineBuffer, "Index: ", 7)) { // For subversion's diff |
515 | styler.ColourTo(endLine, SCE_DIFF_COMMAND); | |
1dcf666d | 516 | } else if (0 == strncmp(lineBuffer, "---", 3) && lineBuffer[3] != '-') { |
591d01be | 517 | // In a context diff, --- appears in both the header and the position markers |
9e96e16f RD |
518 | if (lineBuffer[3] == ' ' && atoi(lineBuffer + 4) && !strchr(lineBuffer, '/')) |
519 | styler.ColourTo(endLine, SCE_DIFF_POSITION); | |
520 | else if (lineBuffer[3] == '\r' || lineBuffer[3] == '\n') | |
591d01be RD |
521 | styler.ColourTo(endLine, SCE_DIFF_POSITION); |
522 | else | |
523 | styler.ColourTo(endLine, SCE_DIFF_HEADER); | |
524 | } else if (0 == strncmp(lineBuffer, "+++ ", 4)) { | |
525 | // I don't know of any diff where "+++ " is a position marker, but for | |
526 | // consistency, do the same as with "--- " and "*** ". | |
527 | if (atoi(lineBuffer+4) && !strchr(lineBuffer, '/')) | |
528 | styler.ColourTo(endLine, SCE_DIFF_POSITION); | |
529 | else | |
530 | styler.ColourTo(endLine, SCE_DIFF_HEADER); | |
9e730a78 RD |
531 | } else if (0 == strncmp(lineBuffer, "====", 4)) { // For p4's diff |
532 | styler.ColourTo(endLine, SCE_DIFF_HEADER); | |
591d01be RD |
533 | } else if (0 == strncmp(lineBuffer, "***", 3)) { |
534 | // In a context diff, *** appears in both the header and the position markers. | |
535 | // Also ******** is a chunk header, but here it's treated as part of the | |
536 | // position marker since there is no separate style for a chunk header. | |
537 | if (lineBuffer[3] == ' ' && atoi(lineBuffer+4) && !strchr(lineBuffer, '/')) | |
538 | styler.ColourTo(endLine, SCE_DIFF_POSITION); | |
539 | else if (lineBuffer[3] == '*') | |
540 | styler.ColourTo(endLine, SCE_DIFF_POSITION); | |
541 | else | |
542 | styler.ColourTo(endLine, SCE_DIFF_HEADER); | |
9e730a78 | 543 | } else if (0 == strncmp(lineBuffer, "? ", 2)) { // For difflib |
a834585d | 544 | styler.ColourTo(endLine, SCE_DIFF_HEADER); |
d134f170 | 545 | } else if (lineBuffer[0] == '@') { |
a834585d | 546 | styler.ColourTo(endLine, SCE_DIFF_POSITION); |
591d01be RD |
547 | } else if (lineBuffer[0] >= '0' && lineBuffer[0] <= '9') { |
548 | styler.ColourTo(endLine, SCE_DIFF_POSITION); | |
9e730a78 | 549 | } else if (lineBuffer[0] == '-' || lineBuffer[0] == '<') { |
a834585d | 550 | styler.ColourTo(endLine, SCE_DIFF_DELETED); |
9e730a78 | 551 | } else if (lineBuffer[0] == '+' || lineBuffer[0] == '>') { |
a834585d | 552 | styler.ColourTo(endLine, SCE_DIFF_ADDED); |
9e96e16f RD |
553 | } else if (lineBuffer[0] == '!') { |
554 | styler.ColourTo(endLine, SCE_DIFF_CHANGED); | |
d134f170 | 555 | } else if (lineBuffer[0] != ' ') { |
a834585d | 556 | styler.ColourTo(endLine, SCE_DIFF_COMMENT); |
d134f170 | 557 | } else { |
a834585d | 558 | styler.ColourTo(endLine, SCE_DIFF_DEFAULT); |
d134f170 RD |
559 | } |
560 | } | |
561 | ||
562 | static void ColouriseDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { | |
1dcf666d | 563 | char lineBuffer[DIFF_BUFFER_START_SIZE]; |
d134f170 RD |
564 | styler.StartAt(startPos); |
565 | styler.StartSegment(startPos); | |
566 | unsigned int linePos = 0; | |
567 | for (unsigned int i = startPos; i < startPos + length; i++) { | |
1dcf666d RD |
568 | if (AtEOL(styler, i)) { |
569 | if (linePos < DIFF_BUFFER_START_SIZE) { | |
570 | lineBuffer[linePos] = 0; | |
571 | } | |
d134f170 RD |
572 | ColouriseDiffLine(lineBuffer, i, styler); |
573 | linePos = 0; | |
1dcf666d RD |
574 | } else if (linePos < DIFF_BUFFER_START_SIZE - 1) { |
575 | lineBuffer[linePos++] = styler[i]; | |
576 | } else if (linePos == DIFF_BUFFER_START_SIZE - 1) { | |
577 | lineBuffer[linePos++] = 0; | |
d134f170 RD |
578 | } |
579 | } | |
1a2fb4cd | 580 | if (linePos > 0) { // Last line does not have ending characters |
1dcf666d RD |
581 | if (linePos < DIFF_BUFFER_START_SIZE) { |
582 | lineBuffer[linePos] = 0; | |
583 | } | |
1a2fb4cd RD |
584 | ColouriseDiffLine(lineBuffer, startPos + length - 1, styler); |
585 | } | |
d134f170 RD |
586 | } |
587 | ||
9e96e16f | 588 | static void FoldDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { |
591d01be | 589 | int curLine = styler.GetLine(startPos); |
591d01be | 590 | int curLineStart = styler.LineStart(curLine); |
9e96e16f RD |
591 | int prevLevel = curLine > 0 ? styler.LevelAt(curLine - 1) : SC_FOLDLEVELBASE; |
592 | int nextLevel; | |
1e9bafca | 593 | |
9e96e16f | 594 | do { |
591d01be RD |
595 | int lineType = styler.StyleAt(curLineStart); |
596 | if (lineType == SCE_DIFF_COMMAND) | |
9e96e16f RD |
597 | nextLevel = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; |
598 | else if (lineType == SCE_DIFF_HEADER) | |
591d01be | 599 | nextLevel = (SC_FOLDLEVELBASE + 1) | SC_FOLDLEVELHEADERFLAG; |
9e96e16f | 600 | else if (lineType == SCE_DIFF_POSITION && styler[curLineStart] != '-') |
591d01be | 601 | nextLevel = (SC_FOLDLEVELBASE + 2) | SC_FOLDLEVELHEADERFLAG; |
9e96e16f RD |
602 | else if (prevLevel & SC_FOLDLEVELHEADERFLAG) |
603 | nextLevel = (prevLevel & SC_FOLDLEVELNUMBERMASK) + 1; | |
604 | else | |
605 | nextLevel = prevLevel; | |
1e9bafca | 606 | |
591d01be RD |
607 | if ((nextLevel & SC_FOLDLEVELHEADERFLAG) && (nextLevel == prevLevel)) |
608 | styler.SetLevel(curLine-1, prevLevel & ~SC_FOLDLEVELHEADERFLAG); | |
609 | ||
610 | styler.SetLevel(curLine, nextLevel); | |
611 | prevLevel = nextLevel; | |
1e9bafca | 612 | |
591d01be RD |
613 | curLineStart = styler.LineStart(++curLine); |
614 | } while (static_cast<int>(startPos) + length > curLineStart); | |
615 | } | |
616 | ||
9e96e16f | 617 | static void ColourisePoLine( |
65ec6247 RD |
618 | char *lineBuffer, |
619 | unsigned int lengthLine, | |
620 | unsigned int startLine, | |
621 | unsigned int endPos, | |
622 | Accessor &styler) { | |
623 | ||
624 | unsigned int i = 0; | |
9e96e16f RD |
625 | static unsigned int state = SCE_PO_DEFAULT; |
626 | unsigned int state_start = SCE_PO_DEFAULT; | |
627 | ||
1a2fb4cd | 628 | while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces |
f6bcfd97 | 629 | i++; |
9e96e16f RD |
630 | if (i < lengthLine) { |
631 | if (lineBuffer[i] == '#') { | |
632 | // check if the comment contains any flags ("#, ") and | |
633 | // then whether the flags contain "fuzzy" | |
634 | if (strstart(lineBuffer, "#, ") && strstr(lineBuffer, "fuzzy")) | |
635 | styler.ColourTo(endPos, SCE_PO_FUZZY); | |
636 | else | |
637 | styler.ColourTo(endPos, SCE_PO_COMMENT); | |
638 | } else { | |
639 | if (lineBuffer[0] == '"') { | |
640 | // line continuation, use previous style | |
641 | styler.ColourTo(endPos, state); | |
642 | return; | |
643 | // this implicitly also matches "msgid_plural" | |
644 | } else if (strstart(lineBuffer, "msgid")) { | |
645 | state_start = SCE_PO_MSGID; | |
646 | state = SCE_PO_MSGID_TEXT; | |
647 | } else if (strstart(lineBuffer, "msgstr")) { | |
648 | state_start = SCE_PO_MSGSTR; | |
649 | state = SCE_PO_MSGSTR_TEXT; | |
650 | } else if (strstart(lineBuffer, "msgctxt")) { | |
651 | state_start = SCE_PO_MSGCTXT; | |
652 | state = SCE_PO_MSGCTXT_TEXT; | |
653 | } | |
654 | if (state_start != SCE_PO_DEFAULT) { | |
655 | // find the next space | |
656 | while ((i < lengthLine) && ! isspacechar(lineBuffer[i])) | |
657 | i++; | |
658 | styler.ColourTo(startLine + i - 1, state_start); | |
659 | styler.ColourTo(startLine + i, SCE_PO_DEFAULT); | |
660 | styler.ColourTo(endPos, state); | |
661 | } | |
662 | } | |
663 | } else { | |
664 | styler.ColourTo(endPos, SCE_PO_DEFAULT); | |
665 | } | |
666 | } | |
667 | ||
668 | static void ColourisePoDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { | |
669 | char lineBuffer[1024]; | |
670 | styler.StartAt(startPos); | |
671 | styler.StartSegment(startPos); | |
672 | unsigned int linePos = 0; | |
673 | unsigned int startLine = startPos; | |
674 | for (unsigned int i = startPos; i < startPos + length; i++) { | |
675 | lineBuffer[linePos++] = styler[i]; | |
676 | if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { | |
677 | // End of line (or of line buffer) met, colourise it | |
678 | lineBuffer[linePos] = '\0'; | |
679 | ColourisePoLine(lineBuffer, linePos, startLine, i, styler); | |
680 | linePos = 0; | |
681 | startLine = i + 1; | |
682 | } | |
683 | } | |
684 | if (linePos > 0) { // Last line does not have ending characters | |
685 | ColourisePoLine(lineBuffer, linePos, startLine, startPos + length - 1, styler); | |
686 | } | |
687 | } | |
688 | ||
689 | static inline bool isassignchar(unsigned char ch) { | |
690 | return (ch == '=') || (ch == ':'); | |
691 | } | |
692 | ||
693 | static void ColourisePropsLine( | |
694 | char *lineBuffer, | |
695 | unsigned int lengthLine, | |
696 | unsigned int startLine, | |
697 | unsigned int endPos, | |
698 | Accessor &styler, | |
699 | bool allowInitialSpaces) { | |
700 | ||
701 | unsigned int i = 0; | |
702 | if (allowInitialSpaces) { | |
703 | while ((i < lengthLine) && isspacechar(lineBuffer[i])) // Skip initial spaces | |
704 | i++; | |
705 | } else { | |
706 | if (isspacechar(lineBuffer[i])) // don't allow initial spaces | |
707 | i = lengthLine; | |
708 | } | |
709 | ||
1a2fb4cd RD |
710 | if (i < lengthLine) { |
711 | if (lineBuffer[i] == '#' || lineBuffer[i] == '!' || lineBuffer[i] == ';') { | |
a834585d | 712 | styler.ColourTo(endPos, SCE_PROPS_COMMENT); |
1a2fb4cd | 713 | } else if (lineBuffer[i] == '[') { |
a834585d | 714 | styler.ColourTo(endPos, SCE_PROPS_SECTION); |
1a2fb4cd | 715 | } else if (lineBuffer[i] == '@') { |
a834585d | 716 | styler.ColourTo(startLine + i, SCE_PROPS_DEFVAL); |
9e96e16f | 717 | if (isassignchar(lineBuffer[i++])) |
a834585d RD |
718 | styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT); |
719 | styler.ColourTo(endPos, SCE_PROPS_DEFAULT); | |
f6bcfd97 | 720 | } else { |
1a2fb4cd | 721 | // Search for the '=' character |
9e96e16f | 722 | while ((i < lengthLine) && !isassignchar(lineBuffer[i])) |
1a2fb4cd | 723 | i++; |
9e96e16f | 724 | if ((i < lengthLine) && isassignchar(lineBuffer[i])) { |
b8193d80 RD |
725 | styler.ColourTo(startLine + i - 1, SCE_PROPS_KEY); |
726 | styler.ColourTo(startLine + i, SCE_PROPS_ASSIGNMENT); | |
a834585d | 727 | styler.ColourTo(endPos, SCE_PROPS_DEFAULT); |
1a2fb4cd | 728 | } else { |
a834585d | 729 | styler.ColourTo(endPos, SCE_PROPS_DEFAULT); |
1a2fb4cd | 730 | } |
f6bcfd97 | 731 | } |
1a2fb4cd | 732 | } else { |
a834585d | 733 | styler.ColourTo(endPos, SCE_PROPS_DEFAULT); |
f6bcfd97 BP |
734 | } |
735 | } | |
736 | ||
737 | static void ColourisePropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { | |
738 | char lineBuffer[1024]; | |
739 | styler.StartAt(startPos); | |
740 | styler.StartSegment(startPos); | |
1a2fb4cd RD |
741 | unsigned int linePos = 0; |
742 | unsigned int startLine = startPos; | |
9e96e16f | 743 | |
1dcf666d RD |
744 | // property lexer.props.allow.initial.spaces |
745 | // For properties files, set to 0 to style all lines that start with whitespace in the default style. | |
746 | // This is not suitable for SciTE .properties files which use indentation for flow control but | |
747 | // can be used for RFC2822 text where indentation is used for continuation lines. | |
9e96e16f RD |
748 | bool allowInitialSpaces = styler.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0; |
749 | ||
1a2fb4cd | 750 | for (unsigned int i = startPos; i < startPos + length; i++) { |
f6bcfd97 | 751 | lineBuffer[linePos++] = styler[i]; |
1a2fb4cd RD |
752 | if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { |
753 | // End of line (or of line buffer) met, colourise it | |
f6bcfd97 | 754 | lineBuffer[linePos] = '\0'; |
9e96e16f | 755 | ColourisePropsLine(lineBuffer, linePos, startLine, i, styler, allowInitialSpaces); |
f6bcfd97 | 756 | linePos = 0; |
65ec6247 | 757 | startLine = i + 1; |
f6bcfd97 BP |
758 | } |
759 | } | |
1a2fb4cd | 760 | if (linePos > 0) { // Last line does not have ending characters |
9e96e16f | 761 | ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler, allowInitialSpaces); |
1a2fb4cd | 762 | } |
f6bcfd97 BP |
763 | } |
764 | ||
88a8b04e RD |
765 | // adaption by ksc, using the "} else {" trick of 1.53 |
766 | // 030721 | |
767 | static void FoldPropsDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { | |
768 | bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; | |
769 | ||
770 | unsigned int endPos = startPos + length; | |
771 | int visibleChars = 0; | |
772 | int lineCurrent = styler.GetLine(startPos); | |
773 | ||
774 | char chNext = styler[startPos]; | |
775 | int styleNext = styler.StyleAt(startPos); | |
776 | bool headerPoint = false; | |
a33203cb | 777 | int lev; |
88a8b04e RD |
778 | |
779 | for (unsigned int i = startPos; i < endPos; i++) { | |
780 | char ch = chNext; | |
781 | chNext = styler[i+1]; | |
782 | ||
783 | int style = styleNext; | |
784 | styleNext = styler.StyleAt(i + 1); | |
785 | bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); | |
786 | ||
a33203cb | 787 | if (style == SCE_PROPS_SECTION) { |
88a8b04e RD |
788 | headerPoint = true; |
789 | } | |
790 | ||
791 | if (atEOL) { | |
a33203cb RD |
792 | lev = SC_FOLDLEVELBASE; |
793 | ||
794 | if (lineCurrent > 0) { | |
795 | int levelPrevious = styler.LevelAt(lineCurrent - 1); | |
88a8b04e | 796 | |
a33203cb RD |
797 | if (levelPrevious & SC_FOLDLEVELHEADERFLAG) { |
798 | lev = SC_FOLDLEVELBASE + 1; | |
799 | } else { | |
800 | lev = levelPrevious & SC_FOLDLEVELNUMBERMASK; | |
801 | } | |
802 | } | |
803 | ||
804 | if (headerPoint) { | |
805 | lev = SC_FOLDLEVELBASE; | |
806 | } | |
88a8b04e RD |
807 | if (visibleChars == 0 && foldCompact) |
808 | lev |= SC_FOLDLEVELWHITEFLAG; | |
809 | ||
a33203cb | 810 | if (headerPoint) { |
88a8b04e | 811 | lev |= SC_FOLDLEVELHEADERFLAG; |
a33203cb | 812 | } |
88a8b04e RD |
813 | if (lev != styler.LevelAt(lineCurrent)) { |
814 | styler.SetLevel(lineCurrent, lev); | |
815 | } | |
816 | ||
817 | lineCurrent++; | |
818 | visibleChars = 0; | |
1e9bafca | 819 | headerPoint = false; |
88a8b04e RD |
820 | } |
821 | if (!isspacechar(ch)) | |
822 | visibleChars++; | |
823 | } | |
824 | ||
a33203cb RD |
825 | if (lineCurrent > 0) { |
826 | int levelPrevious = styler.LevelAt(lineCurrent - 1); | |
827 | if (levelPrevious & SC_FOLDLEVELHEADERFLAG) { | |
828 | lev = SC_FOLDLEVELBASE + 1; | |
829 | } else { | |
830 | lev = levelPrevious & SC_FOLDLEVELNUMBERMASK; | |
831 | } | |
832 | } else { | |
833 | lev = SC_FOLDLEVELBASE; | |
834 | } | |
835 | int flagsNext = styler.LevelAt(lineCurrent); | |
9e96e16f | 836 | styler.SetLevel(lineCurrent, lev | (flagsNext & ~SC_FOLDLEVELNUMBERMASK)); |
88a8b04e RD |
837 | } |
838 | ||
65ec6247 RD |
839 | static void ColouriseMakeLine( |
840 | char *lineBuffer, | |
841 | unsigned int lengthLine, | |
842 | unsigned int startLine, | |
843 | unsigned int endPos, | |
844 | Accessor &styler) { | |
845 | ||
846 | unsigned int i = 0; | |
9e730a78 | 847 | int lastNonSpace = -1; |
65ec6247 RD |
848 | unsigned int state = SCE_MAKE_DEFAULT; |
849 | bool bSpecial = false; | |
7e0c58e9 RD |
850 | |
851 | // check for a tab character in column 0 indicating a command | |
852 | bool bCommand = false; | |
853 | if ((lengthLine > 0) && (lineBuffer[0] == '\t')) | |
854 | bCommand = true; | |
855 | ||
65ec6247 | 856 | // Skip initial spaces |
1a2fb4cd | 857 | while ((i < lengthLine) && isspacechar(lineBuffer[i])) { |
f6bcfd97 | 858 | i++; |
65ec6247 RD |
859 | } |
860 | if (lineBuffer[i] == '#') { // Comment | |
861 | styler.ColourTo(endPos, SCE_MAKE_COMMENT); | |
862 | return; | |
863 | } | |
864 | if (lineBuffer[i] == '!') { // Special directive | |
865 | styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR); | |
866 | return; | |
867 | } | |
1dcf666d | 868 | int varCount = 0; |
65ec6247 RD |
869 | while (i < lengthLine) { |
870 | if (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(') { | |
871 | styler.ColourTo(startLine + i - 1, state); | |
872 | state = SCE_MAKE_IDENTIFIER; | |
1dcf666d | 873 | varCount++; |
65ec6247 | 874 | } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') { |
1dcf666d RD |
875 | if (--varCount == 0) { |
876 | styler.ColourTo(startLine + i, state); | |
877 | state = SCE_MAKE_DEFAULT; | |
878 | } | |
65ec6247 | 879 | } |
7e0c58e9 RD |
880 | |
881 | // skip identifier and target styling if this is a command line | |
882 | if (!bSpecial && !bCommand) { | |
65ec6247 | 883 | if (lineBuffer[i] == ':') { |
7e0c58e9 RD |
884 | if (((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=')) { |
885 | // it's a ':=', so style as an identifier | |
886 | if (lastNonSpace >= 0) | |
887 | styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER); | |
888 | styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); | |
889 | styler.ColourTo(startLine + i + 1, SCE_MAKE_OPERATOR); | |
890 | } else { | |
891 | // We should check that no colouring was made since the beginning of the line, | |
892 | // to avoid colouring stuff like /OUT:file | |
893 | if (lastNonSpace >= 0) | |
894 | styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET); | |
895 | styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); | |
896 | styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR); | |
897 | } | |
65ec6247 RD |
898 | bSpecial = true; // Only react to the first ':' of the line |
899 | state = SCE_MAKE_DEFAULT; | |
900 | } else if (lineBuffer[i] == '=') { | |
9e730a78 RD |
901 | if (lastNonSpace >= 0) |
902 | styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER); | |
65ec6247 RD |
903 | styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT); |
904 | styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR); | |
905 | bSpecial = true; // Only react to the first '=' of the line | |
906 | state = SCE_MAKE_DEFAULT; | |
907 | } | |
908 | } | |
909 | if (!isspacechar(lineBuffer[i])) { | |
910 | lastNonSpace = i; | |
911 | } | |
912 | i++; | |
913 | } | |
914 | if (state == SCE_MAKE_IDENTIFIER) { | |
915 | styler.ColourTo(endPos, SCE_MAKE_IDEOL); // Error, variable reference not ended | |
f6bcfd97 | 916 | } else { |
65ec6247 | 917 | styler.ColourTo(endPos, SCE_MAKE_DEFAULT); |
f6bcfd97 BP |
918 | } |
919 | } | |
920 | ||
921 | static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { | |
922 | char lineBuffer[1024]; | |
923 | styler.StartAt(startPos); | |
924 | styler.StartSegment(startPos); | |
1a2fb4cd RD |
925 | unsigned int linePos = 0; |
926 | unsigned int startLine = startPos; | |
927 | for (unsigned int i = startPos; i < startPos + length; i++) { | |
f6bcfd97 | 928 | lineBuffer[linePos++] = styler[i]; |
1a2fb4cd RD |
929 | if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { |
930 | // End of line (or of line buffer) met, colourise it | |
65ec6247 RD |
931 | lineBuffer[linePos] = '\0'; |
932 | ColouriseMakeLine(lineBuffer, linePos, startLine, i, styler); | |
f6bcfd97 | 933 | linePos = 0; |
65ec6247 | 934 | startLine = i + 1; |
f6bcfd97 BP |
935 | } |
936 | } | |
1a2fb4cd RD |
937 | if (linePos > 0) { // Last line does not have ending characters |
938 | ColouriseMakeLine(lineBuffer, linePos, startLine, startPos + length - 1, styler); | |
65ec6247 | 939 | } |
f6bcfd97 BP |
940 | } |
941 | ||
7e0c58e9 | 942 | static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLine, int &startValue) { |
f6bcfd97 BP |
943 | if (lineBuffer[0] == '>') { |
944 | // Command or return status | |
1e9bafca | 945 | return SCE_ERR_CMD; |
f114b858 | 946 | } else if (lineBuffer[0] == '<') { |
1dcf666d RD |
947 | // Diff removal. |
948 | return SCE_ERR_DIFF_DELETION; | |
65ec6247 | 949 | } else if (lineBuffer[0] == '!') { |
1e9bafca | 950 | return SCE_ERR_DIFF_CHANGED; |
65ec6247 | 951 | } else if (lineBuffer[0] == '+') { |
1e9bafca RD |
952 | if (strstart(lineBuffer, "+++ ")) { |
953 | return SCE_ERR_DIFF_MESSAGE; | |
954 | } else { | |
955 | return SCE_ERR_DIFF_ADDITION; | |
956 | } | |
591d01be | 957 | } else if (lineBuffer[0] == '-') { |
1e9bafca RD |
958 | if (strstart(lineBuffer, "--- ")) { |
959 | return SCE_ERR_DIFF_MESSAGE; | |
960 | } else { | |
961 | return SCE_ERR_DIFF_DELETION; | |
962 | } | |
8e54aaed RD |
963 | } else if (strstart(lineBuffer, "cf90-")) { |
964 | // Absoft Pro Fortran 90/95 v8.2 error and/or warning message | |
1e9bafca | 965 | return SCE_ERR_ABSF; |
8e54aaed RD |
966 | } else if (strstart(lineBuffer, "fortcom:")) { |
967 | // Intel Fortran Compiler v8.0 error/warning message | |
1e9bafca | 968 | return SCE_ERR_IFORT; |
f6bcfd97 | 969 | } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) { |
1e9bafca | 970 | return SCE_ERR_PYTHON; |
9e730a78 | 971 | } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) { |
1e9bafca | 972 | return SCE_ERR_PHP; |
9e730a78 | 973 | } else if ((strstart(lineBuffer, "Error ") || |
1e9bafca RD |
974 | strstart(lineBuffer, "Warning ")) && |
975 | strstr(lineBuffer, " at (") && | |
976 | strstr(lineBuffer, ") : ") && | |
977 | (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) { | |
9e730a78 | 978 | // Intel Fortran Compiler error/warning message |
1e9bafca | 979 | return SCE_ERR_IFC; |
9e730a78 | 980 | } else if (strstart(lineBuffer, "Error ")) { |
f6bcfd97 | 981 | // Borland error message |
1e9bafca | 982 | return SCE_ERR_BORLAND; |
9e730a78 | 983 | } else if (strstart(lineBuffer, "Warning ")) { |
f6bcfd97 | 984 | // Borland warning message |
1e9bafca | 985 | return SCE_ERR_BORLAND; |
1dcf666d RD |
986 | } else if (strstr(lineBuffer, "at line ") && |
987 | (strstr(lineBuffer, "at line ") < (lineBuffer + lengthLine)) && | |
65ec6247 | 988 | strstr(lineBuffer, "file ") && |
1a2fb4cd | 989 | (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) { |
591d01be | 990 | // Lua 4 error message |
1e9bafca | 991 | return SCE_ERR_LUA; |
1dcf666d RD |
992 | } else if (strstr(lineBuffer, " at ") && |
993 | (strstr(lineBuffer, " at ") < (lineBuffer + lengthLine)) && | |
65ec6247 | 994 | strstr(lineBuffer, " line ") && |
9e730a78 | 995 | (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) && |
1dcf666d | 996 | (strstr(lineBuffer, " at ") < (strstr(lineBuffer, " line ")))) { |
d134f170 | 997 | // perl error message |
1e9bafca | 998 | return SCE_ERR_PERL; |
65ec6247 | 999 | } else if ((memcmp(lineBuffer, " at ", 6) == 0) && |
1e9bafca | 1000 | strstr(lineBuffer, ":line ")) { |
65ec6247 | 1001 | // A .NET traceback |
1e9bafca | 1002 | return SCE_ERR_NET; |
9e730a78 | 1003 | } else if (strstart(lineBuffer, "Line ") && |
1e9bafca | 1004 | strstr(lineBuffer, ", file ")) { |
9e730a78 | 1005 | // Essential Lahey Fortran error message |
1e9bafca | 1006 | return SCE_ERR_ELF; |
a33203cb | 1007 | } else if (strstart(lineBuffer, "line ") && |
1e9bafca | 1008 | strstr(lineBuffer, " column ")) { |
a33203cb | 1009 | // HTML tidy style: line 42 column 1 |
1e9bafca | 1010 | return SCE_ERR_TIDY; |
a33203cb | 1011 | } else if (strstart(lineBuffer, "\tat ") && |
1e9bafca RD |
1012 | strstr(lineBuffer, "(") && |
1013 | strstr(lineBuffer, ".java:")) { | |
a33203cb | 1014 | // Java stack back trace |
1e9bafca | 1015 | return SCE_ERR_JAVA_STACK; |
f6bcfd97 | 1016 | } else { |
1e9bafca RD |
1017 | // Look for one of the following formats: |
1018 | // GCC: <filename>:<line>:<message> | |
1019 | // Microsoft: <filename>(<line>) :<message> | |
1020 | // Common: <filename>(<line>): warning|error|note|remark|catastrophic|fatal | |
1021 | // Common: <filename>(<line>) warning|error|note|remark|catastrophic|fatal | |
1022 | // Microsoft: <filename>(<line>,<column>)<message> | |
1023 | // CTags: \t<message> | |
1024 | // Lua 5 traceback: \t<filename>:<line>:<message> | |
7e0c58e9 | 1025 | // Lua 5.1: <exe>: <filename>:<line>:<message> |
591d01be | 1026 | bool initialTab = (lineBuffer[0] == '\t'); |
7e0c58e9 | 1027 | bool initialColonPart = false; |
b8193d80 | 1028 | enum { stInitial, |
1dcf666d | 1029 | stGccStart, stGccDigit, stGccColumn, stGcc, |
1e9bafca RD |
1030 | stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet, |
1031 | stCtagsStart, stCtagsStartString, stCtagsStringDollar, stCtags, | |
1032 | stUnrecognized | |
1033 | } state = stInitial; | |
65ec6247 | 1034 | for (unsigned int i = 0; i < lengthLine; i++) { |
9e730a78 RD |
1035 | char ch = lineBuffer[i]; |
1036 | char chNext = ' '; | |
1e9bafca RD |
1037 | if ((i + 1) < lengthLine) |
1038 | chNext = lineBuffer[i + 1]; | |
1039 | if (state == stInitial) { | |
9e730a78 | 1040 | if (ch == ':') { |
591d01be | 1041 | // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix) |
7e0c58e9 | 1042 | if ((chNext != '\\') && (chNext != '/') && (chNext != ' ')) { |
9e730a78 RD |
1043 | // This check is not completely accurate as may be on |
1044 | // GTK+ with a file name that includes ':'. | |
9e96e16f | 1045 | state = stGccStart; |
7e0c58e9 RD |
1046 | } else if (chNext == ' ') { // indicates a Lua 5.1 error message |
1047 | initialColonPart = true; | |
9e730a78 | 1048 | } |
591d01be | 1049 | } else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) { |
9e730a78 | 1050 | // May be Microsoft |
591d01be | 1051 | // Check against '0' often removes phone numbers |
1e9bafca | 1052 | state = stMsStart; |
591d01be | 1053 | } else if ((ch == '\t') && (!initialTab)) { |
9e730a78 | 1054 | // May be CTags |
1e9bafca | 1055 | state = stCtagsStart; |
9e730a78 | 1056 | } |
1e9bafca RD |
1057 | } else if (state == stGccStart) { // <filename>: |
1058 | state = Is1To9(ch) ? stGccDigit : stUnrecognized; | |
1059 | } else if (state == stGccDigit) { // <filename>:<line> | |
9e730a78 | 1060 | if (ch == ':') { |
1dcf666d | 1061 | state = stGccColumn; // :9.*: is GCC |
7e0c58e9 | 1062 | startValue = i + 1; |
9e730a78 | 1063 | } else if (!Is0To9(ch)) { |
1e9bafca | 1064 | state = stUnrecognized; |
9e730a78 | 1065 | } |
1dcf666d RD |
1066 | } else if (state == stGccColumn) { // <filename>:<line>:<column> |
1067 | if (!Is0To9(ch)) { | |
1068 | state = stGcc; | |
1069 | if (ch == ':') | |
1070 | startValue = i + 1; | |
1071 | break; | |
1072 | } | |
1e9bafca RD |
1073 | } else if (state == stMsStart) { // <filename>( |
1074 | state = Is0To9(ch) ? stMsDigit : stUnrecognized; | |
1075 | } else if (state == stMsDigit) { // <filename>(<line> | |
9e730a78 | 1076 | if (ch == ',') { |
1e9bafca | 1077 | state = stMsDigitComma; |
9e730a78 | 1078 | } else if (ch == ')') { |
1e9bafca | 1079 | state = stMsBracket; |
9e730a78 | 1080 | } else if ((ch != ' ') && !Is0To9(ch)) { |
1e9bafca | 1081 | state = stUnrecognized; |
9e730a78 | 1082 | } |
1e9bafca | 1083 | } else if (state == stMsBracket) { // <filename>(<line>) |
591d01be | 1084 | if ((ch == ' ') && (chNext == ':')) { |
1e9bafca RD |
1085 | state = stMsVc; |
1086 | } else if ((ch == ':' && chNext == ' ') || (ch == ' ')) { | |
1087 | // Possibly Delphi.. don't test against chNext as it's one of the strings below. | |
1088 | char word[512]; | |
1089 | unsigned int j, chPos; | |
1090 | unsigned numstep; | |
1091 | chPos = 0; | |
1092 | if (ch == ' ') | |
1093 | numstep = 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i. | |
1094 | else | |
1095 | numstep = 2; // otherwise add 2. | |
1dcf666d | 1096 | for (j = i + numstep; j < lengthLine && IsAlphabetic(lineBuffer[j]) && chPos < sizeof(word) - 1; j++) |
1e9bafca RD |
1097 | word[chPos++] = lineBuffer[j]; |
1098 | word[chPos] = 0; | |
b8193d80 RD |
1099 | if (!CompareCaseInsensitive(word, "error") || !CompareCaseInsensitive(word, "warning") || |
1100 | !CompareCaseInsensitive(word, "fatal") || !CompareCaseInsensitive(word, "catastrophic") || | |
1e9bafca RD |
1101 | !CompareCaseInsensitive(word, "note") || !CompareCaseInsensitive(word, "remark")) { |
1102 | state = stMsVc; | |
1103 | } else | |
1104 | state = stUnrecognized; | |
591d01be | 1105 | } else { |
1e9bafca | 1106 | state = stUnrecognized; |
591d01be | 1107 | } |
1e9bafca | 1108 | } else if (state == stMsDigitComma) { // <filename>(<line>, |
9e730a78 | 1109 | if (ch == ')') { |
1e9bafca | 1110 | state = stMsDotNet; |
9e730a78 RD |
1111 | break; |
1112 | } else if ((ch != ' ') && !Is0To9(ch)) { | |
1e9bafca | 1113 | state = stUnrecognized; |
9e730a78 | 1114 | } |
1e9bafca RD |
1115 | } else if (state == stCtagsStart) { |
1116 | if ((lineBuffer[i - 1] == '\t') && | |
1117 | ((ch == '/' && lineBuffer[i + 1] == '^') || Is0To9(ch))) { | |
1118 | state = stCtags; | |
9e730a78 | 1119 | break; |
1e9bafca RD |
1120 | } else if ((ch == '/') && (lineBuffer[i + 1] == '^')) { |
1121 | state = stCtagsStartString; | |
9e730a78 | 1122 | } |
1e9bafca RD |
1123 | } else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) { |
1124 | state = stCtagsStringDollar; | |
9e730a78 | 1125 | break; |
f6bcfd97 BP |
1126 | } |
1127 | } | |
1e9bafca | 1128 | if (state == stGcc) { |
7e0c58e9 | 1129 | return initialColonPart ? SCE_ERR_LUA : SCE_ERR_GCC; |
1e9bafca RD |
1130 | } else if ((state == stMsVc) || (state == stMsDotNet)) { |
1131 | return SCE_ERR_MS; | |
1132 | } else if ((state == stCtagsStringDollar) || (state == stCtags)) { | |
1133 | return SCE_ERR_CTAG; | |
f6bcfd97 | 1134 | } else { |
1e9bafca | 1135 | return SCE_ERR_DEFAULT; |
f6bcfd97 BP |
1136 | } |
1137 | } | |
1138 | } | |
1139 | ||
1e9bafca RD |
1140 | static void ColouriseErrorListLine( |
1141 | char *lineBuffer, | |
1142 | unsigned int lengthLine, | |
1143 | unsigned int endPos, | |
7e0c58e9 RD |
1144 | Accessor &styler, |
1145 | bool valueSeparate) { | |
1146 | int startValue = -1; | |
1147 | int style = RecogniseErrorListLine(lineBuffer, lengthLine, startValue); | |
1148 | if (valueSeparate && (startValue >= 0)) { | |
1149 | styler.ColourTo(endPos - (lengthLine - startValue), style); | |
1150 | styler.ColourTo(endPos, SCE_ERR_VALUE); | |
1151 | } else { | |
1152 | styler.ColourTo(endPos, style); | |
1153 | } | |
1e9bafca RD |
1154 | } |
1155 | ||
f6bcfd97 | 1156 | static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { |
1e9bafca | 1157 | char lineBuffer[10000]; |
f6bcfd97 BP |
1158 | styler.StartAt(startPos); |
1159 | styler.StartSegment(startPos); | |
1160 | unsigned int linePos = 0; | |
9e96e16f | 1161 | |
1dcf666d RD |
1162 | // property lexer.errorlist.value.separate |
1163 | // For lines in the output pane that are matches from Find in Files or GCC-style | |
1164 | // diagnostics, style the path and line number separately from the rest of the | |
1165 | // line with style 21 used for the rest of the line. | |
1166 | // This allows matched text to be more easily distinguished from its location. | |
7e0c58e9 | 1167 | bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0; |
1a2fb4cd | 1168 | for (unsigned int i = startPos; i < startPos + length; i++) { |
f6bcfd97 | 1169 | lineBuffer[linePos++] = styler[i]; |
1a2fb4cd RD |
1170 | if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { |
1171 | // End of line (or of line buffer) met, colourise it | |
1172 | lineBuffer[linePos] = '\0'; | |
7e0c58e9 | 1173 | ColouriseErrorListLine(lineBuffer, linePos, i, styler, valueSeparate); |
f6bcfd97 BP |
1174 | linePos = 0; |
1175 | } | |
1176 | } | |
1a2fb4cd | 1177 | if (linePos > 0) { // Last line does not have ending characters |
7e0c58e9 | 1178 | ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler, valueSeparate); |
1a2fb4cd | 1179 | } |
f6bcfd97 BP |
1180 | } |
1181 | ||
1dcf666d RD |
1182 | static bool latexIsSpecial(int ch) { |
1183 | return (ch == '#') || (ch == '$') || (ch == '%') || (ch == '&') || (ch == '_') || | |
1184 | (ch == '{') || (ch == '}') || (ch == ' '); | |
1185 | } | |
1186 | ||
1187 | static bool latexIsBlank(int ch) { | |
1188 | return (ch == ' ') || (ch == '\t'); | |
f6bcfd97 BP |
1189 | } |
1190 | ||
1dcf666d RD |
1191 | static bool latexIsBlankAndNL(int ch) { |
1192 | return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'); | |
1193 | } | |
1194 | ||
1195 | static bool latexIsLetter(int ch) { | |
1196 | return isascii(ch) && isalpha(ch); | |
1197 | } | |
1198 | ||
1199 | static bool latexIsTagValid(int &i, int l, Accessor &styler) { | |
1200 | while (i < l) { | |
1201 | if (styler.SafeGetCharAt(i) == '{') { | |
1202 | while (i < l) { | |
1203 | i++; | |
1204 | if (styler.SafeGetCharAt(i) == '}') { | |
1205 | return true; | |
1206 | } else if (!latexIsLetter(styler.SafeGetCharAt(i)) && | |
1207 | styler.SafeGetCharAt(i)!='*') { | |
1208 | return false; | |
1209 | } | |
1210 | } | |
1211 | } else if (!latexIsBlank(styler.SafeGetCharAt(i))) { | |
1212 | return false; | |
1213 | } | |
f6bcfd97 | 1214 | i++; |
1dcf666d RD |
1215 | } |
1216 | return false; | |
1217 | } | |
1218 | ||
1219 | static bool latexNextNotBlankIs(int i, int l, Accessor &styler, char needle) { | |
1220 | char ch; | |
1221 | while (i < l) { | |
1222 | ch = styler.SafeGetCharAt(i); | |
1223 | if (!latexIsBlankAndNL(ch) && ch != '*') { | |
1224 | if (ch == needle) | |
1225 | return true; | |
1226 | else | |
1227 | return false; | |
1228 | } | |
1229 | i++; | |
1230 | } | |
1231 | return false; | |
1232 | } | |
1233 | ||
1234 | static bool latexLastWordIs(int start, Accessor &styler, const char *needle) { | |
1235 | unsigned int i = 0; | |
1236 | unsigned int l = static_cast<unsigned int>(strlen(needle)); | |
1237 | int ini = start-l+1; | |
1238 | char s[32]; | |
1239 | ||
1240 | while (i < l && i < 32) { | |
1241 | s[i] = styler.SafeGetCharAt(ini + i); | |
1242 | i++; | |
f6bcfd97 BP |
1243 | } |
1244 | s[i] = '\0'; | |
1dcf666d RD |
1245 | |
1246 | return (strcmp(s, needle) == 0); | |
f6bcfd97 BP |
1247 | } |
1248 | ||
1249 | static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle, | |
65ec6247 | 1250 | WordList *[], Accessor &styler) { |
f6bcfd97 BP |
1251 | |
1252 | styler.StartAt(startPos); | |
1253 | ||
1254 | int state = initStyle; | |
1dcf666d | 1255 | char chNext = styler.SafeGetCharAt(startPos); |
f6bcfd97 BP |
1256 | styler.StartSegment(startPos); |
1257 | int lengthDoc = startPos + length; | |
1dcf666d | 1258 | char chVerbatimDelim = '\0'; |
f6bcfd97 BP |
1259 | |
1260 | for (int i = startPos; i < lengthDoc; i++) { | |
1261 | char ch = chNext; | |
1262 | chNext = styler.SafeGetCharAt(i + 1); | |
1263 | ||
1264 | if (styler.IsLeadByte(ch)) { | |
f6bcfd97 | 1265 | i++; |
1dcf666d | 1266 | chNext = styler.SafeGetCharAt(i + 1); |
f6bcfd97 BP |
1267 | continue; |
1268 | } | |
1dcf666d | 1269 | |
65ec6247 RD |
1270 | switch (state) { |
1271 | case SCE_L_DEFAULT : | |
1272 | switch (ch) { | |
1273 | case '\\' : | |
1274 | styler.ColourTo(i - 1, state); | |
1dcf666d RD |
1275 | if (latexIsSpecial(chNext)) { |
1276 | state = SCE_L_SPECIAL; | |
65ec6247 | 1277 | } else { |
1dcf666d | 1278 | if (latexIsLetter(chNext)) { |
65ec6247 | 1279 | state = SCE_L_COMMAND; |
1dcf666d RD |
1280 | } else { |
1281 | if (chNext == '(' || chNext == '[') { | |
1282 | styler.ColourTo(i-1, state); | |
1283 | styler.ColourTo(i+1, SCE_L_SHORTCMD); | |
1284 | state = SCE_L_MATH; | |
1285 | if (chNext == '[') | |
1286 | state = SCE_L_MATH2; | |
1287 | i++; | |
1288 | chNext = styler.SafeGetCharAt(i+1); | |
1289 | } else { | |
1290 | state = SCE_L_SHORTCMD; | |
1291 | } | |
1292 | } | |
f6bcfd97 BP |
1293 | } |
1294 | break; | |
65ec6247 RD |
1295 | case '$' : |
1296 | styler.ColourTo(i - 1, state); | |
1297 | state = SCE_L_MATH; | |
1298 | if (chNext == '$') { | |
1dcf666d | 1299 | state = SCE_L_MATH2; |
65ec6247 RD |
1300 | i++; |
1301 | chNext = styler.SafeGetCharAt(i + 1); | |
f6bcfd97 BP |
1302 | } |
1303 | break; | |
65ec6247 RD |
1304 | case '%' : |
1305 | styler.ColourTo(i - 1, state); | |
1306 | state = SCE_L_COMMENT; | |
1307 | break; | |
1308 | } | |
1309 | break; | |
1dcf666d RD |
1310 | case SCE_L_ERROR: |
1311 | styler.ColourTo(i-1, state); | |
1312 | state = SCE_L_DEFAULT; | |
1313 | break; | |
1314 | case SCE_L_SPECIAL: | |
1315 | case SCE_L_SHORTCMD: | |
1316 | styler.ColourTo(i, state); | |
1317 | state = SCE_L_DEFAULT; | |
1318 | break; | |
65ec6247 | 1319 | case SCE_L_COMMAND : |
1dcf666d | 1320 | if (!latexIsLetter(chNext)) { |
65ec6247 RD |
1321 | styler.ColourTo(i, state); |
1322 | state = SCE_L_DEFAULT; | |
1dcf666d RD |
1323 | if (latexNextNotBlankIs(i+1, lengthDoc, styler, '[' )) { |
1324 | state = SCE_L_CMDOPT; | |
1325 | } else if (latexLastWordIs(i, styler, "\\begin")) { | |
1326 | state = SCE_L_TAG; | |
1327 | } else if (latexLastWordIs(i, styler, "\\end")) { | |
1328 | state = SCE_L_TAG2; | |
1329 | } else if (latexLastWordIs(i, styler, "\\verb") && | |
1330 | chNext != '*' && chNext != ' ') { | |
1331 | chVerbatimDelim = chNext; | |
1332 | state = SCE_L_VERBATIM; | |
1333 | } | |
65ec6247 RD |
1334 | } |
1335 | break; | |
1dcf666d RD |
1336 | case SCE_L_CMDOPT : |
1337 | if (ch == ']') { | |
1338 | styler.ColourTo(i, state); | |
1339 | state = SCE_L_DEFAULT; | |
1340 | } | |
1341 | break; | |
65ec6247 | 1342 | case SCE_L_TAG : |
1dcf666d RD |
1343 | if (latexIsTagValid(i, lengthDoc, styler)) { |
1344 | styler.ColourTo(i, state); | |
1345 | state = SCE_L_DEFAULT; | |
1346 | if (latexLastWordIs(i, styler, "{verbatim}")) { | |
1347 | state = SCE_L_VERBATIM; | |
1348 | } else if (latexLastWordIs(i, styler, "{comment}")) { | |
1349 | state = SCE_L_COMMENT2; | |
1350 | } else if (latexLastWordIs(i, styler, "{math}")) { | |
1351 | state = SCE_L_MATH; | |
1352 | } else if (latexLastWordIs(i, styler, "{displaymath}")) { | |
1353 | state = SCE_L_MATH2; | |
1354 | } else if (latexLastWordIs(i, styler, "{equation}")) { | |
1355 | state = SCE_L_MATH2; | |
1356 | } | |
1357 | } else { | |
1358 | state = SCE_L_ERROR; | |
65ec6247 RD |
1359 | styler.ColourTo(i, state); |
1360 | state = SCE_L_DEFAULT; | |
1361 | } | |
1dcf666d RD |
1362 | chNext = styler.SafeGetCharAt(i+1); |
1363 | break; | |
1364 | case SCE_L_TAG2 : | |
1365 | if (latexIsTagValid(i, lengthDoc, styler)) { | |
1366 | styler.ColourTo(i, state); | |
1367 | state = SCE_L_DEFAULT; | |
1368 | } else { | |
1369 | state = SCE_L_ERROR; | |
1370 | } | |
1371 | chNext = styler.SafeGetCharAt(i+1); | |
65ec6247 RD |
1372 | break; |
1373 | case SCE_L_MATH : | |
1374 | if (ch == '$') { | |
65ec6247 RD |
1375 | styler.ColourTo(i, state); |
1376 | state = SCE_L_DEFAULT; | |
1dcf666d RD |
1377 | } else if (ch == '\\' && chNext == ')') { |
1378 | styler.ColourTo(i-1, state); | |
1379 | styler.ColourTo(i+1, SCE_L_SHORTCMD); | |
1380 | i++; | |
1381 | chNext = styler.SafeGetCharAt(i+1); | |
1382 | state = SCE_L_DEFAULT; | |
1383 | } else if (ch == '\\') { | |
1384 | int match = i + 3; | |
1385 | if (latexLastWordIs(match, styler, "\\end")) { | |
1386 | match++; | |
1387 | if (latexIsTagValid(match, lengthDoc, styler)) { | |
1388 | if (latexLastWordIs(match, styler, "{math}")) { | |
1389 | styler.ColourTo(i-1, state); | |
1390 | state = SCE_L_COMMAND; | |
1391 | } | |
1392 | } | |
1393 | } | |
1394 | } | |
1395 | ||
1396 | break; | |
1397 | case SCE_L_MATH2 : | |
1398 | if (ch == '$') { | |
1399 | if (chNext == '$') { | |
1400 | i++; | |
1401 | chNext = styler.SafeGetCharAt(i + 1); | |
1402 | styler.ColourTo(i, state); | |
1403 | state = SCE_L_DEFAULT; | |
1404 | } else { | |
1405 | styler.ColourTo(i, SCE_L_ERROR); | |
1406 | state = SCE_L_DEFAULT; | |
1407 | } | |
1408 | } else if (ch == '\\' && chNext == ']') { | |
1409 | styler.ColourTo(i-1, state); | |
1410 | styler.ColourTo(i+1, SCE_L_SHORTCMD); | |
1411 | i++; | |
1412 | chNext = styler.SafeGetCharAt(i+1); | |
1413 | state = SCE_L_DEFAULT; | |
1414 | } else if (ch == '\\') { | |
1415 | int match = i + 3; | |
1416 | if (latexLastWordIs(match, styler, "\\end")) { | |
1417 | match++; | |
1418 | if (latexIsTagValid(match, lengthDoc, styler)) { | |
1419 | if (latexLastWordIs(match, styler, "{displaymath}")) { | |
1420 | styler.ColourTo(i-1, state); | |
1421 | state = SCE_L_COMMAND; | |
1422 | } else if (latexLastWordIs(match, styler, "{equation}")) { | |
1423 | styler.ColourTo(i-1, state); | |
1424 | state = SCE_L_COMMAND; | |
1425 | } | |
1426 | } | |
1427 | } | |
65ec6247 RD |
1428 | } |
1429 | break; | |
1430 | case SCE_L_COMMENT : | |
1431 | if (ch == '\r' || ch == '\n') { | |
1432 | styler.ColourTo(i - 1, state); | |
1433 | state = SCE_L_DEFAULT; | |
1434 | } | |
1dcf666d RD |
1435 | break; |
1436 | case SCE_L_COMMENT2 : | |
1437 | if (ch == '\\') { | |
1438 | int match = i + 3; | |
1439 | if (latexLastWordIs(match, styler, "\\end")) { | |
1440 | match++; | |
1441 | if (latexIsTagValid(match, lengthDoc, styler)) { | |
1442 | if (latexLastWordIs(match, styler, "{comment}")) { | |
1443 | styler.ColourTo(i-1, state); | |
1444 | state = SCE_L_COMMAND; | |
1445 | } | |
1446 | } | |
1447 | } | |
1448 | } | |
1449 | break; | |
1450 | case SCE_L_VERBATIM : | |
1451 | if (ch == '\\') { | |
1452 | int match = i + 3; | |
1453 | if (latexLastWordIs(match, styler, "\\end")) { | |
1454 | match++; | |
1455 | if (latexIsTagValid(match, lengthDoc, styler)) { | |
1456 | if (latexLastWordIs(match, styler, "{verbatim}")) { | |
1457 | styler.ColourTo(i-1, state); | |
1458 | state = SCE_L_COMMAND; | |
1459 | } | |
1460 | } | |
1461 | } | |
1462 | } else if (chNext == chVerbatimDelim) { | |
1463 | styler.ColourTo(i+1, state); | |
1464 | state = SCE_L_DEFAULT; | |
1465 | chVerbatimDelim = '\0'; | |
1466 | } else if (chVerbatimDelim != '\0' && (ch == '\n' || ch == '\r')) { | |
1467 | styler.ColourTo(i, SCE_L_ERROR); | |
1468 | state = SCE_L_DEFAULT; | |
1469 | chVerbatimDelim = '\0'; | |
1470 | } | |
1471 | break; | |
65ec6247 | 1472 | } |
f6bcfd97 | 1473 | } |
9e730a78 | 1474 | styler.ColourTo(lengthDoc-1, state); |
f6bcfd97 BP |
1475 | } |
1476 | ||
1dcf666d | 1477 | static const char *const batchWordListDesc[] = { |
b8193d80 RD |
1478 | "Internal Commands", |
1479 | "External Commands", | |
9e730a78 RD |
1480 | 0 |
1481 | }; | |
1482 | ||
1dcf666d | 1483 | static const char *const emptyWordListDesc[] = { |
9e730a78 RD |
1484 | 0 |
1485 | }; | |
1486 | ||
e14d10b0 RD |
1487 | static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[], |
1488 | Accessor &styler) { | |
1489 | // Null language means all style bytes are 0 so just mark the end - no need to fill in. | |
1490 | if (length > 0) { | |
1491 | styler.StartAt(startPos + length - 1); | |
1492 | styler.StartSegment(startPos + length - 1); | |
1493 | styler.ColourTo(startPos + length - 1, 0); | |
1494 | } | |
1495 | } | |
1496 | ||
9e730a78 | 1497 | LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc); |
591d01be | 1498 | LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordListDesc); |
9e96e16f | 1499 | LexerModule lmPo(SCLEX_PO, ColourisePoDoc, "po", 0, emptyWordListDesc); |
88a8b04e | 1500 | LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc); |
9e730a78 RD |
1501 | LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc); |
1502 | LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc); | |
1503 | LexerModule lmLatex(SCLEX_LATEX, ColouriseLatexDoc, "latex", 0, emptyWordListDesc); | |
e14d10b0 | 1504 | LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null"); |