]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/LexCPP.cxx
661b968cd75c3138b798bea9c369027e73a08367
[wxWidgets.git] / contrib / src / stc / scintilla / src / LexCPP.cxx
1 // Scintilla source code edit control
2 /** @file LexCPP.cxx
3 ** Lexer for C++, C, Java, and Javascript.
4 **/
5 // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
6 // The License.txt file describes the conditions under which this software may be distributed.
7
8 #include <stdlib.h>
9 #include <string.h>
10 #include <ctype.h>
11 #include <stdio.h>
12 #include <stdarg.h>
13
14 #include "Platform.h"
15
16 #include "PropSet.h"
17 #include "Accessor.h"
18 #include "StyleContext.h"
19 #include "KeyWords.h"
20 #include "Scintilla.h"
21 #include "SciLexer.h"
22
23 #define KEYWORD_BOXHEADER 1
24 #define KEYWORD_FOLDCONTRACTED 2
25
26 static bool IsOKBeforeRE(const int ch) {
27 return (ch == '(') || (ch == '=') || (ch == ',');
28 }
29
30 static inline bool IsAWordChar(const int ch) {
31 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
32 }
33
34 static inline bool IsAWordStart(const int ch) {
35 return (ch < 0x80) && (isalnum(ch) || ch == '_');
36 }
37
38 static inline bool IsADoxygenChar(const int ch) {
39 return (islower(ch) || ch == '$' || ch == '@' ||
40 ch == '\\' || ch == '&' || ch == '<' ||
41 ch == '>' || ch == '#' || ch == '{' ||
42 ch == '}' || ch == '[' || ch == ']');
43 }
44
45 static inline bool IsStateComment(const int state) {
46 return ((state == SCE_C_COMMENT) ||
47 (state == SCE_C_COMMENTLINE) ||
48 (state == SCE_C_COMMENTDOC) ||
49 (state == SCE_C_COMMENTDOCKEYWORD) ||
50 (state == SCE_C_COMMENTDOCKEYWORDERROR));
51 }
52
53 static inline bool IsStateString(const int state) {
54 return ((state == SCE_C_STRING) || (state == SCE_C_VERBATIM));
55 }
56
57 static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
58 Accessor &styler, bool caseSensitive) {
59
60 WordList &keywords = *keywordlists[0];
61 WordList &keywords2 = *keywordlists[1];
62 WordList &keywords3 = *keywordlists[2];
63
64 bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;
65
66 // Do not leak onto next line
67 if (initStyle == SCE_C_STRINGEOL)
68 initStyle = SCE_C_DEFAULT;
69
70 int chPrevNonWhite = ' ';
71 int visibleChars = 0;
72 bool lastWordWasUUID = false;
73
74 StyleContext sc(startPos, length, initStyle, styler);
75
76 for (; sc.More(); sc.Forward()) {
77
78 if (sc.atLineStart && (sc.state == SCE_C_STRING)) {
79 // Prevent SCE_C_STRINGEOL from leaking back to previous line
80 sc.SetState(SCE_C_STRING);
81 }
82
83 // Handle line continuation generically.
84 if (sc.ch == '\\') {
85 if (sc.chNext == '\n' || sc.chNext == '\r') {
86 sc.Forward();
87 if (sc.ch == '\r' && sc.chNext == '\n') {
88 sc.Forward();
89 }
90 continue;
91 }
92 }
93
94 // Determine if the current state should terminate.
95 if (sc.state == SCE_C_OPERATOR) {
96 sc.SetState(SCE_C_DEFAULT);
97 } else if (sc.state == SCE_C_NUMBER) {
98 if (!IsAWordChar(sc.ch)) {
99 sc.SetState(SCE_C_DEFAULT);
100 }
101 } else if (sc.state == SCE_C_IDENTIFIER) {
102 if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
103 char s[100];
104 if (caseSensitive) {
105 sc.GetCurrent(s, sizeof(s));
106 } else {
107 sc.GetCurrentLowered(s, sizeof(s));
108 }
109 if (keywords.InList(s)) {
110 lastWordWasUUID = strcmp(s, "uuid") == 0;
111 sc.ChangeState(SCE_C_WORD);
112 } else if (keywords2.InList(s)) {
113 sc.ChangeState(SCE_C_WORD2);
114 }
115 sc.SetState(SCE_C_DEFAULT);
116 }
117 } else if (sc.state == SCE_C_PREPROCESSOR) {
118 if (stylingWithinPreprocessor) {
119 if (IsASpace(sc.ch)) {
120 sc.SetState(SCE_C_DEFAULT);
121 }
122 } else {
123 if ((sc.atLineEnd) || (sc.Match('/', '*')) || (sc.Match('/', '/'))) {
124 sc.SetState(SCE_C_DEFAULT);
125 }
126 }
127 } else if (sc.state == SCE_C_COMMENT) {
128 if (sc.Match('*', '/')) {
129 sc.Forward();
130 sc.ForwardSetState(SCE_C_DEFAULT);
131 }
132 } else if (sc.state == SCE_C_COMMENTDOC) {
133 if (sc.Match('*', '/')) {
134 sc.Forward();
135 sc.ForwardSetState(SCE_C_DEFAULT);
136 } else if (sc.ch == '@' || sc.ch == '\\') {
137 sc.SetState(SCE_C_COMMENTDOCKEYWORD);
138 }
139 } else if (sc.state == SCE_C_COMMENTLINE || sc.state == SCE_C_COMMENTLINEDOC) {
140 if (sc.atLineEnd) {
141 sc.SetState(SCE_C_DEFAULT);
142 visibleChars = 0;
143 }
144 } else if (sc.state == SCE_C_COMMENTDOCKEYWORD) {
145 if (sc.Match('*', '/')) {
146 sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
147 sc.Forward();
148 sc.ForwardSetState(SCE_C_DEFAULT);
149 } else if (!IsADoxygenChar(sc.ch)) {
150 char s[100];
151 if (caseSensitive) {
152 sc.GetCurrent(s, sizeof(s));
153 } else {
154 sc.GetCurrentLowered(s, sizeof(s));
155 }
156 if (!isspace(sc.ch) || !keywords3.InList(s + 1)) {
157 sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
158 }
159 sc.SetState(SCE_C_COMMENTDOC);
160 }
161 } else if (sc.state == SCE_C_STRING) {
162 if (sc.ch == '\\') {
163 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
164 sc.Forward();
165 }
166 } else if (sc.ch == '\"') {
167 sc.ForwardSetState(SCE_C_DEFAULT);
168 } else if (sc.atLineEnd) {
169 sc.ChangeState(SCE_C_STRINGEOL);
170 sc.ForwardSetState(SCE_C_DEFAULT);
171 visibleChars = 0;
172 }
173 } else if (sc.state == SCE_C_CHARACTER) {
174 if (sc.atLineEnd) {
175 sc.ChangeState(SCE_C_STRINGEOL);
176 sc.ForwardSetState(SCE_C_DEFAULT);
177 visibleChars = 0;
178 } else if (sc.ch == '\\') {
179 if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
180 sc.Forward();
181 }
182 } else if (sc.ch == '\'') {
183 sc.ForwardSetState(SCE_C_DEFAULT);
184 }
185 } else if (sc.state == SCE_C_REGEX) {
186 if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == '/') {
187 sc.ForwardSetState(SCE_C_DEFAULT);
188 } else if (sc.ch == '\\') {
189 // Gobble up the quoted character
190 if (sc.chNext == '\\' || sc.chNext == '/') {
191 sc.Forward();
192 }
193 }
194 } else if (sc.state == SCE_C_VERBATIM) {
195 if (sc.ch == '\"') {
196 if (sc.chNext == '\"') {
197 sc.Forward();
198 } else {
199 sc.ForwardSetState(SCE_C_DEFAULT);
200 }
201 }
202 } else if (sc.state == SCE_C_UUID) {
203 if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
204 sc.SetState(SCE_C_DEFAULT);
205 }
206 }
207
208 // Determine if a new state should be entered.
209 if (sc.state == SCE_C_DEFAULT) {
210 if (sc.Match('@', '\"')) {
211 sc.SetState(SCE_C_VERBATIM);
212 sc.Forward();
213 } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
214 if (lastWordWasUUID) {
215 sc.SetState(SCE_C_UUID);
216 lastWordWasUUID = false;
217 } else {
218 sc.SetState(SCE_C_NUMBER);
219 }
220 } else if (IsAWordStart(sc.ch) || (sc.ch == '@')) {
221 if (lastWordWasUUID) {
222 sc.SetState(SCE_C_UUID);
223 lastWordWasUUID = false;
224 } else {
225 sc.SetState(SCE_C_IDENTIFIER);
226 }
227 } else if (sc.Match('/', '*')) {
228 if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style
229 sc.SetState(SCE_C_COMMENTDOC);
230 } else {
231 sc.SetState(SCE_C_COMMENT);
232 }
233 sc.Forward(); // Eat the * so it isn't used for the end of the comment
234 } else if (sc.Match('/', '/')) {
235 if (sc.Match("///") || sc.Match("//!")) // Support of Qt/Doxygen doc. style
236 sc.SetState(SCE_C_COMMENTLINEDOC);
237 else
238 sc.SetState(SCE_C_COMMENTLINE);
239 } else if (sc.ch == '/' && IsOKBeforeRE(chPrevNonWhite)) {
240 sc.SetState(SCE_C_REGEX);
241 } else if (sc.ch == '\"') {
242 sc.SetState(SCE_C_STRING);
243 } else if (sc.ch == '\'') {
244 sc.SetState(SCE_C_CHARACTER);
245 } else if (sc.ch == '#' && visibleChars == 0) {
246 // Preprocessor commands are alone on their line
247 sc.SetState(SCE_C_PREPROCESSOR);
248 // Skip whitespace between # and preprocessor word
249 do {
250 sc.Forward();
251 } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
252 if (sc.atLineEnd) {
253 sc.SetState(SCE_C_DEFAULT);
254 }
255 } else if (isoperator(static_cast<char>(sc.ch))) {
256 sc.SetState(SCE_C_OPERATOR);
257 }
258 }
259
260 if (sc.atLineEnd) {
261 // Reset states to begining of colourise so no surprises
262 // if different sets of lines lexed.
263 chPrevNonWhite = ' ';
264 visibleChars = 0;
265 lastWordWasUUID = false;
266 }
267 if (!IsASpace(sc.ch)) {
268 chPrevNonWhite = sc.ch;
269 visibleChars++;
270 }
271 }
272 sc.Complete();
273 }
274
275 static bool IsStreamCommentStyle(int style) {
276 return style == SCE_C_COMMENT ||
277 style == SCE_C_COMMENTDOC ||
278 style == SCE_C_COMMENTDOCKEYWORD ||
279 style == SCE_C_COMMENTDOCKEYWORDERROR;
280 }
281
282 static bool matchKeyword(unsigned int start, WordList &keywords, Accessor &styler, int keywordtype) {
283 bool FoundKeyword = false;
284
285 for (unsigned int i = 0;
286 strlen(keywords[i]) > 0 && !FoundKeyword;
287 i++) {
288 if (atoi(keywords[i]) == keywordtype) {
289 FoundKeyword = styler.Match(start, ((char *)keywords[i]) + 2);
290 }
291 }
292 return FoundKeyword;
293 }
294
295 static bool IsCommentLine(int line, Accessor &styler) {
296 unsigned int Pos = styler.LineStart(line);
297 while (styler.GetLine(Pos) == line) {
298 int PosStyle = styler.StyleAt(Pos);
299
300 if ( !IsStreamCommentStyle(PosStyle)
301 &&
302 PosStyle != SCE_C_COMMENTLINEDOC
303 &&
304 PosStyle != SCE_C_COMMENTLINE
305 &&
306 !IsASpace(styler.SafeGetCharAt(Pos))
307 )
308 return false;
309 Pos++;
310 }
311
312 return true;
313 }
314
315 static void FoldBoxCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
316 Accessor &styler) {
317
318 WordList &keywords4 = *keywordlists[3];
319
320 bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
321 bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
322 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
323 bool firstLine = true;
324 unsigned int endPos = startPos + length;
325 int visibleChars = 0;
326 int lineCurrent = styler.GetLine(startPos);
327 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
328 int levelCurrent = levelPrev;
329 int levelPrevPrev;
330 int levelFlags = 0;
331 int levelUnindent = 0;
332 char chNext = styler[startPos];
333 int styleNext = styler.StyleAt(startPos);
334 int style = initStyle;
335
336 if (lineCurrent == 0) {
337 levelPrevPrev = levelPrev;
338 } else {
339 levelPrevPrev = styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK;
340 }
341
342 for (unsigned int i = startPos; i < endPos; i++) {
343 char ch = chNext;
344 chNext = styler.SafeGetCharAt(i + 1);
345 int stylePrev = style;
346 style = styleNext;
347 styleNext = styler.StyleAt(i + 1);
348
349 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
350
351 if (foldComment && IsStreamCommentStyle(style)) {
352 if (!IsStreamCommentStyle(stylePrev)) {
353 levelCurrent++;
354 } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
355 // Comments don't end at end of line and the next character may be unstyled.
356 levelCurrent--;
357 }
358 }
359
360 if (foldComment && (style == SCE_C_COMMENTLINE)) {
361 if ((ch == '/') && (chNext == '/')) {
362 char chNext2 = styler.SafeGetCharAt(i + 2);
363 if (chNext2 == '{') {
364 levelCurrent++;
365 } else if (chNext2 == '}') {
366 levelCurrent--;
367 }
368 }
369 }
370
371 if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
372 if (ch == '#') {
373 unsigned int j = i + 1;
374 while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
375 j++;
376 }
377
378 if (styler.Match(j, "region") || styler.Match(j, "if")) {
379 levelCurrent++;
380 } else if (styler.Match(j, "end")) {
381 levelCurrent--;
382 }
383 }
384 }
385
386 if (style == SCE_C_OPERATOR
387 ||
388 style == SCE_C_COMMENT
389 ||
390 style == SCE_C_COMMENTLINE) {
391
392 if (ch == '{') {
393 levelCurrent++;
394 // Special handling if line has closing brace followed by opening brace.
395 if (levelCurrent == levelPrev) {
396 if (firstLine)
397 levelUnindent = 1;
398 else
399 levelUnindent = -1;
400 }
401 } else if (ch == '}') {
402 levelCurrent--;
403 }
404 }
405
406 /* Check for fold header keyword at beginning of word */
407 if ((style == SCE_C_WORD || style == SCE_C_COMMENT || style == SCE_C_COMMENTLINE)
408 &&
409 (style != stylePrev)) {
410 if (matchKeyword(i, keywords4, styler, KEYWORD_BOXHEADER)) {
411 int line;
412 /* Loop backwards all empty or comment lines */
413 for (line = lineCurrent - 1;
414 line >= 0
415 &&
416 levelCurrent == (styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK)
417 &&
418 (styler.LevelAt(line) & SC_FOLDLEVELBOXFOOTERFLAG) == 0
419 &&
420 IsCommentLine(line, styler);
421 line--) {
422 /* just loop backwards */;
423 }
424
425 line++;
426 /* Set Box header flag (if the previous line has no footer line) */
427 if ((styler.LevelAt(line) & SC_FOLDLEVELBOXFOOTERFLAG) == 0) {
428 if (line == lineCurrent) {
429 /* in current line */
430 levelFlags |= SC_FOLDLEVELBOXHEADERFLAG;
431 } else {
432 /* at top of all preceding comment lines */
433 styler.SetLevel(line, styler.LevelAt(line)
434 | SC_FOLDLEVELBOXHEADERFLAG);
435 }
436 }
437 }
438 }
439
440 if (matchKeyword(i, keywords4, styler, KEYWORD_FOLDCONTRACTED)) {
441 levelFlags |= SC_FOLDLEVELCONTRACTED;
442 }
443
444 if (atEOL) {
445 int lev;
446 // Compute level correction for special case: '} else {'
447 if (levelUnindent < 0) {
448 levelPrev += levelUnindent;
449 } else {
450 levelCurrent += levelUnindent;
451 }
452
453 lev = levelPrev;
454 if (visibleChars == 0 && foldCompact)
455 lev |= SC_FOLDLEVELWHITEFLAG;
456 // Produce additional footer line (e.g. after closed if)
457 if (visibleChars == 0
458 &&
459 (levelPrev < levelPrevPrev))
460 lev |= SC_FOLDLEVELBOXFOOTERFLAG;
461 // Produce footer line at line before (special handling for '} else {'
462 if (levelPrev < levelPrevPrev) {
463 styler.SetLevel(lineCurrent - 1,
464 styler.LevelAt(lineCurrent - 1) | SC_FOLDLEVELBOXFOOTERFLAG);
465 }
466 // Mark the fold header (the line that is always visible)
467 if ((levelCurrent > levelPrev) && (visibleChars > 0))
468 lev |= SC_FOLDLEVELHEADERFLAG;
469 // Show a footer line at end of fold
470 if (levelCurrent < levelPrev)
471 lev |= SC_FOLDLEVELBOXFOOTERFLAG;
472 /* Show a footer line at the end of each procedure (level == SC_FOLDLEVELBASE) */
473 if ((levelPrev == SC_FOLDLEVELBASE)
474 &&
475 (levelPrevPrev > SC_FOLDLEVELBASE)
476 &&
477 (visibleChars == 0)) {
478 lev |= SC_FOLDLEVELBOXFOOTERFLAG;
479 }
480
481 lev |= levelFlags;
482 if (lev != styler.LevelAt(lineCurrent)) {
483 styler.SetLevel(lineCurrent, lev);
484 }
485
486 lineCurrent++;
487 levelPrevPrev = levelPrev;
488 levelPrev = levelCurrent;
489 levelUnindent = 0;
490 visibleChars = 0;
491 levelFlags = 0;
492 firstLine = false;
493 }
494
495 if (!isspacechar(ch))
496 visibleChars++;
497 }
498 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
499 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
500 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
501 }
502
503 static void FoldNoBoxCppDoc(unsigned int startPos, int length, int initStyle,
504 Accessor &styler) {
505 bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
506 bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
507 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
508 unsigned int endPos = startPos + length;
509 int visibleChars = 0;
510 int lineCurrent = styler.GetLine(startPos);
511 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
512 int levelCurrent = levelPrev;
513 char chNext = styler[startPos];
514 int styleNext = styler.StyleAt(startPos);
515 int style = initStyle;
516 for (unsigned int i = startPos; i < endPos; i++) {
517 char ch = chNext;
518 chNext = styler.SafeGetCharAt(i + 1);
519 int stylePrev = style;
520 style = styleNext;
521 styleNext = styler.StyleAt(i + 1);
522 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
523 if (foldComment && IsStreamCommentStyle(style)) {
524 if (!IsStreamCommentStyle(stylePrev)) {
525 levelCurrent++;
526 } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
527 // Comments don't end at end of line and the next character may be unstyled.
528 levelCurrent--;
529 }
530 }
531 if (foldComment && (style == SCE_C_COMMENTLINE)) {
532 if ((ch == '/') && (chNext == '/')) {
533 char chNext2 = styler.SafeGetCharAt(i + 2);
534 if (chNext2 == '{') {
535 levelCurrent++;
536 } else if (chNext2 == '}') {
537 levelCurrent--;
538 }
539 }
540 }
541 if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) {
542 if (ch == '#') {
543 unsigned int j = i + 1;
544 while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
545 j++;
546 }
547 if (styler.Match(j, "region") || styler.Match(j, "if")) {
548 levelCurrent++;
549 } else if (styler.Match(j, "end")) {
550 levelCurrent--;
551 }
552 }
553 }
554 if (style == SCE_C_OPERATOR) {
555 if (ch == '{') {
556 levelCurrent++;
557 } else if (ch == '}') {
558 levelCurrent--;
559 }
560 }
561 if (atEOL) {
562 int lev = levelPrev;
563 if (visibleChars == 0 && foldCompact)
564 lev |= SC_FOLDLEVELWHITEFLAG;
565 if ((levelCurrent > levelPrev) && (visibleChars > 0))
566 lev |= SC_FOLDLEVELHEADERFLAG;
567 if (lev != styler.LevelAt(lineCurrent)) {
568 styler.SetLevel(lineCurrent, lev);
569 }
570 lineCurrent++;
571 levelPrev = levelCurrent;
572 visibleChars = 0;
573 }
574 if (!isspacechar(ch))
575 visibleChars++;
576 }
577 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
578 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
579 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
580 }
581
582 static void FoldCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
583 Accessor &styler) {
584
585 int foldFlags = styler.GetPropertyInt("fold.flags") ;
586 bool foldBox = ((foldFlags & SC_FOLDFLAG_BOX) == SC_FOLDFLAG_BOX);
587
588 if (foldBox) {
589 FoldBoxCppDoc(startPos, length, initStyle, keywordlists, styler);
590 } else {
591 FoldNoBoxCppDoc(startPos, length, initStyle, styler);
592 }
593 }
594
595 static const char * const cppWordLists[] = {
596 "Primary keywords and identifiers",
597 "Secondary keywords and identifiers",
598 "Documentation comment keywords",
599 "Fold header keywords",
600 0,
601 };
602
603 static void ColouriseCppDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
604 Accessor &styler) {
605 ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler, true);
606 }
607
608 static void ColouriseCppDocInsensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
609 Accessor &styler) {
610 ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler, false);
611 }
612
613 LexerModule lmCPP(SCLEX_CPP, ColouriseCppDocSensitive, "cpp", FoldCppDoc, cppWordLists);
614 LexerModule lmCPPNoCase(SCLEX_CPPNOCASE, ColouriseCppDocInsensitive, "cppnocase", FoldCppDoc, cppWordLists);
615 LexerModule lmTCL(SCLEX_TCL, ColouriseCppDocSensitive, "tcl", FoldCppDoc, cppWordLists);