// Scintilla source code edit control // @file LexPowerPro.cxx // PowerPro utility, written by Bruce Switzer, is available from http://powerpro.webeddie.com // PowerPro lexer is written by Christopher Bean (cbean@cb-software.net) // // Lexer code heavily borrowed from: // LexAU3.cxx by Jos van der Zande // LexCPP.cxx by Neil Hodgson // LexVB.cxx by Neil Hodgson // // Changes: // 2008-10-25 - Initial release // 2008-10-26 - Changed how is hilighted in 'function ' so that // local isFunction = "" and local functions = "" don't get falsely highlighted // 2008-12-14 - Added bounds checking for szKeyword and szDo // - Replaced SetOfCharacters with CharacterSet // - Made sure that CharacterSet::Contains is passed only positive values // - Made sure that the return value of Accessor::SafeGetCharAt is positive before // passsing to functions that require positive values like isspacechar() // - Removed unused visibleChars processing from ColourisePowerProDoc() // - Fixed bug with folding logic where line continuations didn't end where // they were supposed to // - Moved all helper functions to the top of the file // // Copyright 1998-2005 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include #include #include #include #include #include "Platform.h" #include "PropSet.h" #include "Accessor.h" #include "StyleContext.h" #include "KeyWords.h" #include "Scintilla.h" #include "SciLexer.h" #include "CharacterSet.h" #ifdef SCI_NAMESPACE using namespace Scintilla; #endif static inline bool IsStreamCommentStyle(int style) { return style == SCE_POWERPRO_COMMENTBLOCK; } static bool IsContinuationLine(unsigned int szLine, Accessor &styler) { int nsPos = styler.LineStart(szLine); int nePos = styler.LineStart(szLine + 1) - 2; while (nsPos < nePos) { int stylech = styler.StyleAt(nsPos); if (!(stylech == SCE_POWERPRO_COMMENTBLOCK)) { char ch = styler.SafeGetCharAt(nePos); char chPrev = styler.SafeGetCharAt(nePos-1); char chPrevPrev = styler.SafeGetCharAt(nePos-2); if (ch > 0 && chPrev > 0 && chPrevPrev > 0 && !isspacechar(ch) && !isspacechar(chPrev) && !isspacechar(chPrevPrev) ) { if (chPrevPrev == ';' && chPrev == ';' && ch == '+') return true; else return false; } } nePos--; // skip to next char } return false; } // Routine to find first none space on the current line and return its Style // needed for comment lines not starting on pos 1 static int GetStyleFirstWord(unsigned int szLine, Accessor &styler) { int nsPos = styler.LineStart(szLine); int nePos = styler.LineStart(szLine+1) - 1; char ch = styler.SafeGetCharAt(nsPos); while (ch > 0 && isspacechar(ch) && nsPos < nePos) { nsPos++; // skip to next char ch = styler.SafeGetCharAt(nsPos); } return styler.StyleAt(nsPos); } //returns true if there is a function to highlight //used to highlight in 'function ' static bool HasFunction(Accessor &styler, unsigned int currentPos) { //check for presence of 'function ' return (styler.SafeGetCharAt(currentPos) == ' ' && tolower(styler.SafeGetCharAt(currentPos-1)) == 'n' && tolower(styler.SafeGetCharAt(currentPos-2)) == 'o' && tolower(styler.SafeGetCharAt(currentPos-3)) == 'i' && tolower(styler.SafeGetCharAt(currentPos-4)) == 't' && tolower(styler.SafeGetCharAt(currentPos-5)) == 'c' && tolower(styler.SafeGetCharAt(currentPos-6)) == 'n' && tolower(styler.SafeGetCharAt(currentPos-7)) == 'u' && tolower(styler.SafeGetCharAt(currentPos-8)) == 'f' //only allow 'function ' to appear at the beginning of a line && (styler.SafeGetCharAt(currentPos-9) == '\n' || styler.SafeGetCharAt(currentPos-9) == '\r' || (styler.SafeGetCharAt(currentPos -9, '\0')) == '\0') //is the first line ); } static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler, bool caseSensitive) { WordList &keywords = *keywordlists[0]; WordList &keywords2 = *keywordlists[1]; WordList &keywords3 = *keywordlists[2]; WordList &keywords4 = *keywordlists[3]; //define the character sets CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true); CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); StyleContext sc(startPos, length, initStyle, styler); char s_save[100]; //for last line highlighting for (; sc.More(); sc.Forward()) { // ********************************************** // save the total current word for eof processing char s[100]; sc.GetCurrentLowered(s, sizeof(s)); if ((sc.ch > 0) && setWord.Contains(sc.ch)) { strcpy(s_save,s); int tp = strlen(s_save); if (tp < 99) { s_save[tp] = static_cast(tolower(sc.ch)); s_save[tp+1] = '\0'; } } // ********************************************** // if (sc.atLineStart) { if (sc.state == SCE_POWERPRO_DOUBLEQUOTEDSTRING) { // Prevent SCE_POWERPRO_STRINGEOL from leaking back to previous line which // ends with a line continuation by locking in the state upto this position. sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING); } } // Determine if the current state should terminate. switch (sc.state) { case SCE_POWERPRO_OPERATOR: sc.SetState(SCE_POWERPRO_DEFAULT); break; case SCE_POWERPRO_NUMBER: if (!IsADigit(sc.ch)) sc.SetState(SCE_POWERPRO_DEFAULT); break; case SCE_POWERPRO_IDENTIFIER: //if ((sc.ch > 0) && !setWord.Contains(sc.ch) || (sc.ch == '.')) { // use this line if don't want to match keywords with . in them. ie: win.debug will match both win and debug so win debug will also be colorized if ((sc.ch > 0) && !setWord.Contains(sc.ch)){ // || (sc.ch == '.')) { // use this line if you want to match keywords with a . ie: win.debug will only match win.debug neither win nor debug will be colorized separately char s[1000]; if (caseSensitive) { sc.GetCurrent(s, sizeof(s)); } else { sc.GetCurrentLowered(s, sizeof(s)); } if (keywords.InList(s)) { sc.ChangeState(SCE_POWERPRO_WORD); } else if (keywords2.InList(s)) { sc.ChangeState(SCE_POWERPRO_WORD2); } else if (keywords3.InList(s)) { sc.ChangeState(SCE_POWERPRO_WORD3); } else if (keywords4.InList(s)) { sc.ChangeState(SCE_POWERPRO_WORD4); } sc.SetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_LINECONTINUE: if (sc.atLineStart) { sc.SetState(SCE_POWERPRO_DEFAULT); } else if (sc.Match('/', '*') || sc.Match('/', '/')) { sc.SetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_COMMENTBLOCK: if (sc.Match('*', '/')) { sc.Forward(); sc.ForwardSetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_COMMENTLINE: if (sc.atLineStart) { sc.SetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_DOUBLEQUOTEDSTRING: if (sc.atLineEnd) { sc.ChangeState(SCE_POWERPRO_STRINGEOL); } else if (sc.ch == '\\') { if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { sc.Forward(); } } else if (sc.ch == '\"') { sc.ForwardSetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_SINGLEQUOTEDSTRING: if (sc.atLineEnd) { sc.ChangeState(SCE_POWERPRO_STRINGEOL); } else if (sc.ch == '\\') { if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { sc.Forward(); } } else if (sc.ch == '\'') { sc.ForwardSetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_STRINGEOL: if (sc.atLineStart) { sc.SetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_VERBATIM: if (sc.ch == '\"') { if (sc.chNext == '\"') { sc.Forward(); } else { sc.ForwardSetState(SCE_POWERPRO_DEFAULT); } } break; case SCE_POWERPRO_ALTQUOTE: if (sc.ch == '#') { if (sc.chNext == '#') { sc.Forward(); } else { sc.ForwardSetState(SCE_POWERPRO_DEHTTP/1.1 200 OK Connection: keep-alive Connection: keep-alive Content-Disposition: inline; filename="LexPowerPro.cxx" Content-Disposition: inline; filename="LexPowerPro.cxx" Content-Length: 19317 Content-Length: 19317 Content-Security-Policy: default-src 'none' Content-Security-Policy: default-src 'none' Content-Type: text/plain; charset=UTF-8 Content-Type: text/plain; charset=UTF-8 Date: Sun, 19 Oct 2025 02:04:13 UTC ETag: "9320baf94389987b6fcbb44a323b4c7f1ef6f54b" ETag: "9320baf94389987b6fcbb44a323b4c7f1ef6f54b" Expires: Wed, 17 Oct 2035 02:04:13 GMT Expires: Wed, 17 Oct 2035 02:04:13 GMT Last-Modified: Sun, 19 Oct 2025 02:04:13 GMT Last-Modified: Sun, 19 Oct 2025 02:04:13 GMT Server: OpenBSD httpd Server: OpenBSD httpd X-Content-Type-Options: nosniff X-Content-Type-Options: nosniff // Scintilla source code edit control // @file LexPowerPro.cxx // PowerPro utility, written by Bruce Switzer, is available from http://powerpro.webeddie.com // PowerPro lexer is written by Christopher Bean (cbean@cb-software.net) // // Lexer code heavily borrowed from: // LexAU3.cxx by Jos van der Zande // LexCPP.cxx by Neil Hodgson // LexVB.cxx by Neil Hodgson // // Changes: // 2008-10-25 - Initial release // 2008-10-26 - Changed how is hilighted in 'function ' so that // local isFunction = "" and local functions = "" don't get falsely highlighted // 2008-12-14 - Added bounds checking for szKeyword and szDo // - Replaced SetOfCharacters with CharacterSet // - Made sure that CharacterSet::Contains is passed only positive values // - Made sure that the return value of Accessor::SafeGetCharAt is positive before // passsing to functions that require positive values like isspacechar() // - Removed unused visibleChars processing from ColourisePowerProDoc() // - Fixed bug with folding logic where line continuations didn't end where // they were supposed to // - Moved all helper functions to the top of the file // // Copyright 1998-2005 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. #include #include #include #include #include #include "Platform.h" #include "PropSet.h" #include "Accessor.h" #include "StyleContext.h" #include "KeyWords.h" #include "Scintilla.h" #include "SciLexer.h" #include "CharacterSet.h" #ifdef SCI_NAMESPACE using namespace Scintilla; #endif static inline bool IsStreamCommentStyle(int style) { return style == SCE_POWERPRO_COMMENTBLOCK; } static bool IsContinuationLine(unsigned int szLine, Accessor &styler) { int nsPos = styler.LineStart(szLine); int nePos = styler.LineStart(szLine + 1) - 2; while (nsPos < nePos) { int stylech = styler.StyleAt(nsPos); if (!(stylech == SCE_POWERPRO_COMMENTBLOCK)) { char ch = styler.SafeGetCharAt(nePos); char chPrev = styler.SafeGetCharAt(nePos-1); char chPrevPrev = styler.SafeGetCharAt(nePos-2); if (ch > 0 && chPrev > 0 && chPrevPrev > 0 && !isspacechar(ch) && !isspacechar(chPrev) && !isspacechar(chPrevPrev) ) { if (chPrevPrev == ';' && chPrev == ';' && ch == '+') return true; else return false; } } nePos--; // skip to next char } return false; } // Routine to find first none space on the current line and return its Style // needed for comment lines not starting on pos 1 static int GetStyleFirstWord(unsigned int szLine, Accessor &styler) { int nsPos = styler.LineStart(szLine); int nePos = styler.LineStart(szLine+1) - 1; char ch = styler.SafeGetCharAt(nsPos); while (ch > 0 && isspacechar(ch) && nsPos < nePos) { nsPos++; // skip to next char ch = styler.SafeGetCharAt(nsPos); } return styler.StyleAt(nsPos); } //returns true if there is a function to highlight //used to highlight in 'function ' static bool HasFunction(Accessor &styler, unsigned int currentPos) { //check for presence of 'function ' return (styler.SafeGetCharAt(currentPos) == ' ' && tolower(styler.SafeGetCharAt(currentPos-1)) == 'n' && tolower(styler.SafeGetCharAt(currentPos-2)) == 'o' && tolower(styler.SafeGetCharAt(currentPos-3)) == 'i' && tolower(styler.SafeGetCharAt(currentPos-4)) == 't' && tolower(styler.SafeGetCharAt(currentPos-5)) == 'c' && tolower(styler.SafeGetCharAt(currentPos-6)) == 'n' && tolower(styler.SafeGetCharAt(currentPos-7)) == 'u' && tolower(styler.SafeGetCharAt(currentPos-8)) == 'f' //only allow 'function ' to appear at the beginning of a line && (styler.SafeGetCharAt(currentPos-9) == '\n' || styler.SafeGetCharAt(currentPos-9) == '\r' || (styler.SafeGetCharAt(currentPos -9, '\0')) == '\0') //is the first line ); } static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler, bool caseSensitive) { WordList &keywords = *keywordlists[0]; WordList &keywords2 = *keywordlists[1]; WordList &keywords3 = *keywordlists[2]; WordList &keywords4 = *keywordlists[3]; //define the character sets CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true); CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); StyleContext sc(startPos, length, initStyle, styler); char s_save[100]; //for last line highlighting for (; sc.More(); sc.Forward()) { // ********************************************** // save the total current word for eof processing char s[100]; sc.GetCurrentLowered(s, sizeof(s)); if ((sc.ch > 0) && setWord.Contains(sc.ch)) { strcpy(s_save,s); int tp = strlen(s_save); if (tp < 99) { s_save[tp] = static_cast(tolower(sc.ch)); s_save[tp+1] = '\0'; } } // ********************************************** // if (sc.atLineStart) { if (sc.state == SCE_POWERPRO_DOUBLEQUOTEDSTRING) { // Prevent SCE_POWERPRO_STRINGEOL from leaking back to previous line which // ends with a line continuation by locking in the state upto this position. sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING); } } // Determine if the current state should terminate. switch (sc.state) { case SCE_POWERPRO_OPERATOR: sc.SetState(SCE_POWERPRO_DEFAULT); break; case SCE_POWERPRO_NUMBER: if (!IsADigit(sc.ch)) sc.SetState(SCE_POWERPRO_DEFAULT); break; case SCE_POWERPRO_IDENTIFIER: //if ((sc.ch > 0) && !setWord.Contains(sc.ch) || (sc.ch == '.')) { // use this line if don't want to match keywords with . in them. ie: win.debug will match both win and debug so win debug will also be colorized if ((sc.ch > 0) && !setWord.Contains(sc.ch)){ // || (sc.ch == '.')) { // use this line if you want to match keywords with a . ie: win.debug will only match win.debug neither win nor debug will be colorized separately char s[1000]; if (caseSensitive) { sc.GetCurrent(s, sizeof(s)); } else { sc.GetCurrentLowered(s, sizeof(s)); } if (keywords.InList(s)) { sc.ChangeState(SCE_POWERPRO_WORD); } else if (keywords2.InList(s)) { sc.ChangeState(SCE_POWERPRO_WORD2); } else if (keywords3.InList(s)) { sc.ChangeState(SCE_POWERPRO_WORD3); } else if (keywords4.InList(s)) { sc.ChangeState(SCE_POWERPRO_WORD4); } sc.SetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_LINECONTINUE: if (sc.atLineStart) { sc.SetState(SCE_POWERPRO_DEFAULT); } else if (sc.Match('/', '*') || sc.Match('/', '/')) { sc.SetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_COMMENTBLOCK: if (sc.Match('*', '/')) { sc.Forward(); sc.ForwardSetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_COMMENTLINE: if (sc.atLineStart) { sc.SetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_DOUBLEQUOTEDSTRING: if (sc.atLineEnd) { sc.ChangeState(SCE_POWERPRO_STRINGEOL); } else if (sc.ch == '\\') { if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { sc.Forward(); } } else if (sc.ch == '\"') { sc.ForwardSetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_SINGLEQUOTEDSTRING: if (sc.atLineEnd) { sc.ChangeState(SCE_POWERPRO_STRINGEOL); } else if (sc.ch == '\\') { if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { sc.Forward(); } } else if (sc.ch == '\'') { sc.ForwardSetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_STRINGEOL: if (sc.atLineStart) { sc.SetState(SCE_POWERPRO_DEFAULT); } break; case SCE_POWERPRO_VERBATIM: if (sc.ch == '\"') { if (sc.chNext == '\"') { sc.Forward(); } else { sc.ForwardSetState(SCE_POWERPRO_DEFAULT); } } break; case SCE_POWERPRO_ALTQUOTE: if (sc.ch == '#') { if (sc.chNext == '#') { sc.Forward(); } else { sc.ForwardSetState(SCE_POWERPRO_DEFAULT); } } break; case SCE_POWERPRO_FUNCTION: if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ' ' || sc.ch == '(') { sc.SetState(SCE_POWERPRO_DEFAULT); } break; } // Determine if a new state should be entered. if (sc.state == SCE_POWERPRO_DEFAULT) { if (sc.Match('?', '\"')) { sc.SetState(SCE_POWERPRO_VERBATIM); sc.Forward(); } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { sc.SetState(SCE_POWERPRO_NUMBER); }else if (sc.Match('?','#')) { if (sc.ch == '?' && sc.chNext == '#') { sc.SetState(SCE_POWERPRO_ALTQUOTE); sc.Forward(); } } else if (HasFunction(styler, sc.currentPos)) { //highlight in 'function ' sc.SetState(SCE_POWERPRO_FUNCTION); } else if (sc.ch == '@' && sc.atLineStart) { //alternate function definition [label] sc.SetState(SCE_POWERPRO_FUNCTION); } else if ((sc.ch > 0) && (setWordStart.Contains(sc.ch) || (sc.ch == '?'))) { sc.SetState(SCE_POWERPRO_IDENTIFIER); } else if (sc.Match(";;+")) { sc.SetState(SCE_POWERPRO_LINECONTINUE); } else if (sc.Match('/', '*')) { sc.SetState(SCE_POWERPRO_COMMENTBLOCK); sc.Forward(); // Eat the * so it isn't used for the end of the comment } else if (sc.Match('/', '/')) { sc.SetState(SCE_POWERPRO_COMMENTLINE); } else if (sc.atLineStart && sc.ch == ';') { //legacy comment that can only appear at the beginning of a line sc.SetState(SCE_POWERPRO_COMMENTLINE); } else if (sc.Match(";;")) { sc.SetState(SCE_POWERPRO_COMMENTLINE); } else if (sc.ch == '\"') { sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING); } else if (sc.ch == '\'') { sc.SetState(SCE_POWERPRO_SINGLEQUOTEDSTRING); } else if (isoperator(static_cast(sc.ch))) { sc.SetState(SCE_POWERPRO_OPERATOR); } } } //************************************* // Colourize the last word correctly //************************************* if (sc.state == SCE_POWERPRO_IDENTIFIER) { if (keywords.InList(s_save)) { sc.ChangeState(SCE_POWERPRO_WORD); sc.SetState(SCE_POWERPRO_DEFAULT);