mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-04-08 17:15:37 +02:00
Release 5.5.2 ( https://www.scintilla.org/scintilla552.zip ) Released 21 August 2024. Add SCI_SETCOPYSEPARATOR for separator between parts of a multiple selection when copied to the clipboard. Feature #1530. Add SCI_GETUNDOSEQUENCE to determine whether an undo sequence is active and its nesting depth. Add SCI_STYLESETSTRETCH to support condensed and expanded text styles. Add SCI_LINEINDENT and SCI_LINEDEDENT. Feature #1524. Fix bug on Cocoa where double-click stopped working when system had been running for a long time. On Cocoa implement more values of font weight and stretch. Release 5.4.0 ( https://www.scintilla.org/lexilla540.zip ) Released 21 August 2024. Inside Lexilla, LexerModule instances are now const. This will require changes to applications that modify Lexilla.cxx, which may be done to add custom lexers. Lexer added for TOML "toml". Bash: Handle backslash in heredoc delimiter. Issue #257. Progress: Fix lexing of nested comments. Pull request #258. Force lower-casing of case-insensitive keyword lists so keywords match in some lexers. Issue #259. Close #15564
684 lines
22 KiB
C++
684 lines
22 KiB
C++
// Scintilla source code edit control
|
|
/** @file LexCLW.cxx
|
|
** Lexer for Clarion.
|
|
** 2004/12/17 Updated Lexer
|
|
**/
|
|
// Copyright 2003-2004 by Ron Schofield <ron@schofieldcomputer.com>
|
|
// The License.txt file describes the conditions under which this software may be distributed.
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
#include "ILexer.h"
|
|
#include "Scintilla.h"
|
|
#include "SciLexer.h"
|
|
|
|
#include "WordList.h"
|
|
#include "LexAccessor.h"
|
|
#include "Accessor.h"
|
|
#include "StyleContext.h"
|
|
#include "CharacterSet.h"
|
|
#include "LexerModule.h"
|
|
|
|
using namespace Lexilla;
|
|
|
|
// Is an end of line character
|
|
inline bool IsEOL(const int ch) {
|
|
|
|
return(ch == '\n');
|
|
}
|
|
|
|
// Convert character to uppercase
|
|
static char CharacterUpper(char chChar) {
|
|
|
|
if (chChar < 'a' || chChar > 'z') {
|
|
return(chChar);
|
|
}
|
|
else {
|
|
return(static_cast<char>(chChar - 'a' + 'A'));
|
|
}
|
|
}
|
|
|
|
// Convert string to uppercase
|
|
static void StringUpper(char *szString) {
|
|
|
|
while (*szString) {
|
|
*szString = CharacterUpper(*szString);
|
|
szString++;
|
|
}
|
|
}
|
|
|
|
// Is a label start character
|
|
inline bool IsALabelStart(const int iChar) {
|
|
|
|
return(isalpha(iChar) || iChar == '_');
|
|
}
|
|
|
|
// Is a label character
|
|
inline bool IsALabelCharacter(const int iChar) {
|
|
|
|
return(isalnum(iChar) || iChar == '_' || iChar == ':');
|
|
}
|
|
|
|
// Is the character is a ! and the the next character is not a !
|
|
inline bool IsACommentStart(const int iChar) {
|
|
|
|
return(iChar == '!');
|
|
}
|
|
|
|
// Is the character a Clarion hex character (ABCDEF)
|
|
inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) {
|
|
|
|
// Case insensitive.
|
|
if (!bCaseSensitive) {
|
|
if (strchr("ABCDEFabcdef", iChar) != NULL) {
|
|
return(true);
|
|
}
|
|
}
|
|
// Case sensitive
|
|
else {
|
|
if (strchr("ABCDEF", iChar) != NULL) {
|
|
return(true);
|
|
}
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
// Is the character a Clarion base character (B=Binary, O=Octal, H=Hex)
|
|
inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) {
|
|
|
|
// Case insensitive.
|
|
if (!bCaseSensitive) {
|
|
// If character is a numeric base character
|
|
if (strchr("BOHboh", iChar) != NULL) {
|
|
return(true);
|
|
}
|
|
}
|
|
// Case sensitive
|
|
else {
|
|
// If character is a numeric base character
|
|
if (strchr("BOH", iChar) != NULL) {
|
|
return(true);
|
|
}
|
|
}
|
|
return(false);
|
|
}
|
|
|
|
// Set the correct numeric constant state
|
|
inline bool SetNumericConstantState(StyleContext &scDoc) {
|
|
|
|
int iPoints = 0; // Point counter
|
|
char cNumericString[512]; // Numeric string buffer
|
|
|
|
// Buffer the current numberic string
|
|
scDoc.GetCurrent(cNumericString, sizeof(cNumericString));
|
|
// Loop through the string until end of string (NULL termination)
|
|
for (int iIndex = 0; cNumericString[iIndex] != '\0'; iIndex++) {
|
|
// Depending on the character
|
|
switch (cNumericString[iIndex]) {
|
|
// Is a . (point)
|
|
case '.' :
|
|
// Increment point counter
|
|
iPoints++;
|
|
break;
|
|
default :
|
|
break;
|
|
}
|
|
}
|
|
// If points found (can be more than one for improper formatted number
|
|
if (iPoints > 0) {
|
|
return(true);
|
|
}
|
|
// Else no points found
|
|
else {
|
|
return(false);
|
|
}
|
|
}
|
|
|
|
// Get the next word in uppercase from the current position (keyword lookahead)
|
|
inline bool GetNextWordUpper(Accessor &styler, Sci_PositionU uiStartPos, Sci_Position iLength, char *cWord) {
|
|
|
|
Sci_PositionU iIndex = 0; // Buffer Index
|
|
|
|
// Loop through the remaining string from the current position
|
|
for (Sci_Position iOffset = uiStartPos; iOffset < iLength; iOffset++) {
|
|
// Get the character from the buffer using the offset
|
|
char cCharacter = styler[iOffset];
|
|
if (IsEOL(cCharacter)) {
|
|
break;
|
|
}
|
|
// If the character is alphabet character
|
|
if (isalpha(cCharacter)) {
|
|
// Add UPPERCASE character to the word buffer
|
|
cWord[iIndex++] = CharacterUpper(cCharacter);
|
|
}
|
|
}
|
|
// Add null termination
|
|
cWord[iIndex] = '\0';
|
|
// If no word was found
|
|
if (iIndex == 0) {
|
|
// Return failure
|
|
return(false);
|
|
}
|
|
// Else word was found
|
|
else {
|
|
// Return success
|
|
return(true);
|
|
}
|
|
}
|
|
|
|
// Clarion Language Colouring Procedure
|
|
static void ColouriseClarionDoc(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) {
|
|
|
|
int iParenthesesLevel = 0; // Parenthese Level
|
|
int iColumn1Label = false; // Label starts in Column 1
|
|
|
|
WordList &wlClarionKeywords = *wlKeywords[0]; // Clarion Keywords
|
|
WordList &wlCompilerDirectives = *wlKeywords[1]; // Compiler Directives
|
|
WordList &wlRuntimeExpressions = *wlKeywords[2]; // Runtime Expressions
|
|
WordList &wlBuiltInProcsFuncs = *wlKeywords[3]; // Builtin Procedures and Functions
|
|
WordList &wlStructsDataTypes = *wlKeywords[4]; // Structures and Data Types
|
|
WordList &wlAttributes = *wlKeywords[5]; // Procedure Attributes
|
|
WordList &wlStandardEquates = *wlKeywords[6]; // Standard Equates
|
|
WordList &wlLabelReservedWords = *wlKeywords[7]; // Clarion Reserved Keywords (Labels)
|
|
WordList &wlProcLabelReservedWords = *wlKeywords[8]; // Clarion Reserved Keywords (Procedure Labels)
|
|
|
|
const char wlProcReservedKeywordList[] =
|
|
"PROCEDURE FUNCTION";
|
|
WordList wlProcReservedKeywords;
|
|
wlProcReservedKeywords.Set(wlProcReservedKeywordList);
|
|
|
|
const char wlCompilerKeywordList[] =
|
|
"COMPILE OMIT";
|
|
WordList wlCompilerKeywords;
|
|
wlCompilerKeywords.Set(wlCompilerKeywordList);
|
|
|
|
const char wlLegacyStatementsList[] =
|
|
"BOF EOF FUNCTION POINTER SHARE";
|
|
WordList wlLegacyStatements;
|
|
wlLegacyStatements.Set(wlLegacyStatementsList);
|
|
|
|
StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler);
|
|
|
|
// lex source code
|
|
for (; scDoc.More(); scDoc.Forward())
|
|
{
|
|
//
|
|
// Determine if the current state should terminate.
|
|
//
|
|
|
|
// Label State Handling
|
|
if (scDoc.state == SCE_CLW_LABEL) {
|
|
// If the character is not a valid label
|
|
if (!IsALabelCharacter(scDoc.ch)) {
|
|
// If the character is a . (dot syntax)
|
|
if (scDoc.ch == '.') {
|
|
// Turn off column 1 label flag as label now cannot be reserved work
|
|
iColumn1Label = false;
|
|
// Uncolour the . (dot) to default state, move forward one character,
|
|
// and change back to the label state.
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
scDoc.Forward();
|
|
scDoc.SetState(SCE_CLW_LABEL);
|
|
}
|
|
// Else check label
|
|
else {
|
|
char cLabel[512]; // Label buffer
|
|
// Buffer the current label string
|
|
scDoc.GetCurrent(cLabel,sizeof(cLabel));
|
|
// If case insensitive, convert string to UPPERCASE to match passed keywords.
|
|
if (!bCaseSensitive) {
|
|
StringUpper(cLabel);
|
|
}
|
|
// Else if UPPERCASE label string is in the Clarion compiler keyword list
|
|
if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){
|
|
// change the label to error state
|
|
scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
|
|
}
|
|
// Else if UPPERCASE label string is in the Clarion reserved keyword list
|
|
else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){
|
|
// change the label to error state
|
|
scDoc.ChangeState(SCE_CLW_ERROR);
|
|
}
|
|
// Else if UPPERCASE label string is
|
|
else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) {
|
|
char cWord[512]; // Word buffer
|
|
// Get the next word from the current position
|
|
if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) {
|
|
// If the next word is a procedure reserved word
|
|
if (wlProcReservedKeywords.InList(cWord)) {
|
|
// Change the label to error state
|
|
scDoc.ChangeState(SCE_CLW_ERROR);
|
|
}
|
|
}
|
|
}
|
|
// Else if label string is in the compiler directive keyword list
|
|
else if (wlCompilerDirectives.InList(cLabel)) {
|
|
// change the state to compiler directive state
|
|
scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
|
|
}
|
|
// Terminate the label state and set to default state
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
}
|
|
}
|
|
}
|
|
// Keyword State Handling
|
|
else if (scDoc.state == SCE_CLW_KEYWORD) {
|
|
// If character is : (colon)
|
|
if (scDoc.ch == ':') {
|
|
char cEquate[512]; // Equate buffer
|
|
// Move forward to include : (colon) in buffer
|
|
scDoc.Forward();
|
|
// Buffer the equate string
|
|
scDoc.GetCurrent(cEquate,sizeof(cEquate));
|
|
// If case insensitive, convert string to UPPERCASE to match passed keywords.
|
|
if (!bCaseSensitive) {
|
|
StringUpper(cEquate);
|
|
}
|
|
// If statement string is in the equate list
|
|
if (wlStandardEquates.InList(cEquate)) {
|
|
// Change to equate state
|
|
scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
|
|
}
|
|
}
|
|
// If the character is not a valid label character
|
|
else if (!IsALabelCharacter(scDoc.ch)) {
|
|
char cStatement[512]; // Statement buffer
|
|
// Buffer the statement string
|
|
scDoc.GetCurrent(cStatement,sizeof(cStatement));
|
|
// If case insensitive, convert string to UPPERCASE to match passed keywords.
|
|
if (!bCaseSensitive) {
|
|
StringUpper(cStatement);
|
|
}
|
|
// If statement string is in the Clarion keyword list
|
|
if (wlClarionKeywords.InList(cStatement)) {
|
|
// Change the statement string to the Clarion keyword state
|
|
scDoc.ChangeState(SCE_CLW_KEYWORD);
|
|
}
|
|
// Else if statement string is in the compiler directive keyword list
|
|
else if (wlCompilerDirectives.InList(cStatement)) {
|
|
// Change the statement string to the compiler directive state
|
|
scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
|
|
}
|
|
// Else if statement string is in the runtime expressions keyword list
|
|
else if (wlRuntimeExpressions.InList(cStatement)) {
|
|
// Change the statement string to the runtime expressions state
|
|
scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS);
|
|
}
|
|
// Else if statement string is in the builtin procedures and functions keyword list
|
|
else if (wlBuiltInProcsFuncs.InList(cStatement)) {
|
|
// Change the statement string to the builtin procedures and functions state
|
|
scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION);
|
|
}
|
|
// Else if statement string is in the tructures and data types keyword list
|
|
else if (wlStructsDataTypes.InList(cStatement)) {
|
|
// Change the statement string to the structures and data types state
|
|
scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE);
|
|
}
|
|
// Else if statement string is in the procedure attribute keyword list
|
|
else if (wlAttributes.InList(cStatement)) {
|
|
// Change the statement string to the procedure attribute state
|
|
scDoc.ChangeState(SCE_CLW_ATTRIBUTE);
|
|
}
|
|
// Else if statement string is in the standard equate keyword list
|
|
else if (wlStandardEquates.InList(cStatement)) {
|
|
// Change the statement string to the standard equate state
|
|
scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
|
|
}
|
|
// Else if statement string is in the deprecated or legacy keyword list
|
|
else if (wlLegacyStatements.InList(cStatement)) {
|
|
// Change the statement string to the standard equate state
|
|
scDoc.ChangeState(SCE_CLW_DEPRECATED);
|
|
}
|
|
// Else the statement string doesn't match any work list
|
|
else {
|
|
// Change the statement string to the default state
|
|
scDoc.ChangeState(SCE_CLW_DEFAULT);
|
|
}
|
|
// Terminate the keyword state and set to default state
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
}
|
|
}
|
|
// String State Handling
|
|
else if (scDoc.state == SCE_CLW_STRING) {
|
|
// If the character is an ' (single quote)
|
|
if (scDoc.ch == '\'') {
|
|
// Set the state to default and move forward colouring
|
|
// the ' (single quote) as default state
|
|
// terminating the string state
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
scDoc.Forward();
|
|
}
|
|
// If the next character is an ' (single quote)
|
|
if (scDoc.chNext == '\'') {
|
|
// Move forward one character and set to default state
|
|
// colouring the next ' (single quote) as default state
|
|
// terminating the string state
|
|
scDoc.ForwardSetState(SCE_CLW_DEFAULT);
|
|
scDoc.Forward();
|
|
}
|
|
}
|
|
// Picture String State Handling
|
|
else if (scDoc.state == SCE_CLW_PICTURE_STRING) {
|
|
// If the character is an ( (open parenthese)
|
|
if (scDoc.ch == '(') {
|
|
// Increment the parenthese level
|
|
iParenthesesLevel++;
|
|
}
|
|
// Else if the character is a ) (close parenthese)
|
|
else if (scDoc.ch == ')') {
|
|
// If the parenthese level is set to zero
|
|
// parentheses matched
|
|
if (!iParenthesesLevel) {
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
}
|
|
// Else parenthese level is greater than zero
|
|
// still looking for matching parentheses
|
|
else {
|
|
// Decrement the parenthese level
|
|
iParenthesesLevel--;
|
|
}
|
|
}
|
|
}
|
|
// Standard Equate State Handling
|
|
else if (scDoc.state == SCE_CLW_STANDARD_EQUATE) {
|
|
if (!isalnum(scDoc.ch)) {
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
}
|
|
}
|
|
// Integer Constant State Handling
|
|
else if (scDoc.state == SCE_CLW_INTEGER_CONSTANT) {
|
|
// If the character is not a digit (0-9)
|
|
// or character is not a hexidecimal character (A-F)
|
|
// or character is not a . (point)
|
|
// or character is not a numberic base character (B,O,H)
|
|
if (!(isdigit(scDoc.ch)
|
|
|| IsAHexCharacter(scDoc.ch, bCaseSensitive)
|
|
|| scDoc.ch == '.'
|
|
|| IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) {
|
|
// If the number was a real
|
|
if (SetNumericConstantState(scDoc)) {
|
|
// Colour the matched string to the real constant state
|
|
scDoc.ChangeState(SCE_CLW_REAL_CONSTANT);
|
|
}
|
|
// Else the number was an integer
|
|
else {
|
|
// Colour the matched string to an integer constant state
|
|
scDoc.ChangeState(SCE_CLW_INTEGER_CONSTANT);
|
|
}
|
|
// Terminate the integer constant state and set to default state
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Determine if a new state should be entered.
|
|
//
|
|
|
|
// Beginning of Line Handling
|
|
if (scDoc.atLineStart) {
|
|
// Reset the column 1 label flag
|
|
iColumn1Label = false;
|
|
// If column 1 character is a label start character
|
|
if (IsALabelStart(scDoc.ch)) {
|
|
// Label character is found in column 1
|
|
// so set column 1 label flag and clear last column 1 label
|
|
iColumn1Label = true;
|
|
// Set the state to label
|
|
scDoc.SetState(SCE_CLW_LABEL);
|
|
}
|
|
// else if character is a space or tab
|
|
else if (IsASpace(scDoc.ch)){
|
|
// Set to default state
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
}
|
|
// else if comment start (!) or is an * (asterisk)
|
|
else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) {
|
|
// then set the state to comment.
|
|
scDoc.SetState(SCE_CLW_COMMENT);
|
|
}
|
|
// else the character is a ? (question mark)
|
|
else if (scDoc.ch == '?') {
|
|
// Change to the compiler directive state, move forward,
|
|
// colouring the ? (question mark), change back to default state.
|
|
scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
|
|
scDoc.Forward();
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
}
|
|
// else an invalid character in column 1
|
|
else {
|
|
// Set to error state
|
|
scDoc.SetState(SCE_CLW_ERROR);
|
|
}
|
|
}
|
|
// End of Line Handling
|
|
else if (scDoc.atLineEnd) {
|
|
// Reset to the default state at the end of each line.
|
|
scDoc.SetState(SCE_CLW_DEFAULT);
|
|
}
|
|
// Default Handling
|
|
else {
|
|
// If in default state
|
|
if (scDoc.state == SCE_CLW_DEFAULT) {
|
|
// If is a letter could be a possible statement
|
|
if (isalpha(scDoc.ch)) {
|
|
// Set the state to Clarion Keyword and verify later
|
|
scDoc.SetState(SCE_CLW_KEYWORD);
|
|
}
|
|
// else is a number
|
|
else if (isdigit(scDoc.ch)) {
|
|
// Set the state to Integer Constant and verify later
|
|
scDoc.SetState(SCE_CLW_INTEGER_CONSTANT);
|
|
}
|
|
// else if the start of a comment or a | (line continuation)
|
|
else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') {
|
|
// then set the state to comment.
|
|
scDoc.SetState(SCE_CLW_COMMENT);
|
|
}
|
|
// else if the character is a ' (single quote)
|
|
else if (scDoc.ch == '\'') {
|
|
// If the character is also a ' (single quote)
|
|
// Embedded Apostrophe
|
|
if (scDoc.chNext == '\'') {
|
|
// Move forward colouring it as default state
|
|
scDoc.ForwardSetState(SCE_CLW_DEFAULT);
|
|
}
|
|
else {
|
|
// move to the next character and then set the state to comment.
|
|
scDoc.ForwardSetState(SCE_CLW_STRING);
|
|
}
|
|
}
|
|
// else the character is an @ (ampersand)
|
|
else if (scDoc.ch == '@') {
|
|
// Case insensitive.
|
|
if (!bCaseSensitive) {
|
|
// If character is a valid picture token character
|
|
if (strchr("DEKNPSTdeknpst", scDoc.chNext) != NULL) {
|
|
// Set to the picture string state
|
|
scDoc.SetState(SCE_CLW_PICTURE_STRING);
|
|
}
|
|
}
|
|
// Case sensitive
|
|
else {
|
|
// If character is a valid picture token character
|
|
if (strchr("DEKNPST", scDoc.chNext) != NULL) {
|
|
// Set the picture string state
|
|
scDoc.SetState(SCE_CLW_PICTURE_STRING);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// lexing complete
|
|
scDoc.Complete();
|
|
}
|
|
|
|
// Clarion Language Case Sensitive Colouring Procedure
|
|
static void ColouriseClarionDocSensitive(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
|
|
|
|
ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true);
|
|
}
|
|
|
|
// Clarion Language Case Insensitive Colouring Procedure
|
|
static void ColouriseClarionDocInsensitive(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
|
|
|
|
ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false);
|
|
}
|
|
|
|
// Fill Buffer
|
|
|
|
static void FillBuffer(Sci_PositionU uiStart, Sci_PositionU uiEnd, Accessor &accStyler, char *szBuffer, Sci_PositionU uiLength) {
|
|
|
|
Sci_PositionU uiPos = 0;
|
|
|
|
while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) {
|
|
szBuffer[uiPos] = static_cast<char>(toupper(accStyler[uiStart + uiPos]));
|
|
uiPos++;
|
|
}
|
|
szBuffer[uiPos] = '\0';
|
|
}
|
|
|
|
// Classify Clarion Fold Point
|
|
|
|
static int ClassifyClarionFoldPoint(int iLevel, const char* szString) {
|
|
|
|
if (!(isdigit(szString[0]) || (szString[0] == '.'))) {
|
|
if (strcmp(szString, "PROCEDURE") == 0) {
|
|
// iLevel = SC_FOLDLEVELBASE + 1;
|
|
}
|
|
else if (strcmp(szString, "MAP") == 0 ||
|
|
strcmp(szString,"ACCEPT") == 0 ||
|
|
strcmp(szString,"BEGIN") == 0 ||
|
|
strcmp(szString,"CASE") == 0 ||
|
|
strcmp(szString,"EXECUTE") == 0 ||
|
|
strcmp(szString,"IF") == 0 ||
|
|
strcmp(szString,"ITEMIZE") == 0 ||
|
|
strcmp(szString,"INTERFACE") == 0 ||
|
|
strcmp(szString,"JOIN") == 0 ||
|
|
strcmp(szString,"LOOP") == 0 ||
|
|
strcmp(szString,"MODULE") == 0 ||
|
|
strcmp(szString,"RECORD") == 0) {
|
|
iLevel++;
|
|
}
|
|
else if (strcmp(szString, "APPLICATION") == 0 ||
|
|
strcmp(szString, "CLASS") == 0 ||
|
|
strcmp(szString, "DETAIL") == 0 ||
|
|
strcmp(szString, "FILE") == 0 ||
|
|
strcmp(szString, "FOOTER") == 0 ||
|
|
strcmp(szString, "FORM") == 0 ||
|
|
strcmp(szString, "GROUP") == 0 ||
|
|
strcmp(szString, "HEADER") == 0 ||
|
|
strcmp(szString, "INTERFACE") == 0 ||
|
|
strcmp(szString, "MENU") == 0 ||
|
|
strcmp(szString, "MENUBAR") == 0 ||
|
|
strcmp(szString, "OLE") == 0 ||
|
|
strcmp(szString, "OPTION") == 0 ||
|
|
strcmp(szString, "QUEUE") == 0 ||
|
|
strcmp(szString, "REPORT") == 0 ||
|
|
strcmp(szString, "SHEET") == 0 ||
|
|
strcmp(szString, "TAB") == 0 ||
|
|
strcmp(szString, "TOOLBAR") == 0 ||
|
|
strcmp(szString, "VIEW") == 0 ||
|
|
strcmp(szString, "WINDOW") == 0) {
|
|
iLevel++;
|
|
}
|
|
else if (strcmp(szString, "END") == 0 ||
|
|
strcmp(szString, "UNTIL") == 0 ||
|
|
strcmp(szString, "WHILE") == 0) {
|
|
iLevel--;
|
|
}
|
|
}
|
|
return(iLevel);
|
|
}
|
|
|
|
// Clarion Language Folding Procedure
|
|
static void FoldClarionDoc(Sci_PositionU uiStartPos, Sci_Position iLength, int iInitStyle, WordList *[], Accessor &accStyler) {
|
|
|
|
Sci_PositionU uiEndPos = uiStartPos + iLength;
|
|
Sci_Position iLineCurrent = accStyler.GetLine(uiStartPos);
|
|
int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK;
|
|
int iLevelCurrent = iLevelPrev;
|
|
char chNext = accStyler[uiStartPos];
|
|
int iStyle = iInitStyle;
|
|
int iStyleNext = accStyler.StyleAt(uiStartPos);
|
|
int iVisibleChars = 0;
|
|
Sci_Position iLastStart = 0;
|
|
|
|
for (Sci_PositionU uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) {
|
|
|
|
char chChar = chNext;
|
|
chNext = accStyler.SafeGetCharAt(uiPos + 1);
|
|
int iStylePrev = iStyle;
|
|
iStyle = iStyleNext;
|
|
iStyleNext = accStyler.StyleAt(uiPos + 1);
|
|
bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n');
|
|
|
|
if (iStylePrev == SCE_CLW_DEFAULT) {
|
|
if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) {
|
|
// Store last word start point.
|
|
iLastStart = uiPos;
|
|
}
|
|
}
|
|
|
|
if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) {
|
|
if(iswordchar(chChar) && !iswordchar(chNext)) {
|
|
char chBuffer[100];
|
|
FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer));
|
|
iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer);
|
|
// if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) {
|
|
// accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE);
|
|
// iLevelPrev = SC_FOLDLEVELBASE;
|
|
// }
|
|
}
|
|
}
|
|
|
|
if (bEOL) {
|
|
int iLevel = iLevelPrev;
|
|
if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0))
|
|
iLevel |= SC_FOLDLEVELHEADERFLAG;
|
|
if (iLevel != accStyler.LevelAt(iLineCurrent)) {
|
|
accStyler.SetLevel(iLineCurrent,iLevel);
|
|
}
|
|
iLineCurrent++;
|
|
iLevelPrev = iLevelCurrent;
|
|
iVisibleChars = 0;
|
|
}
|
|
|
|
if (!isspacechar(chChar))
|
|
iVisibleChars++;
|
|
}
|
|
|
|
// Fill in the real level of the next line, keeping the current flags
|
|
// as they will be filled in later.
|
|
int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
|
|
accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext);
|
|
}
|
|
|
|
// Word List Descriptions
|
|
static const char * const rgWordListDescriptions[] = {
|
|
"Clarion Keywords",
|
|
"Compiler Directives",
|
|
"Built-in Procedures and Functions",
|
|
"Runtime Expressions",
|
|
"Structure and Data Types",
|
|
"Attributes",
|
|
"Standard Equates",
|
|
"Reserved Words (Labels)",
|
|
"Reserved Words (Procedure Labels)",
|
|
0,
|
|
};
|
|
|
|
// Case Sensitive Clarion Language Lexer
|
|
extern const LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions);
|
|
|
|
// Case Insensitive Clarion Language Lexer
|
|
extern const LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions);
|