]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/stc/scintilla/lexers/LexPascal.cxx
Add missing WXK constants for the control keys
[wxWidgets.git] / src / stc / scintilla / lexers / LexPascal.cxx
... / ...
CommitLineData
1// Scintilla source code edit control
2/** @file LexPascal.cxx
3 ** Lexer for Pascal.
4 ** Written by Laurent le Tynevez
5 ** Updated by Simon Steele <s.steele@pnotepad.org> September 2002
6 ** Updated by Mathias Rauen <scite@madshi.net> May 2003 (Delphi adjustments)
7 ** Completely rewritten by Marko Njezic <sf@maxempire.com> October 2008
8 **/
9
10/*
11
12A few words about features of the new completely rewritten LexPascal...
13
14Generally speaking LexPascal tries to support all available Delphi features (up
15to Delphi 2009 at this time), including .NET specific features.
16
17~ HIGHLIGHTING:
18
19If you enable "lexer.pascal.smart.highlighting" property, some keywords will
20only be highlighted in appropriate context. As implemented those are keywords
21related to property and DLL exports declarations (similar to how Delphi IDE
22works).
23
24For example, keywords "read" and "write" will only be highlighted if they are in
25property declaration:
26
27property MyProperty: boolean read FMyProperty write FMyProperty;
28
29~ FOLDING:
30
31Folding is supported in the following cases:
32
33- Folding of stream-like comments
34- Folding of groups of consecutive line comments
35- Folding of preprocessor blocks (the following preprocessor blocks are
36supported: IF / IFEND; IFDEF, IFNDEF, IFOPT / ENDIF and REGION / ENDREGION
37blocks), including nesting of preprocessor blocks up to 255 levels
38- Folding of code blocks on appropriate keywords (the following code blocks are
39supported: "begin, asm, record, try, case / end" blocks, class & object
40declarations and interface declarations)
41
42Remarks:
43
44- Folding of code blocks tries to handle all special cases in which folding
45should not occur. As implemented those are:
46
471. Structure "record case / end" (there's only one "end" statement and "case" is
48ignored as fold point)
492. Forward class declarations ("type TMyClass = class;") and object method
50declarations ("TNotifyEvent = procedure(Sender: TObject) of object;") are
51ignored as fold points
523. Simplified complete class declarations ("type TMyClass = class(TObject);")
53are ignored as fold points
544. Every other situation when class keyword doesn't actually start class
55declaration ("class procedure", "class function", "class of", "class var",
56"class property" and "class operator")
575. Forward (disp)interface declarations ("type IMyInterface = interface;") are
58ignored as fold points
59
60- Folding of code blocks inside preprocessor blocks is disabled (any comments
61inside them will be folded fine) because there is no guarantee that complete
62code block will be contained inside folded preprocessor block in which case
63folded code block could end prematurely at the end of preprocessor block if
64there is no closing statement inside. This was done in order to properly process
65document that may contain something like this:
66
67type
68{$IFDEF UNICODE}
69 TMyClass = class(UnicodeAncestor)
70{$ELSE}
71 TMyClass = class(AnsiAncestor)
72{$ENDIF}
73 private
74 ...
75 public
76 ...
77 published
78 ...
79end;
80
81If class declarations were folded, then the second class declaration would end
82at "$ENDIF" statement, first class statement would end at "end;" statement and
83preprocessor "$IFDEF" block would go all the way to the end of document.
84However, having in mind all this, if you want to enable folding of code blocks
85inside preprocessor blocks, you can disable folding of preprocessor blocks by
86changing "fold.preprocessor" property, in which case everything inside them
87would be folded.
88
89~ KEYWORDS:
90
91The list of keywords that can be used in pascal.properties file (up to Delphi
922009):
93
94- Keywords: absolute abstract and array as asm assembler automated begin case
95cdecl class const constructor deprecated destructor dispid dispinterface div do
96downto dynamic else end except export exports external far file final
97finalization finally for forward function goto if implementation in inherited
98initialization inline interface is label library message mod near nil not object
99of on or out overload override packed pascal platform private procedure program
100property protected public published raise record register reintroduce repeat
101resourcestring safecall sealed set shl shr static stdcall strict string then
102threadvar to try type unit unsafe until uses var varargs virtual while with xor
103
104- Keywords related to the "smart highlithing" feature: add default implements
105index name nodefault read readonly remove stored write writeonly
106
107- Keywords related to Delphi packages (in addition to all above): package
108contains requires
109
110*/
111
112#include <stdlib.h>
113#include <string.h>
114#include <stdio.h>
115#include <stdarg.h>
116#include <assert.h>
117#include <ctype.h>
118
119#include "ILexer.h"
120#include "Scintilla.h"
121#include "SciLexer.h"
122
123#include "WordList.h"
124#include "LexAccessor.h"
125#include "Accessor.h"
126#include "StyleContext.h"
127#include "CharacterSet.h"
128#include "LexerModule.h"
129
130#ifdef SCI_NAMESPACE
131using namespace Scintilla;
132#endif
133
134static void GetRangeLowered(unsigned int start,
135 unsigned int end,
136 Accessor &styler,
137 char *s,
138 unsigned int len) {
139 unsigned int i = 0;
140 while ((i < end - start + 1) && (i < len-1)) {
141 s[i] = static_cast<char>(tolower(styler[start + i]));
142 i++;
143 }
144 s[i] = '\0';
145}
146
147static void GetForwardRangeLowered(unsigned int start,
148 CharacterSet &charSet,
149 Accessor &styler,
150 char *s,
151 unsigned int len) {
152 unsigned int i = 0;
153 while ((i < len-1) && charSet.Contains(styler.SafeGetCharAt(start + i))) {
154 s[i] = static_cast<char>(tolower(styler.SafeGetCharAt(start + i)));
155 i++;
156 }
157 s[i] = '\0';
158
159}
160
161enum {
162 stateInAsm = 0x1000,
163 stateInProperty = 0x2000,
164 stateInExport = 0x4000,
165 stateFoldInPreprocessor = 0x0100,
166 stateFoldInRecord = 0x0200,
167 stateFoldInPreprocessorLevelMask = 0x00FF,
168 stateFoldMaskAll = 0x0FFF
169};
170
171static void ClassifyPascalWord(WordList *keywordlists[], StyleContext &sc, int &curLineState, bool bSmartHighlighting) {
172 WordList& keywords = *keywordlists[0];
173
174 char s[100];
175 sc.GetCurrentLowered(s, sizeof(s));
176 if (keywords.InList(s)) {
177 if (curLineState & stateInAsm) {
178 if (strcmp(s, "end") == 0 && sc.GetRelative(-4) != '@') {
179 curLineState &= ~stateInAsm;
180 sc.ChangeState(SCE_PAS_WORD);
181 } else {
182 sc.ChangeState(SCE_PAS_ASM);
183 }
184 } else {
185 bool ignoreKeyword = false;
186 if (strcmp(s, "asm") == 0) {
187 curLineState |= stateInAsm;
188 } else if (bSmartHighlighting) {
189 if (strcmp(s, "property") == 0) {
190 curLineState |= stateInProperty;
191 } else if (strcmp(s, "exports") == 0) {
192 curLineState |= stateInExport;
193 } else if (!(curLineState & (stateInProperty | stateInExport)) && strcmp(s, "index") == 0) {
194 ignoreKeyword = true;
195 } else if (!(curLineState & stateInExport) && strcmp(s, "name") == 0) {
196 ignoreKeyword = true;
197 } else if (!(curLineState & stateInProperty) &&
198 (strcmp(s, "read") == 0 || strcmp(s, "write") == 0 ||
199 strcmp(s, "default") == 0 || strcmp(s, "nodefault") == 0 ||
200 strcmp(s, "stored") == 0 || strcmp(s, "implements") == 0 ||
201 strcmp(s, "readonly") == 0 || strcmp(s, "writeonly") == 0 ||
202 strcmp(s, "add") == 0 || strcmp(s, "remove") == 0)) {
203 ignoreKeyword = true;
204 }
205 }
206 if (!ignoreKeyword) {
207 sc.ChangeState(SCE_PAS_WORD);
208 }
209 }
210 } else if (curLineState & stateInAsm) {
211 sc.ChangeState(SCE_PAS_ASM);
212 }
213 sc.SetState(SCE_PAS_DEFAULT);
214}
215
216static void ColourisePascalDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
217 Accessor &styler) {
218 bool bSmartHighlighting = styler.GetPropertyInt("lexer.pascal.smart.highlighting", 1) != 0;
219
220 CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
221 CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
222 CharacterSet setNumber(CharacterSet::setDigits, ".-+eE");
223 CharacterSet setHexNumber(CharacterSet::setDigits, "abcdefABCDEF");
224 CharacterSet setOperator(CharacterSet::setNone, "#$&'()*+,-./:;<=>@[]^{}");
225
226 int curLine = styler.GetLine(startPos);
227 int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0;
228
229 StyleContext sc(startPos, length, initStyle, styler);
230
231 for (; sc.More(); sc.Forward()) {
232 if (sc.atLineEnd) {
233 // Update the line state, so it can be seen by next line
234 curLine = styler.GetLine(sc.currentPos);
235 styler.SetLineState(curLine, curLineState);
236 }
237
238 // Determine if the current state should terminate.
239 switch (sc.state) {
240 case SCE_PAS_NUMBER:
241 if (!setNumber.Contains(sc.ch) || (sc.ch == '.' && sc.chNext == '.')) {
242 sc.SetState(SCE_PAS_DEFAULT);
243 } else if (sc.ch == '-' || sc.ch == '+') {
244 if (sc.chPrev != 'E' && sc.chPrev != 'e') {
245 sc.SetState(SCE_PAS_DEFAULT);
246 }
247 }
248 break;
249 case SCE_PAS_IDENTIFIER:
250 if (!setWord.Contains(sc.ch)) {
251 ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting);
252 }
253 break;
254 case SCE_PAS_HEXNUMBER:
255 if (!setHexNumber.Contains(sc.ch)) {
256 sc.SetState(SCE_PAS_DEFAULT);
257 }
258 break;
259 case SCE_PAS_COMMENT:
260 case SCE_PAS_PREPROCESSOR:
261 if (sc.ch == '}') {
262 sc.ForwardSetState(SCE_PAS_DEFAULT);
263 }
264 break;
265 case SCE_PAS_COMMENT2:
266 case SCE_PAS_PREPROCESSOR2:
267 if (sc.Match('*', ')')) {
268 sc.Forward();
269 sc.ForwardSetState(SCE_PAS_DEFAULT);
270 }
271 break;
272 case SCE_PAS_COMMENTLINE:
273 if (sc.atLineStart) {
274 sc.SetState(SCE_PAS_DEFAULT);
275 }
276 break;
277 case SCE_PAS_STRING:
278 if (sc.atLineEnd) {
279 sc.ChangeState(SCE_PAS_STRINGEOL);
280 } else if (sc.ch == '\'' && sc.chNext == '\'') {
281 sc.Forward();
282 } else if (sc.ch == '\'') {
283 sc.ForwardSetState(SCE_PAS_DEFAULT);
284 }
285 break;
286 case SCE_PAS_STRINGEOL:
287 if (sc.atLineStart) {
288 sc.SetState(SCE_PAS_DEFAULT);
289 }
290 break;
291 case SCE_PAS_CHARACTER:
292 if (!setHexNumber.Contains(sc.ch) && sc.ch != '$') {
293 sc.SetState(SCE_PAS_DEFAULT);
294 }
295 break;
296 case SCE_PAS_OPERATOR:
297 if (bSmartHighlighting && sc.chPrev == ';') {
298 curLineState &= ~(stateInProperty | stateInExport);
299 }
300 sc.SetState(SCE_PAS_DEFAULT);
301 break;
302 case SCE_PAS_ASM:
303 sc.SetState(SCE_PAS_DEFAULT);
304 break;
305 }
306
307 // Determine if a new state should be entered.
308 if (sc.state == SCE_PAS_DEFAULT) {
309 if (IsADigit(sc.ch) && !(curLineState & stateInAsm)) {
310 sc.SetState(SCE_PAS_NUMBER);
311 } else if (setWordStart.Contains(sc.ch)) {
312 sc.SetState(SCE_PAS_IDENTIFIER);
313 } else if (sc.ch == '$' && !(curLineState & stateInAsm)) {
314 sc.SetState(SCE_PAS_HEXNUMBER);
315 } else if (sc.Match('{', '$')) {
316 sc.SetState(SCE_PAS_PREPROCESSOR);
317 } else if (sc.ch == '{') {
318 sc.SetState(SCE_PAS_COMMENT);
319 } else if (sc.Match("(*$")) {
320 sc.SetState(SCE_PAS_PREPROCESSOR2);
321 } else if (sc.Match('(', '*')) {
322 sc.SetState(SCE_PAS_COMMENT2);
323 sc.Forward(); // Eat the * so it isn't used for the end of the comment
324 } else if (sc.Match('/', '/')) {
325 sc.SetState(SCE_PAS_COMMENTLINE);
326 } else if (sc.ch == '\'') {
327 sc.SetState(SCE_PAS_STRING);
328 } else if (sc.ch == '#') {
329 sc.SetState(SCE_PAS_CHARACTER);
330 } else if (setOperator.Contains(sc.ch) && !(curLineState & stateInAsm)) {
331 sc.SetState(SCE_PAS_OPERATOR);
332 } else if (curLineState & stateInAsm) {
333 sc.SetState(SCE_PAS_ASM);
334 }
335 }
336 }
337
338 if (sc.state == SCE_PAS_IDENTIFIER && setWord.Contains(sc.chPrev)) {
339 ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting);
340 }
341
342 sc.Complete();
343}
344
345static bool IsStreamCommentStyle(int style) {
346 return style == SCE_PAS_COMMENT || style == SCE_PAS_COMMENT2;
347}
348
349static bool IsCommentLine(int line, Accessor &styler) {
350 int pos = styler.LineStart(line);
351 int eolPos = styler.LineStart(line + 1) - 1;
352 for (int i = pos; i < eolPos; i++) {
353 char ch = styler[i];
354 char chNext = styler.SafeGetCharAt(i + 1);
355 int style = styler.StyleAt(i);
356 if (ch == '/' && chNext == '/' && style == SCE_PAS_COMMENTLINE) {
357 return true;
358 } else if (!IsASpaceOrTab(ch)) {
359 return false;
360 }
361 }
362 return false;
363}
364
365static unsigned int GetFoldInPreprocessorLevelFlag(int lineFoldStateCurrent) {
366 return lineFoldStateCurrent & stateFoldInPreprocessorLevelMask;
367}
368
369static void SetFoldInPreprocessorLevelFlag(int &lineFoldStateCurrent, unsigned int nestLevel) {
370 lineFoldStateCurrent &= ~stateFoldInPreprocessorLevelMask;
371 lineFoldStateCurrent |= nestLevel & stateFoldInPreprocessorLevelMask;
372}
373
374static void ClassifyPascalPreprocessorFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
375 unsigned int startPos, Accessor &styler) {
376 CharacterSet setWord(CharacterSet::setAlpha);
377
378 char s[11]; // Size of the longest possible keyword + one additional character + null
379 GetForwardRangeLowered(startPos, setWord, styler, s, sizeof(s));
380
381 unsigned int nestLevel = GetFoldInPreprocessorLevelFlag(lineFoldStateCurrent);
382
383 if (strcmp(s, "if") == 0 ||
384 strcmp(s, "ifdef") == 0 ||
385 strcmp(s, "ifndef") == 0 ||
386 strcmp(s, "ifopt") == 0 ||
387 strcmp(s, "region") == 0) {
388 nestLevel++;
389 SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel);
390 lineFoldStateCurrent |= stateFoldInPreprocessor;
391 levelCurrent++;
392 } else if (strcmp(s, "endif") == 0 ||
393 strcmp(s, "ifend") == 0 ||
394 strcmp(s, "endregion") == 0) {
395 nestLevel--;
396 SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel);
397 if (nestLevel == 0) {
398 lineFoldStateCurrent &= ~stateFoldInPreprocessor;
399 }
400 levelCurrent--;
401 if (levelCurrent < SC_FOLDLEVELBASE) {
402 levelCurrent = SC_FOLDLEVELBASE;
403 }
404 }
405}
406
407static unsigned int SkipWhiteSpace(unsigned int currentPos, unsigned int endPos,
408 Accessor &styler, bool includeChars = false) {
409 CharacterSet setWord(CharacterSet::setAlphaNum, "_");
410 unsigned int j = currentPos + 1;
411 char ch = styler.SafeGetCharAt(j);
412 while ((j < endPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' ||
413 IsStreamCommentStyle(styler.StyleAt(j)) || (includeChars && setWord.Contains(ch)))) {
414 j++;
415 ch = styler.SafeGetCharAt(j);
416 }
417 return j;
418}
419
420static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
421 int startPos, unsigned int endPos,
422 unsigned int lastStart, unsigned int currentPos, Accessor &styler) {
423 char s[100];
424 GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s));
425
426 if (strcmp(s, "record") == 0) {
427 lineFoldStateCurrent |= stateFoldInRecord;
428 levelCurrent++;
429 } else if (strcmp(s, "begin") == 0 ||
430 strcmp(s, "asm") == 0 ||
431 strcmp(s, "try") == 0 ||
432 (strcmp(s, "case") == 0 && !(lineFoldStateCurrent & stateFoldInRecord))) {
433 levelCurrent++;
434 } else if (strcmp(s, "class") == 0 || strcmp(s, "object") == 0) {
435 // "class" & "object" keywords require special handling...
436 bool ignoreKeyword = false;
437 unsigned int j = SkipWhiteSpace(currentPos, endPos, styler);
438 if (j < endPos) {
439 CharacterSet setWordStart(CharacterSet::setAlpha, "_");
440 CharacterSet setWord(CharacterSet::setAlphaNum, "_");
441
442 if (styler.SafeGetCharAt(j) == ';') {
443 // Handle forward class declarations ("type TMyClass = class;")
444 // and object method declarations ("TNotifyEvent = procedure(Sender: TObject) of object;")
445 ignoreKeyword = true;
446 } else if (strcmp(s, "class") == 0) {
447 // "class" keyword has a few more special cases...
448 if (styler.SafeGetCharAt(j) == '(') {
449 // Handle simplified complete class declarations ("type TMyClass = class(TObject);")
450 j = SkipWhiteSpace(j, endPos, styler, true);
451 if (j < endPos && styler.SafeGetCharAt(j) == ')') {
452 j = SkipWhiteSpace(j, endPos, styler);
453 if (j < endPos && styler.SafeGetCharAt(j) == ';') {
454 ignoreKeyword = true;
455 }
456 }
457 } else if (setWordStart.Contains(styler.SafeGetCharAt(j))) {
458 char s2[11]; // Size of the longest possible keyword + one additional character + null
459 GetForwardRangeLowered(j, setWord, styler, s2, sizeof(s2));
460
461 if (strcmp(s2, "procedure") == 0 ||
462 strcmp(s2, "function") == 0 ||
463 strcmp(s2, "of") == 0 ||
464 strcmp(s2, "var") == 0 ||
465 strcmp(s2, "property") == 0 ||
466 strcmp(s2, "operator") == 0) {
467 ignoreKeyword = true;
468 }
469 }
470 }
471 }
472 if (!ignoreKeyword) {
473 levelCurrent++;
474 }
475 } else if (strcmp(s, "interface") == 0) {
476 // "interface" keyword requires special handling...
477 bool ignoreKeyword = true;
478 int j = lastStart - 1;
479 char ch = styler.SafeGetCharAt(j);
480 while ((j >= startPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' ||
481 IsStreamCommentStyle(styler.StyleAt(j)))) {
482 j--;
483 ch = styler.SafeGetCharAt(j);
484 }
485 if (j >= startPos && styler.SafeGetCharAt(j) == '=') {
486 ignoreKeyword = false;
487 }
488 if (!ignoreKeyword) {
489 unsigned int k = SkipWhiteSpace(currentPos, endPos, styler);
490 if (k < endPos && styler.SafeGetCharAt(k) == ';') {
491 // Handle forward interface declarations ("type IMyInterface = interface;")
492 ignoreKeyword = true;
493 }
494 }
495 if (!ignoreKeyword) {
496 levelCurrent++;
497 }
498 } else if (strcmp(s, "dispinterface") == 0) {
499 // "dispinterface" keyword requires special handling...
500 bool ignoreKeyword = false;
501 unsigned int j = SkipWhiteSpace(currentPos, endPos, styler);
502 if (j < endPos && styler.SafeGetCharAt(j) == ';') {
503 // Handle forward dispinterface declarations ("type IMyInterface = dispinterface;")
504 ignoreKeyword = true;
505 }
506 if (!ignoreKeyword) {
507 levelCurrent++;
508 }
509 } else if (strcmp(s, "end") == 0) {
510 lineFoldStateCurrent &= ~stateFoldInRecord;
511 levelCurrent--;
512 if (levelCurrent < SC_FOLDLEVELBASE) {
513 levelCurrent = SC_FOLDLEVELBASE;
514 }
515 }
516}
517
518static void FoldPascalDoc(unsigned int startPos, int length, int initStyle, WordList *[],
519 Accessor &styler) {
520 bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
521 bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
522 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
523 unsigned int endPos = startPos + length;
524 int visibleChars = 0;
525 int lineCurrent = styler.GetLine(startPos);
526 int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
527 int levelCurrent = levelPrev;
528 int lineFoldStateCurrent = lineCurrent > 0 ? styler.GetLineState(lineCurrent - 1) & stateFoldMaskAll : 0;
529 char chNext = styler[startPos];
530 int styleNext = styler.StyleAt(startPos);
531 int style = initStyle;
532
533 int lastStart = 0;
534 CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
535
536 for (unsigned int i = startPos; i < endPos; i++) {
537 char ch = chNext;
538 chNext = styler.SafeGetCharAt(i + 1);
539 int stylePrev = style;
540 style = styleNext;
541 styleNext = styler.StyleAt(i + 1);
542 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
543
544 if (foldComment && IsStreamCommentStyle(style)) {
545 if (!IsStreamCommentStyle(stylePrev)) {
546 levelCurrent++;
547 } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
548 // Comments don't end at end of line and the next character may be unstyled.
549 levelCurrent--;
550 }
551 }
552 if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
553 {
554 if (!IsCommentLine(lineCurrent - 1, styler)
555 && IsCommentLine(lineCurrent + 1, styler))
556 levelCurrent++;
557 else if (IsCommentLine(lineCurrent - 1, styler)
558 && !IsCommentLine(lineCurrent+1, styler))
559 levelCurrent--;
560 }
561 if (foldPreprocessor) {
562 if (style == SCE_PAS_PREPROCESSOR && ch == '{' && chNext == '$') {
563 ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 2, styler);
564 } else if (style == SCE_PAS_PREPROCESSOR2 && ch == '(' && chNext == '*'
565 && styler.SafeGetCharAt(i + 2) == '$') {
566 ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 3, styler);
567 }
568 }
569
570 if (stylePrev != SCE_PAS_WORD && style == SCE_PAS_WORD)
571 {
572 // Store last word start point.
573 lastStart = i;
574 }
575 if (stylePrev == SCE_PAS_WORD && !(lineFoldStateCurrent & stateFoldInPreprocessor)) {
576 if(setWord.Contains(ch) && !setWord.Contains(chNext)) {
577 ClassifyPascalWordFoldPoint(levelCurrent, lineFoldStateCurrent, startPos, endPos, lastStart, i, styler);
578 }
579 }
580
581 if (!IsASpace(ch))
582 visibleChars++;
583
584 if (atEOL) {
585 int lev = levelPrev;
586 if (visibleChars == 0 && foldCompact)
587 lev |= SC_FOLDLEVELWHITEFLAG;
588 if ((levelCurrent > levelPrev) && (visibleChars > 0))
589 lev |= SC_FOLDLEVELHEADERFLAG;
590 if (lev != styler.LevelAt(lineCurrent)) {
591 styler.SetLevel(lineCurrent, lev);
592 }
593 int newLineState = (styler.GetLineState(lineCurrent) & ~stateFoldMaskAll) | lineFoldStateCurrent;
594 styler.SetLineState(lineCurrent, newLineState);
595 lineCurrent++;
596 levelPrev = levelCurrent;
597 visibleChars = 0;
598 }
599 }
600
601 // If we didn't reach the EOL in previous loop, store line level and whitespace information.
602 // The rest will be filled in later...
603 int lev = levelPrev;
604 if (visibleChars == 0 && foldCompact)
605 lev |= SC_FOLDLEVELWHITEFLAG;
606 styler.SetLevel(lineCurrent, lev);
607}
608
609static const char * const pascalWordListDesc[] = {
610 "Keywords",
611 0
612};
613
614LexerModule lmPascal(SCLEX_PASCAL, ColourisePascalDoc, "pascal", FoldPascalDoc, pascalWordListDesc);