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