"Fossies" - the Fresh Open Source Software Archive

Member "scintilla/lexers/LexCLW.cxx" (24 Oct 2019, 22108 Bytes) of package /windows/misc/scite421.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "LexCLW.cxx" see the Fossies "Dox" file reference documentation.

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