]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexCLW.cxx
c1dea607c36befd4c712428107f3178062ab9d9a
[wxWidgets.git] / src / stc / scintilla / lexers / LexCLW.cxx
1 // Scintilla source code edit control
2 /** @file LexClw.cxx
3 ** Lexer for Clarion.
4 ** 2004/12/17 Updated Lexer
5 **/
6 // Copyright 2003-2004 by Ron Schofield <ron@schofieldcomputer.com>
7 // The License.txt file describes the conditions under which this software may be distributed.
8
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdio.h>
12 #include <stdarg.h>
13 #include <assert.h>
14 #include <ctype.h>
15
16 #include "ILexer.h"
17 #include "Scintilla.h"
18 #include "SciLexer.h"
19
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
27 #ifdef SCI_NAMESPACE
28 using namespace Scintilla;
29 #endif
30
31 // Is an end of line character
32 inline bool IsEOL(const int ch) {
33
34 return(ch == '\n');
35 }
36
37 // Convert character to uppercase
38 static char CharacterUpper(char chChar) {
39
40 if (chChar < 'a' || chChar > 'z') {
41 return(chChar);
42 }
43 else {
44 return(static_cast<char>(chChar - 'a' + 'A'));
45 }
46 }
47
48 // Convert string to uppercase
49 static void StringUpper(char *szString) {
50
51 while (*szString) {
52 *szString = CharacterUpper(*szString);
53 szString++;
54 }
55 }
56
57 // Is a label start character
58 inline bool IsALabelStart(const int iChar) {
59
60 return(isalpha(iChar) || iChar == '_');
61 }
62
63 // Is a label character
64 inline bool IsALabelCharacter(const int iChar) {
65
66 return(isalnum(iChar) || iChar == '_' || iChar == ':');
67 }
68
69 // Is the character is a ! and the the next character is not a !
70 inline bool IsACommentStart(const int iChar) {
71
72 return(iChar == '!');
73 }
74
75 // Is the character a Clarion hex character (ABCDEF)
76 inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) {
77
78 // Case insensitive.
79 if (!bCaseSensitive) {
80 if (strchr("ABCDEFabcdef", iChar) != NULL) {
81 return(true);
82 }
83 }
84 // Case sensitive
85 else {
86 if (strchr("ABCDEF", iChar) != NULL) {
87 return(true);
88 }
89 }
90 return(false);
91 }
92
93 // Is the character a Clarion base character (B=Binary, O=Octal, H=Hex)
94 inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) {
95
96 // Case insensitive.
97 if (!bCaseSensitive) {
98 // If character is a numeric base character
99 if (strchr("BOHboh", iChar) != NULL) {
100 return(true);
101 }
102 }
103 // Case sensitive
104 else {
105 // If character is a numeric base character
106 if (strchr("BOH", iChar) != NULL) {
107 return(true);
108 }
109 }
110 return(false);
111 }
112
113 // Set the correct numeric constant state
114 inline bool SetNumericConstantState(StyleContext &scDoc) {
115
116 int iPoints = 0; // Point counter
117 char cNumericString[512]; // Numeric string buffer
118
119 // Buffer the current numberic string
120 scDoc.GetCurrent(cNumericString, sizeof(cNumericString));
121 // Loop through the string until end of string (NULL termination)
122 for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) {
123 // Depending on the character
124 switch (cNumericString[iIndex]) {
125 // Is a . (point)
126 case '.' :
127 // Increment point counter
128 iPoints++;
129 break;
130 default :
131 break;
132 }
133 }
134 // If points found (can be more than one for improper formatted number
135 if (iPoints > 0) {
136 return(true);
137 }
138 // Else no points found
139 else {
140 return(false);
141 }
142 }
143
144 // Get the next word in uppercase from the current position (keyword lookahead)
145 inline bool GetNextWordUpper(Accessor &styler, unsigned int uiStartPos, int iLength, char *cWord) {
146
147 unsigned int iIndex = 0; // Buffer Index
148
149 // Loop through the remaining string from the current position
150 for (int iOffset = uiStartPos; iOffset < iLength; iOffset++) {
151 // Get the character from the buffer using the offset
152 char cCharacter = styler[iOffset];
153 if (IsEOL(cCharacter)) {
154 break;
155 }
156 // If the character is alphabet character
157 if (isalpha(cCharacter)) {
158 // Add UPPERCASE character to the word buffer
159 cWord[iIndex++] = CharacterUpper(cCharacter);
160 }
161 }
162 // Add null termination
163 cWord[iIndex] = '\0';
164 // If no word was found
165 if (iIndex == 0) {
166 // Return failure
167 return(false);
168 }
169 // Else word was found
170 else {
171 // Return success
172 return(true);
173 }
174 }
175
176 // Clarion Language Colouring Procedure
177 static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) {
178
179 int iParenthesesLevel = 0; // Parenthese Level
180 int iColumn1Label = false; // Label starts in Column 1
181
182 WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords
183 WordList &wlCompilerDirectives = *wlKeywords[1]; // Compiler Directives
184 WordList &wlRuntimeExpressions = *wlKeywords[2]; // Runtime Expressions
185 WordList &wlBuiltInProcsFuncs = *wlKeywords[3]; // Builtin Procedures and Functions
186 WordList &wlStructsDataTypes = *wlKeywords[4]; // Structures and Data Types
187 WordList &wlAttributes = *wlKeywords[5]; // Procedure Attributes
188 WordList &wlStandardEquates = *wlKeywords[6]; // Standard Equates
189 WordList &wlLabelReservedWords = *wlKeywords[7]; // Clarion Reserved Keywords (Labels)
190 WordList &wlProcLabelReservedWords = *wlKeywords[8]; // Clarion Reserved Keywords (Procedure Labels)
191
192 const char wlProcReservedKeywordList[] =
193 "PROCEDURE FUNCTION";
194 WordList wlProcReservedKeywords;
195 wlProcReservedKeywords.Set(wlProcReservedKeywordList);
196
197 const char wlCompilerKeywordList[] =
198 "COMPILE OMIT";
199 WordList wlCompilerKeywords;
200 wlCompilerKeywords.Set(wlCompilerKeywordList);
201
202 const char wlLegacyStatementsList[] =
203 "BOF EOF FUNCTION POINTER SHARE";
204 WordList wlLegacyStatements;
205 wlLegacyStatements.Set(wlLegacyStatementsList);
206
207 StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler);
208
209 // lex source code
210 for (; scDoc.More(); scDoc.Forward())
211 {
212 //
213 // Determine if the current state should terminate.
214 //
215
216 // Label State Handling
217 if (scDoc.state == SCE_CLW_LABEL) {
218 // If the character is not a valid label
219 if (!IsALabelCharacter(scDoc.ch)) {
220 // If the character is a . (dot syntax)
221 if (scDoc.ch == '.') {
222 // Turn off column 1 label flag as label now cannot be reserved work
223 iColumn1Label = false;
224 // Uncolour the . (dot) to default state, move forward one character,
225 // and change back to the label state.
226 scDoc.SetState(SCE_CLW_DEFAULT);
227 scDoc.Forward();
228 scDoc.SetState(SCE_CLW_LABEL);
229 }
230 // Else check label
231 else {
232 char cLabel[512]; // Label buffer
233 // Buffer the current label string
234 scDoc.GetCurrent(cLabel,sizeof(cLabel));
235 // If case insensitive, convert string to UPPERCASE to match passed keywords.
236 if (!bCaseSensitive) {
237 StringUpper(cLabel);
238 }
239 // Else if UPPERCASE label string is in the Clarion compiler keyword list
240 if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){
241 // change the label to error state
242 scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
243 }
244 // Else if UPPERCASE label string is in the Clarion reserved keyword list
245 else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){
246 // change the label to error state
247 scDoc.ChangeState(SCE_CLW_ERROR);
248 }
249 // Else if UPPERCASE label string is
250 else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) {
251 char cWord[512]; // Word buffer
252 // Get the next word from the current position
253 if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) {
254 // If the next word is a procedure reserved word
255 if (wlProcReservedKeywords.InList(cWord)) {
256 // Change the label to error state
257 scDoc.ChangeState(SCE_CLW_ERROR);
258 }
259 }
260 }
261 // Else if label string is in the compiler directive keyword list
262 else if (wlCompilerDirectives.InList(cLabel)) {
263 // change the state to compiler directive state
264 scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
265 }
266 // Terminate the label state and set to default state
267 scDoc.SetState(SCE_CLW_DEFAULT);
268 }
269 }
270 }
271 // Keyword State Handling
272 else if (scDoc.state == SCE_CLW_KEYWORD) {
273 // If character is : (colon)
274 if (scDoc.ch == ':') {
275 char cEquate[512]; // Equate buffer
276 // Move forward to include : (colon) in buffer
277 scDoc.Forward();
278 // Buffer the equate string
279 scDoc.GetCurrent(cEquate,sizeof(cEquate));
280 // If case insensitive, convert string to UPPERCASE to match passed keywords.
281 if (!bCaseSensitive) {
282 StringUpper(cEquate);
283 }
284 // If statement string is in the equate list
285 if (wlStandardEquates.InList(cEquate)) {
286 // Change to equate state
287 scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
288 }
289 }
290 // If the character is not a valid label character
291 else if (!IsALabelCharacter(scDoc.ch)) {
292 char cStatement[512]; // Statement buffer
293 // Buffer the statement string
294 scDoc.GetCurrent(cStatement,sizeof(cStatement));
295 // If case insensitive, convert string to UPPERCASE to match passed keywords.
296 if (!bCaseSensitive) {
297 StringUpper(cStatement);
298 }
299 // If statement string is in the Clarion keyword list
300 if (wlClarionKeywords.InList(cStatement)) {
301 // Change the statement string to the Clarion keyword state
302 scDoc.ChangeState(SCE_CLW_KEYWORD);
303 }
304 // Else if statement string is in the compiler directive keyword list
305 else if (wlCompilerDirectives.InList(cStatement)) {
306 // Change the statement string to the compiler directive state
307 scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
308 }
309 // Else if statement string is in the runtime expressions keyword list
310 else if (wlRuntimeExpressions.InList(cStatement)) {
311 // Change the statement string to the runtime expressions state
312 scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS);
313 }
314 // Else if statement string is in the builtin procedures and functions keyword list
315 else if (wlBuiltInProcsFuncs.InList(cStatement)) {
316 // Change the statement string to the builtin procedures and functions state
317 scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION);
318 }
319 // Else if statement string is in the tructures and data types keyword list
320 else if (wlStructsDataTypes.InList(cStatement)) {
321 // Change the statement string to the structures and data types state
322 scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE);
323 }
324 // Else if statement string is in the procedure attribute keyword list
325 else if (wlAttributes.InList(cStatement)) {
326 // Change the statement string to the procedure attribute state
327 scDoc.ChangeState(SCE_CLW_ATTRIBUTE);
328 }
329 // Else if statement string is in the standard equate keyword list
330 else if (wlStandardEquates.InList(cStatement)) {
331 // Change the statement string to the standard equate state
332 scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
333 }
334 // Else if statement string is in the deprecated or legacy keyword list
335 else if (wlLegacyStatements.InList(cStatement)) {
336 // Change the statement string to the standard equate state
337 scDoc.ChangeState(SCE_CLW_DEPRECATED);
338 }
339 // Else the statement string doesn't match any work list
340 else {
341 // Change the statement string to the default state
342 scDoc.ChangeState(SCE_CLW_DEFAULT);
343 }
344 // Terminate the keyword state and set to default state
345 scDoc.SetState(SCE_CLW_DEFAULT);
346 }
347 }
348 // String State Handling
349 else if (scDoc.state == SCE_CLW_STRING) {
350 // If the character is an ' (single quote)
351 if (scDoc.ch == '\'') {
352 // Set the state to default and move forward colouring
353 // the ' (single quote) as default state
354 // terminating the string state
355 scDoc.SetState(SCE_CLW_DEFAULT);
356 scDoc.Forward();
357 }
358 // If the next character is an ' (single quote)
359 if (scDoc.chNext == '\'') {
360 // Move forward one character and set to default state
361 // colouring the next ' (single quote) as default state
362 // terminating the string state
363 scDoc.ForwardSetState(SCE_CLW_DEFAULT);
364 scDoc.Forward();
365 }
366 }
367 // Picture String State Handling
368 else if (scDoc.state == SCE_CLW_PICTURE_STRING) {
369 // If the character is an ( (open parenthese)
370 if (scDoc.ch == '(') {
371 // Increment the parenthese level
372 iParenthesesLevel++;
373 }
374 // Else if the character is a ) (close parenthese)
375 else if (scDoc.ch == ')') {
376 // If the parenthese level is set to zero
377 // parentheses matched
378 if (!iParenthesesLevel) {
379 scDoc.SetState(SCE_CLW_DEFAULT);
380 }
381 // Else parenthese level is greater than zero
382 // still looking for matching parentheses
383 else {
384 // Decrement the parenthese level
385 iParenthesesLevel--;
386 }
387 }
388 }
389 // Standard Equate State Handling
390 else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) {
391 if (!isalnum(scDoc.ch)) {
392 scDoc.SetState(SCE_CLW_DEFAULT);
393 }
394 }
395 // Integer Constant State Handling
396 else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) {
397 // If the character is not a digit (0-9)
398 // or character is not a hexidecimal character (A-F)
399 // or character is not a . (point)
400 // or character is not a numberic base character (B,O,H)
401 if (!(isdigit(scDoc.ch)
402 || IsAHexCharacter(scDoc.ch, bCaseSensitive)
403 || scDoc.ch == '.'
404 || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) {
405 // If the number was a real
406 if (SetNumericConstantState(scDoc)) {
407 // Colour the matched string to the real constant state
408 scDoc.ChangeState(SCE_CLW_REAL_CONSTANT);
409 }
410 // Else the number was an integer
411 else {
412 // Colour the matched string to an integer constant state
413 scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT);
414 }
415 // Terminate the integer constant state and set to default state
416 scDoc.SetState(SCE_CLW_DEFAULT);
417 }
418 }
419
420 //
421 // Determine if a new state should be entered.
422 //
423
424 // Beginning of Line Handling
425 if (scDoc.atLineStart) {
426 // Reset the column 1 label flag
427 iColumn1Label = false;
428 // If column 1 character is a label start character
429 if (IsALabelStart(scDoc.ch)) {
430 // Label character is found in column 1
431 // so set column 1 label flag and clear last column 1 label
432 iColumn1Label = true;
433 // Set the state to label
434 scDoc.SetState(SCE_CLW_LABEL);
435 }
436 // else if character is a space or tab
437 else if (IsASpace(scDoc.ch)){
438 // Set to default state
439 scDoc.SetState(SCE_CLW_DEFAULT);
440 }
441 // else if comment start (!) or is an * (asterisk)
442 else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) {
443 // then set the state to comment.
444 scDoc.SetState(SCE_CLW_COMMENT);
445 }
446 // else the character is a ? (question mark)
447 else if (scDoc.ch == '?') {
448 // Change to the compiler directive state, move forward,
449 // colouring the ? (question mark), change back to default state.
450 scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
451 scDoc.Forward();
452 scDoc.SetState(SCE_CLW_DEFAULT);
453 }
454 // else an invalid character in column 1
455 else {
456 // Set to error state
457 scDoc.SetState(SCE_CLW_ERROR);
458 }
459 }
460 // End of Line Handling
461 else if (scDoc.atLineEnd) {
462 // Reset to the default state at the end of each line.
463 scDoc.SetState(SCE_CLW_DEFAULT);
464 }
465 // Default Handling
466 else {
467 // If in default state
468 if (scDoc.state == SCE_CLW_DEFAULT) {
469 // If is a letter could be a possible statement
470 if (isalpha(scDoc.ch)) {
471 // Set the state to Clarion Keyword and verify later
472 scDoc.SetState(SCE_CLW_KEYWORD);
473 }
474 // else is a number
475 else if (isdigit(scDoc.ch)) {
476 // Set the state to Integer Constant and verify later
477 scDoc.SetState(SCE_CLW_INTEGER_CONSTANT);
478 }
479 // else if the start of a comment or a | (line continuation)
480 else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') {
481 // then set the state to comment.
482 scDoc.SetState(SCE_CLW_COMMENT);
483 }
484 // else if the character is a ' (single quote)
485 else if (scDoc.ch == '\'') {
486 // If the character is also a ' (single quote)
487 // Embedded Apostrophe
488 if (scDoc.chNext == '\'') {
489 // Move forward colouring it as default state
490 scDoc.ForwardSetState(SCE_CLW_DEFAULT);
491 }
492 else {
493 // move to the next character and then set the state to comment.
494 scDoc.ForwardSetState(SCE_CLW_STRING);
495 }
496 }
497 // else the character is an @ (ampersand)
498 else if (scDoc.ch == '@') {
499 // Case insensitive.
500 if (!bCaseSensitive) {
501 // If character is a valid picture token character
502 if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) {
503 // Set to the picture string state
504 scDoc.SetState(SCE_CLW_PICTURE_STRING);
505 }
506 }
507 // Case sensitive
508 else {
509 // If character is a valid picture token character
510 if (strchr("DEKNPST", scDoc.chNext) != NULL) {
511 // Set the picture string state
512 scDoc.SetState(SCE_CLW_PICTURE_STRING);
513 }
514 }
515 }
516 }
517 }
518 }
519 // lexing complete
520 scDoc.Complete();
521 }
522
523 // Clarion Language Case Sensitive Colouring Procedure
524 static void ColouriseClarionDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
525
526 ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true);
527 }
528
529 // Clarion Language Case Insensitive Colouring Procedure
530 static void ColouriseClarionDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
531
532 ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false);
533 }
534
535 // Fill Buffer
536
537 static void FillBuffer(unsigned int uiStart, unsigned int uiEnd, Accessor &accStyler, char *szBuffer, unsigned int uiLength) {
538
539 unsigned int uiPos = 0;
540
541 while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) {
542 szBuffer[uiPos] = static_cast<char>(toupper(accStyler[uiStart + uiPos]));
543 uiPos++;
544 }
545 szBuffer[uiPos] = '\0';
546 }
547
548 // Classify Clarion Fold Point
549
550 static int ClassifyClarionFoldPoint(int iLevel, const char* szString) {
551
552 if (!(isdigit(szString[0]) || (szString[0] == '.'))) {
553 if (strcmp(szString, "PROCEDURE") == 0) {
554 // iLevel = SC_FOLDLEVELBASE + 1;
555 }
556 else if (strcmp(szString, "MAP") == 0 ||
557 strcmp(szString,"ACCEPT") == 0 ||
558 strcmp(szString,"BEGIN") == 0 ||
559 strcmp(szString,"CASE") == 0 ||
560 strcmp(szString,"EXECUTE") == 0 ||
561 strcmp(szString,"IF") == 0 ||
562 strcmp(szString,"ITEMIZE") == 0 ||
563 strcmp(szString,"INTERFACE") == 0 ||
564 strcmp(szString,"JOIN") == 0 ||
565 strcmp(szString,"LOOP") == 0 ||
566 strcmp(szString,"MODULE") == 0 ||
567 strcmp(szString,"RECORD") == 0) {
568 iLevel++;
569 }
570 else if (strcmp(szString, "APPLICATION") == 0 ||
571 strcmp(szString, "CLASS") == 0 ||
572 strcmp(szString, "DETAIL") == 0 ||
573 strcmp(szString, "FILE") == 0 ||
574 strcmp(szString, "FOOTER") == 0 ||
575 strcmp(szString, "FORM") == 0 ||
576 strcmp(szString, "GROUP") == 0 ||
577 strcmp(szString, "HEADER") == 0 ||
578 strcmp(szString, "INTERFACE") == 0 ||
579 strcmp(szString, "MENU") == 0 ||
580 strcmp(szString, "MENUBAR") == 0 ||
581 strcmp(szString, "OLE") == 0 ||
582 strcmp(szString, "OPTION") == 0 ||
583 strcmp(szString, "QUEUE") == 0 ||
584 strcmp(szString, "REPORT") == 0 ||
585 strcmp(szString, "SHEET") == 0 ||
586 strcmp(szString, "TAB") == 0 ||
587 strcmp(szString, "TOOLBAR") == 0 ||
588 strcmp(szString, "VIEW") == 0 ||
589 strcmp(szString, "WINDOW") == 0) {
590 iLevel++;
591 }
592 else if (strcmp(szString, "END") == 0 ||
593 strcmp(szString, "UNTIL") == 0 ||
594 strcmp(szString, "WHILE") == 0) {
595 iLevel--;
596 }
597 }
598 return(iLevel);
599 }
600
601 // Clarion Language Folding Procedure
602 static void FoldClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *[], Accessor &accStyler) {
603
604 unsigned int uiEndPos = uiStartPos + iLength;
605 int iLineCurrent = accStyler.GetLine(uiStartPos);
606 int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK;
607 int iLevelCurrent = iLevelPrev;
608 char chNext = accStyler[uiStartPos];
609 int iStyle = iInitStyle;
610 int iStyleNext = accStyler.StyleAt(uiStartPos);
611 int iVisibleChars = 0;
612 int iLastStart = 0;
613
614 for (unsigned int uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) {
615
616 char chChar = chNext;
617 chNext = accStyler.SafeGetCharAt(uiPos + 1);
618 int iStylePrev = iStyle;
619 iStyle = iStyleNext;
620 iStyleNext = accStyler.StyleAt(uiPos + 1);
621 bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n');
622
623 if (iStylePrev == SCE_CLW_DEFAULT) {
624 if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) {
625 // Store last word start point.
626 iLastStart = uiPos;
627 }
628 }
629
630 if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) {
631 if(iswordchar(chChar) && !iswordchar(chNext)) {
632 char chBuffer[100];
633 FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer));
634 iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer);
635 // if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) {
636 // accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE);
637 // iLevelPrev = SC_FOLDLEVELBASE;
638 // }
639 }
640 }
641
642 if (bEOL) {
643 int iLevel = iLevelPrev;
644 if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0))
645 iLevel |= SC_FOLDLEVELHEADERFLAG;
646 if (iLevel != accStyler.LevelAt(iLineCurrent)) {
647 accStyler.SetLevel(iLineCurrent,iLevel);
648 }
649 iLineCurrent++;
650 iLevelPrev = iLevelCurrent;
651 iVisibleChars = 0;
652 }
653
654 if (!isspacechar(chChar))
655 iVisibleChars++;
656 }
657
658 // Fill in the real level of the next line, keeping the current flags
659 // as they will be filled in later.
660 int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
661 accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext);
662 }
663
664 // Word List Descriptions
665 static const char * const rgWordListDescriptions[] = {
666 "Clarion Keywords",
667 "Compiler Directives",
668 "Built-in Procedures and Functions",
669 "Runtime Expressions",
670 "Structure and Data Types",
671 "Attributes",
672 "Standard Equates",
673 "Reserved Words (Labels)",
674 "Reserved Words (Procedure Labels)",
675 0,
676 };
677
678 // Case Sensitive Clarion Language Lexer
679 LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions);
680
681 // Case Insensitive Clarion Language Lexer
682 LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions);