]> git.saurik.com Git - wxWidgets.git/blame - src/stc/scintilla/lexers/LexCLW.cxx
Add missing WXK constants for the control keys
[wxWidgets.git] / src / stc / scintilla / lexers / LexCLW.cxx
CommitLineData
8e54aaed
RD
1// Scintilla source code edit control
2/** @file LexClw.cxx
3 ** Lexer for Clarion.
1e9bafca 4 ** 2004/12/17 Updated Lexer
8e54aaed 5 **/
1e9bafca 6// Copyright 2003-2004 by Ron Schofield <ron@schofieldcomputer.com>
8e54aaed
RD
7// The License.txt file describes the conditions under which this software may be distributed.
8
9#include <stdlib.h>
10#include <string.h>
8e54aaed
RD
11#include <stdio.h>
12#include <stdarg.h>
1dcf666d 13#include <assert.h>
1e9bafca 14#include <ctype.h>
8e54aaed 15
1dcf666d
RD
16#include "ILexer.h"
17#include "Scintilla.h"
18#include "SciLexer.h"
8e54aaed 19
1dcf666d
RD
20#include "WordList.h"
21#include "LexAccessor.h"
8e54aaed
RD
22#include "Accessor.h"
23#include "StyleContext.h"
1dcf666d
RD
24#include "CharacterSet.h"
25#include "LexerModule.h"
8e54aaed 26
7e0c58e9
RD
27#ifdef SCI_NAMESPACE
28using namespace Scintilla;
29#endif
30
1e9bafca
RD
31// Is an end of line character
32inline bool IsEOL(const int ch) {
33
34 return(ch == '\n');
35}
36
37// Convert character to uppercase
38static 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 }
8e54aaed
RD
46}
47
1e9bafca
RD
48// Convert string to uppercase
49static void StringUpper(char *szString) {
50
51 while (*szString) {
52 *szString = CharacterUpper(*szString);
53 szString++;
8e54aaed
RD
54 }
55}
56
57// Is a label start character
58inline bool IsALabelStart(const int iChar) {
1e9bafca 59
8e54aaed
RD
60 return(isalpha(iChar) || iChar == '_');
61}
62
63// Is a label character
64inline bool IsALabelCharacter(const int iChar) {
1e9bafca 65
1dcf666d 66 return(isalnum(iChar) || iChar == '_' || iChar == ':');
8e54aaed
RD
67}
68
1dcf666d 69// Is the character is a ! and the the next character is not a !
1e9bafca
RD
70inline bool IsACommentStart(const int iChar) {
71
72 return(iChar == '!');
8e54aaed
RD
73}
74
75// Is the character a Clarion hex character (ABCDEF)
76inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) {
1e9bafca 77
8e54aaed
RD
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)
94inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) {
1e9bafca 95
8e54aaed
RD
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
114inline bool SetNumericConstantState(StyleContext &scDoc) {
1e9bafca 115
8e54aaed 116 int iPoints = 0; // Point counter
1e9bafca 117 char cNumericString[512]; // Numeric string buffer
8e54aaed
RD
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;
1dcf666d 132 }
8e54aaed
RD
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
1e9bafca
RD
144// Get the next word in uppercase from the current position (keyword lookahead)
145inline 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
8e54aaed 176// Clarion Language Colouring Procedure
1e9bafca
RD
177static 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)
8e54aaed 191
1dcf666d 192 const char wlProcReservedKeywordList[] =
1e9bafca
RD
193 "PROCEDURE FUNCTION";
194 WordList wlProcReservedKeywords;
195 wlProcReservedKeywords.Set(wlProcReservedKeywordList);
8e54aaed 196
1dcf666d 197 const char wlCompilerKeywordList[] =
1e9bafca
RD
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);
8e54aaed
RD
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 == '.') {
1e9bafca
RD
222 // Turn off column 1 label flag as label now cannot be reserved work
223 iColumn1Label = false;
8e54aaed
RD
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 }
1e9bafca 230 // Else check label
8e54aaed 231 else {
1e9bafca 232 char cLabel[512]; // Label buffer
8e54aaed
RD
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) {
1e9bafca 237 StringUpper(cLabel);
8e54aaed 238 }
1e9bafca
RD
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
8e54aaed
RD
247 scDoc.ChangeState(SCE_CLW_ERROR);
248 }
1dcf666d 249 // Else if UPPERCASE label string is
1e9bafca
RD
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 }
8e54aaed
RD
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 == ':') {
1e9bafca 275 char cEquate[512]; // Equate buffer
8e54aaed
RD
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) {
1e9bafca 282 StringUpper(cEquate);
8e54aaed
RD
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)) {
1e9bafca 292 char cStatement[512]; // Statement buffer
8e54aaed
RD
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) {
1e9bafca 297 StringUpper(cStatement);
8e54aaed
RD
298 }
299 // If statement string is in the Clarion keyword list
300 if (wlClarionKeywords.InList(cStatement)) {
1e9bafca 301 // Change the statement string to the Clarion keyword state
8e54aaed
RD
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)) {
1e9bafca 306 // Change the statement string to the compiler directive state
8e54aaed
RD
307 scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
308 }
1e9bafca
RD
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 }
8e54aaed
RD
314 // Else if statement string is in the builtin procedures and functions keyword list
315 else if (wlBuiltInProcsFuncs.InList(cStatement)) {
1e9bafca 316 // Change the statement string to the builtin procedures and functions state
8e54aaed
RD
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)) {
1e9bafca 321 // Change the statement string to the structures and data types state
8e54aaed
RD
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)) {
1e9bafca 326 // Change the statement string to the procedure attribute state
8e54aaed
RD
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)) {
1e9bafca 331 // Change the statement string to the standard equate state
8e54aaed
RD
332 scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
333 }
1e9bafca
RD
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 }
8e54aaed
RD
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 }
1dcf666d 374 // Else if the character is a ) (close parenthese)
8e54aaed
RD
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);
1dcf666d 380 }
8e54aaed
RD
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))) {
1dcf666d 405 // If the number was a real
8e54aaed
RD
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) {
1e9bafca
RD
426 // Reset the column 1 label flag
427 iColumn1Label = false;
8e54aaed
RD
428 // If column 1 character is a label start character
429 if (IsALabelStart(scDoc.ch)) {
1e9bafca
RD
430 // Label character is found in column 1
431 // so set column 1 label flag and clear last column 1 label
432 iColumn1Label = true;
8e54aaed
RD
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 }
1e9bafca
RD
441 // else if comment start (!) or is an * (asterisk)
442 else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) {
8e54aaed
RD
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 {
1dcf666d 467 // If in default state
8e54aaed
RD
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)
1e9bafca 480 else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') {
8e54aaed
RD
481 // then set the state to comment.
482 scDoc.SetState(SCE_CLW_COMMENT);
1dcf666d 483 }
8e54aaed
RD
484 // else if the character is a ' (single quote)
485 else if (scDoc.ch == '\'') {
1dcf666d 486 // If the character is also a ' (single quote)
8e54aaed
RD
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 }
1dcf666d 496 }
1e9bafca 497 // else the character is an @ (ampersand)
8e54aaed
RD
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 }
1dcf666d 515 }
8e54aaed
RD
516 }
517 }
518 }
519 // lexing complete
520 scDoc.Complete();
521}
522
523// Clarion Language Case Sensitive Colouring Procedure
1e9bafca
RD
524static void ColouriseClarionDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
525
526 ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true);
8e54aaed
RD
527}
528
529// Clarion Language Case Insensitive Colouring Procedure
1e9bafca
RD
530static 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
537static 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
550static 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);
8e54aaed
RD
599}
600
601// Clarion Language Folding Procedure
1e9bafca
RD
602static 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');
1dcf666d 622
1e9bafca
RD
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 }
1dcf666d 653
1e9bafca
RD
654 if (!isspacechar(chChar))
655 iVisibleChars++;
656 }
8e54aaed 657
1e9bafca
RD
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);
8e54aaed 662}
8e54aaed
RD
663
664// Word List Descriptions
665static const char * const rgWordListDescriptions[] = {
666 "Clarion Keywords",
667 "Compiler Directives",
668 "Built-in Procedures and Functions",
1e9bafca 669 "Runtime Expressions",
8e54aaed
RD
670 "Structure and Data Types",
671 "Attributes",
672 "Standard Equates",
1e9bafca
RD
673 "Reserved Words (Labels)",
674 "Reserved Words (Procedure Labels)",
8e54aaed
RD
675 0,
676};
677
678// Case Sensitive Clarion Language Lexer
1e9bafca 679LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions);
8e54aaed
RD
680
681// Case Insensitive Clarion Language Lexer
1e9bafca 682LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions);