123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911 |
- // Scintilla source code edit control
- // @file LexAU3.cxx
- // Lexer for AutoIt3 http://www.hiddensoft.com/autoit3
- // by Jos van der Zande, jvdzande@yahoo.com
- //
- // Changes:
- // March 28, 2004 - Added the standard Folding code
- // April 21, 2004 - Added Preprosessor Table + Syntax Highlighting
- // Fixed Number highlighting
- // Changed default isoperator to IsAOperator to have a better match to AutoIt3
- // Fixed "#comments_start" -> "#comments-start"
- // Fixed "#comments_end" -> "#comments-end"
- // Fixed Sendkeys in Strings when not terminated with }
- // Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down}
- // April 26, 2004 - Fixed # pre-processor statement inside of comment block would invalidly change the color.
- // Added logic for #include <xyz.au3> to treat the <> as string
- // Added underscore to IsAOperator.
- // May 17, 2004 - Changed the folding logic from indent to keyword folding.
- // Added Folding logic for blocks of single-commentlines or commentblock.
- // triggered by: fold.comment=1
- // Added Folding logic for preprocessor blocks triggered by fold.preprocessor=1
- // Added Special for #region - #endregion syntax highlight and folding.
- // May 30, 2004 - Fixed issue with continuation lines on If statements.
- // June 5, 2004 - Added comma to Operators for better readability.
- // Added fold.compact support set with fold.compact=1
- // Changed folding inside of #cs-#ce. Default is no keyword folding inside comment blocks when fold.comment=1
- // it will now only happen when fold.comment=2.
- // Sep 5, 2004 - Added logic to handle colourizing words on the last line.
- // Typed Characters now show as "default" till they match any table.
- // Oct 10, 2004 - Added logic to show Comments in "Special" directives.
- // Nov 1, 2004 - Added better testing for Numbers supporting x and e notation.
- // Nov 28, 2004 - Added logic to handle continuation lines for syntax highlighting.
- // Jan 10, 2005 - Added Abbreviations Keyword used for expansion
- // Mar 24, 2005 - Updated Abbreviations Keywords to fix when followed by Operator.
- // Apr 18, 2005 - Updated #CE/#Comment-End logic to take a linecomment ";" into account
- // - Added folding support for With...EndWith
- // - Added support for a DOT in variable names
- // - Fixed Underscore in CommentBlock
- // May 23, 2005 - Fixed the SentKey lexing in case of a missing }
- // Aug 11, 2005 - Fixed possible bug with s_save length > 100.
- // Aug 23, 2005 - Added Switch/endswitch support to the folding logic.
- // Sep 27, 2005 - Fixed the SentKey lexing logic in case of multiple sentkeys.
- // Mar 12, 2006 - Fixed issue with <> coloring as String in stead of Operator in rare occasions.
- // Apr 8, 2006 - Added support for AutoIt3 Standard UDF library (SCE_AU3_UDF)
- // Mar 9, 2007 - Fixed bug with + following a String getting the wrong Color.
- // Jun 20, 2007 - Fixed Commentblock issue when LF's are used as EOL.
- // Jul 26, 2007 - Fixed #endregion undetected bug.
- //
- // Copyright for Scintilla: 1998-2001 by Neil Hodgson <neilh@scintilla.org>
- // The License.txt file describes the conditions under which this software may be distributed.
- // Scintilla source code edit control
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdarg.h>
- #include <assert.h>
- #include <ctype.h>
- #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"
- #ifdef SCI_NAMESPACE
- using namespace Scintilla;
- #endif
- static inline bool IsTypeCharacter(const int ch)
- {
- return ch == '$';
- }
- static inline bool IsAWordChar(const int ch)
- {
- return (ch < 0x80) && (isalnum(ch) || ch == '_');
- }
- static inline bool IsAWordStart(const int ch)
- {
- return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.');
- }
- static inline bool IsAOperator(char ch) {
- if (IsASCII(ch) && isalnum(ch))
- return false;
- if (ch == '+' || ch == '-' || ch == '*' || ch == '/' ||
- ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' ||
- ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == ',' )
- return true;
- return false;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // GetSendKey() filters the portion before and after a/multiple space(s)
- // and return the first portion to be looked-up in the table
- // also check if the second portion is valid... (up,down.on.off,toggle or a number)
- ///////////////////////////////////////////////////////////////////////////////
- static int GetSendKey(const char *szLine, char *szKey)
- {
- int nFlag = 0;
- int nStartFound = 0;
- int nKeyPos = 0;
- int nSpecPos= 0;
- int nSpecNum= 1;
- int nPos = 0;
- char cTemp;
- char szSpecial[100];
- // split the portion of the sendkey in the part before and after the spaces
- while ( ( (cTemp = szLine[nPos]) != '\0'))
- {
- // skip leading Ctrl/Shift/Alt state
- if (cTemp == '{') {
- nStartFound = 1;
- }
- //
- if (nStartFound == 1) {
- if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space
- {
- nFlag = 1;
- // Add } to the end of the first bit for table lookup later.
- szKey[nKeyPos++] = '}';
- }
- else if (cTemp == ' ')
- {
- // skip other spaces
- }
- else if (nFlag == 0)
- {
- // save first portion into var till space or } is hit
- szKey[nKeyPos++] = cTemp;
- }
- else if ((nFlag == 1) && (cTemp != '}'))
- {
- // Save second portion into var...
- szSpecial[nSpecPos++] = cTemp;
- // check if Second portion is all numbers for repeat fuction
- if (isdigit(cTemp) == false) {nSpecNum = 0;}
- }
- }
- nPos++; // skip to next char
- } // End While
- // Check if the second portion is either a number or one of these keywords
- szKey[nKeyPos] = '\0';
- szSpecial[nSpecPos] = '\0';
- if (strcmp(szSpecial,"down")== 0 || strcmp(szSpecial,"up")== 0 ||
- strcmp(szSpecial,"on")== 0 || strcmp(szSpecial,"off")== 0 ||
- strcmp(szSpecial,"toggle")== 0 || nSpecNum == 1 )
- {
- nFlag = 0;
- }
- else
- {
- nFlag = 1;
- }
- return nFlag; // 1 is bad, 0 is good
- } // GetSendKey()
- //
- // Routine to check the last "none comment" character on a line to see if its a continuation
- //
- static bool IsContinuationLine(Sci_PositionU szLine, Accessor &styler)
- {
- Sci_Position nsPos = styler.LineStart(szLine);
- Sci_Position nePos = styler.LineStart(szLine+1) - 2;
- //int stylech = styler.StyleAt(nsPos);
- while (nsPos < nePos)
- {
- //stylech = styler.StyleAt(nePos);
- int stylech = styler.StyleAt(nsPos);
- if (!(stylech == SCE_AU3_COMMENT)) {
- char ch = styler.SafeGetCharAt(nePos);
- if (!isspacechar(ch)) {
- if (ch == '_')
- return true;
- else
- return false;
- }
- }
- nePos--; // skip to next char
- } // End While
- return false;
- } // IsContinuationLine()
- //
- // syntax highlighting logic
- static void ColouriseAU3Doc(Sci_PositionU startPos,
- Sci_Position length, int initStyle,
- WordList *keywordlists[],
- Accessor &styler) {
- WordList &keywords = *keywordlists[0];
- WordList &keywords2 = *keywordlists[1];
- WordList &keywords3 = *keywordlists[2];
- WordList &keywords4 = *keywordlists[3];
- WordList &keywords5 = *keywordlists[4];
- WordList &keywords6 = *keywordlists[5];
- WordList &keywords7 = *keywordlists[6];
- WordList &keywords8 = *keywordlists[7];
- // find the first previous line without continuation character at the end
- Sci_Position lineCurrent = styler.GetLine(startPos);
- Sci_Position s_startPos = startPos;
- // When not inside a Block comment: find First line without _
- if (!(initStyle==SCE_AU3_COMMENTBLOCK)) {
- while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) ||
- (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) {
- lineCurrent--;
- startPos = styler.LineStart(lineCurrent); // get start position
- initStyle = 0; // reset the start style to 0
- }
- }
- // Set the new length to include it from the start and set the start position
- length = length + s_startPos - startPos; // correct the total length to process
- styler.StartAt(startPos);
- StyleContext sc(startPos, length, initStyle, styler);
- char si; // string indicator "=1 '=2
- char ni; // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3
- char ci; // comment indicator 0=not linecomment(;)
- char s_save[100] = "";
- si=0;
- ni=0;
- ci=0;
- //$$$
- for (; sc.More(); sc.Forward()) {
- char s[100];
- sc.GetCurrentLowered(s, sizeof(s));
- // **********************************************
- // save the total current word for eof processing
- if (IsAWordChar(sc.ch) || sc.ch == '}')
- {
- strcpy(s_save,s);
- int tp = static_cast<int>(strlen(s_save));
- if (tp < 99) {
- s_save[tp] = static_cast<char>(tolower(sc.ch));
- s_save[tp+1] = '\0';
- }
- }
- // **********************************************
- //
- switch (sc.state)
- {
- case SCE_AU3_COMMENTBLOCK:
- {
- //Reset at line end
- if (sc.atLineEnd) {
- ci=0;
- if (strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0) {
- if (sc.atLineEnd)
- sc.SetState(SCE_AU3_DEFAULT);
- else
- sc.SetState(SCE_AU3_COMMENTBLOCK);
- }
- break;
- }
- //skip rest of line when a ; is encountered
- if (sc.chPrev == ';') {
- ci=2;
- sc.SetState(SCE_AU3_COMMENTBLOCK);
- }
- // skip rest of the line
- if (ci==2)
- break;
- // check when first character is detected on the line
- if (ci==0) {
- if (IsAWordStart(static_cast<char>(sc.ch)) || IsAOperator(static_cast<char>(sc.ch))) {
- ci=1;
- sc.SetState(SCE_AU3_COMMENTBLOCK);
- }
- break;
- }
- if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0))) {
- if ((strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0))
- sc.SetState(SCE_AU3_COMMENT); // set to comment line for the rest of the line
- else
- ci=2; // line doesn't begin with #CE so skip the rest of the line
- }
- break;
- }
- case SCE_AU3_COMMENT:
- {
- if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
- break;
- }
- case SCE_AU3_OPERATOR:
- {
- // check if its a COMobject
- if (sc.chPrev == '.' && IsAWordChar(sc.ch)) {
- sc.SetState(SCE_AU3_COMOBJ);
- }
- else {
- sc.SetState(SCE_AU3_DEFAULT);
- }
- break;
- }
- case SCE_AU3_SPECIAL:
- {
- if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
- if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
- break;
- }
- case SCE_AU3_KEYWORD:
- {
- if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && (strcmp(s, "#comments") == 0 || strcmp(s, "#include") == 0))))
- {
- if (!IsTypeCharacter(sc.ch))
- {
- if (strcmp(s, "#cs")== 0 || strcmp(s, "#comments-start")== 0 )
- {
- sc.ChangeState(SCE_AU3_COMMENTBLOCK);
- sc.SetState(SCE_AU3_COMMENTBLOCK);
- break;
- }
- else if (keywords.InList(s)) {
- sc.ChangeState(SCE_AU3_KEYWORD);
- sc.SetState(SCE_AU3_DEFAULT);
- }
- else if (keywords2.InList(s)) {
- sc.ChangeState(SCE_AU3_FUNCTION);
- sc.SetState(SCE_AU3_DEFAULT);
- }
- else if (keywords3.InList(s)) {
- sc.ChangeState(SCE_AU3_MACRO);
- sc.SetState(SCE_AU3_DEFAULT);
- }
- else if (keywords5.InList(s)) {
- sc.ChangeState(SCE_AU3_PREPROCESSOR);
- sc.SetState(SCE_AU3_DEFAULT);
- if (strcmp(s, "#include")== 0)
- {
- si = 3; // use to determine string start for #inlude <>
- }
- }
- else if (keywords6.InList(s)) {
- sc.ChangeState(SCE_AU3_SPECIAL);
- sc.SetState(SCE_AU3_SPECIAL);
- }
- else if ((keywords7.InList(s)) && (!IsAOperator(static_cast<char>(sc.ch)))) {
- sc.ChangeState(SCE_AU3_EXPAND);
- sc.SetState(SCE_AU3_DEFAULT);
- }
- else if (keywords8.InList(s)) {
- sc.ChangeState(SCE_AU3_UDF);
- sc.SetState(SCE_AU3_DEFAULT);
- }
- else if (strcmp(s, "_") == 0) {
- sc.ChangeState(SCE_AU3_OPERATOR);
- sc.SetState(SCE_AU3_DEFAULT);
- }
- else if (!IsAWordChar(sc.ch)) {
- sc.ChangeState(SCE_AU3_DEFAULT);
- sc.SetState(SCE_AU3_DEFAULT);
- }
- }
- }
- if (sc.atLineEnd) {
- sc.SetState(SCE_AU3_DEFAULT);}
- break;
- }
- case SCE_AU3_NUMBER:
- {
- // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 E-not=3
- //
- // test for Hex notation
- if (strcmp(s, "0") == 0 && (sc.ch == 'x' || sc.ch == 'X') && ni == 0)
- {
- ni = 2;
- break;
- }
- // test for E notation
- if (IsADigit(sc.chPrev) && (sc.ch == 'e' || sc.ch == 'E') && ni <= 1)
- {
- ni = 3;
- break;
- }
- // Allow Hex characters inside hex numeric strings
- if ((ni == 2) &&
- (sc.ch == 'a' || sc.ch == 'b' || sc.ch == 'c' || sc.ch == 'd' || sc.ch == 'e' || sc.ch == 'f' ||
- sc.ch == 'A' || sc.ch == 'B' || sc.ch == 'C' || sc.ch == 'D' || sc.ch == 'E' || sc.ch == 'F' ))
- {
- break;
- }
- // test for 1 dec point only
- if (sc.ch == '.')
- {
- if (ni==0)
- {
- ni=1;
- }
- else
- {
- ni=9;
- }
- break;
- }
- // end of numeric string ?
- if (!(IsADigit(sc.ch)))
- {
- if (ni==9)
- {
- sc.ChangeState(SCE_AU3_DEFAULT);
- }
- sc.SetState(SCE_AU3_DEFAULT);
- }
- break;
- }
- case SCE_AU3_VARIABLE:
- {
- // Check if its a COMObject
- if (sc.ch == '.' && !IsADigit(sc.chNext)) {
- sc.SetState(SCE_AU3_OPERATOR);
- }
- else if (!IsAWordChar(sc.ch)) {
- sc.SetState(SCE_AU3_DEFAULT);
- }
- break;
- }
- case SCE_AU3_COMOBJ:
- {
- if (!(IsAWordChar(sc.ch))) {
- sc.SetState(SCE_AU3_DEFAULT);
- }
- break;
- }
- case SCE_AU3_STRING:
- {
- // check for " to end a double qouted string or
- // check for ' to end a single qouted string
- if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>'))
- {
- sc.ForwardSetState(SCE_AU3_DEFAULT);
- si=0;
- break;
- }
- if (sc.atLineEnd)
- {
- si=0;
- // at line end and not found a continuation char then reset to default
- Sci_Position lineCurrent = styler.GetLine(sc.currentPos);
- if (!IsContinuationLine(lineCurrent,styler))
- {
- sc.SetState(SCE_AU3_DEFAULT);
- break;
- }
- }
- // find Sendkeys in a STRING
- if (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ) {
- sc.SetState(SCE_AU3_SENT);}
- break;
- }
- case SCE_AU3_SENT:
- {
- // Send key string ended
- if (sc.chPrev == '}' && sc.ch != '}')
- {
- // set color to SENDKEY when valid sendkey .. else set back to regular string
- char sk[100];
- // split {111 222} and return {111} and check if 222 is valid.
- // if return code = 1 then invalid 222 so must be string
- if (GetSendKey(s,sk))
- {
- sc.ChangeState(SCE_AU3_STRING);
- }
- // if single char between {?} then its ok as sendkey for a single character
- else if (strlen(sk) == 3)
- {
- sc.ChangeState(SCE_AU3_SENT);
- }
- // if sendkey {111} is in table then ok as sendkey
- else if (keywords4.InList(sk))
- {
- sc.ChangeState(SCE_AU3_SENT);
- }
- else
- {
- sc.ChangeState(SCE_AU3_STRING);
- }
- sc.SetState(SCE_AU3_STRING);
- }
- else
- {
- // check if the start is a valid SendKey start
- Sci_Position nPos = 0;
- int nState = 1;
- char cTemp;
- while (!(nState == 2) && ((cTemp = s[nPos]) != '\0'))
- {
- if (cTemp == '{' && nState == 1)
- {
- nState = 2;
- }
- if (nState == 1 && !(cTemp == '+' || cTemp == '!' || cTemp == '^' || cTemp == '#' ))
- {
- nState = 0;
- }
- nPos++;
- }
- //Verify characters infront of { ... if not assume regular string
- if (nState == 1 && (!(sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ))) {
- sc.ChangeState(SCE_AU3_STRING);
- sc.SetState(SCE_AU3_STRING);
- }
- // If invalid character found then assume its a regular string
- if (nState == 0) {
- sc.ChangeState(SCE_AU3_STRING);
- sc.SetState(SCE_AU3_STRING);
- }
- }
- // check if next portion is again a sendkey
- if (sc.atLineEnd)
- {
- sc.ChangeState(SCE_AU3_STRING);
- sc.SetState(SCE_AU3_DEFAULT);
- si = 0; // reset string indicator
- }
- //* check in next characters following a sentkey are again a sent key
- // Need this test incase of 2 sentkeys like {F1}{ENTER} but not detect {{}
- if (sc.state == SCE_AU3_STRING && (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' )) {
- sc.SetState(SCE_AU3_SENT);}
- // check to see if the string ended...
- // Sendkey string isn't complete but the string ended....
- if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\''))
- {
- sc.ChangeState(SCE_AU3_STRING);
- sc.ForwardSetState(SCE_AU3_DEFAULT);
- }
- break;
- }
- } //switch (sc.state)
- // Determine if a new state should be entered:
- if (sc.state == SCE_AU3_DEFAULT)
- {
- if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
- else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);}
- else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);}
- else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);}
- else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);}
- //else if (sc.ch == '_') {sc.SetState(SCE_AU3_KEYWORD);}
- else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);} // string after #include
- else if (sc.ch == '\"') {
- sc.SetState(SCE_AU3_STRING);
- si = 1; }
- else if (sc.ch == '\'') {
- sc.SetState(SCE_AU3_STRING);
- si = 2; }
- else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)))
- {
- sc.SetState(SCE_AU3_NUMBER);
- ni = 0;
- }
- else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);}
- else if (IsAOperator(static_cast<char>(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);}
- else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
- }
- } //for (; sc.More(); sc.Forward())
- //*************************************
- // Colourize the last word correctly
- //*************************************
- if (sc.state == SCE_AU3_KEYWORD)
- {
- if (strcmp(s_save, "#cs")== 0 || strcmp(s_save, "#comments-start")== 0 )
- {
- sc.ChangeState(SCE_AU3_COMMENTBLOCK);
- sc.SetState(SCE_AU3_COMMENTBLOCK);
- }
- else if (keywords.InList(s_save)) {
- sc.ChangeState(SCE_AU3_KEYWORD);
- sc.SetState(SCE_AU3_KEYWORD);
- }
- else if (keywords2.InList(s_save)) {
- sc.ChangeState(SCE_AU3_FUNCTION);
- sc.SetState(SCE_AU3_FUNCTION);
- }
- else if (keywords3.InList(s_save)) {
- sc.ChangeState(SCE_AU3_MACRO);
- sc.SetState(SCE_AU3_MACRO);
- }
- else if (keywords5.InList(s_save)) {
- sc.ChangeState(SCE_AU3_PREPROCESSOR);
- sc.SetState(SCE_AU3_PREPROCESSOR);
- }
- else if (keywords6.InList(s_save)) {
- sc.ChangeState(SCE_AU3_SPECIAL);
- sc.SetState(SCE_AU3_SPECIAL);
- }
- else if (keywords7.InList(s_save) && sc.atLineEnd) {
- sc.ChangeState(SCE_AU3_EXPAND);
- sc.SetState(SCE_AU3_EXPAND);
- }
- else if (keywords8.InList(s_save)) {
- sc.ChangeState(SCE_AU3_UDF);
- sc.SetState(SCE_AU3_UDF);
- }
- else {
- sc.ChangeState(SCE_AU3_DEFAULT);
- sc.SetState(SCE_AU3_DEFAULT);
- }
- }
- if (sc.state == SCE_AU3_SENT)
- {
- // Send key string ended
- if (sc.chPrev == '}' && sc.ch != '}')
- {
- // set color to SENDKEY when valid sendkey .. else set back to regular string
- char sk[100];
- // split {111 222} and return {111} and check if 222 is valid.
- // if return code = 1 then invalid 222 so must be string
- if (GetSendKey(s_save,sk))
- {
- sc.ChangeState(SCE_AU3_STRING);
- }
- // if single char between {?} then its ok as sendkey for a single character
- else if (strlen(sk) == 3)
- {
- sc.ChangeState(SCE_AU3_SENT);
- }
- // if sendkey {111} is in table then ok as sendkey
- else if (keywords4.InList(sk))
- {
- sc.ChangeState(SCE_AU3_SENT);
- }
- else
- {
- sc.ChangeState(SCE_AU3_STRING);
- }
- sc.SetState(SCE_AU3_STRING);
- }
- // check if next portion is again a sendkey
- if (sc.atLineEnd)
- {
- sc.ChangeState(SCE_AU3_STRING);
- sc.SetState(SCE_AU3_DEFAULT);
- }
- }
- //*************************************
- sc.Complete();
- }
- //
- static bool IsStreamCommentStyle(int style) {
- return style == SCE_AU3_COMMENT || style == SCE_AU3_COMMENTBLOCK;
- }
- //
- // 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(Sci_PositionU szLine, Accessor &styler)
- {
- Sci_Position nsPos = styler.LineStart(szLine);
- Sci_Position nePos = styler.LineStart(szLine+1) - 1;
- while (isspacechar(styler.SafeGetCharAt(nsPos)) && nsPos < nePos)
- {
- nsPos++; // skip to next char
- } // End While
- return styler.StyleAt(nsPos);
- } // GetStyleFirstWord()
- //
- static void FoldAU3Doc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler)
- {
- Sci_Position endPos = startPos + length;
- // get settings from the config files for folding comments and preprocessor lines
- bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
- bool foldInComment = styler.GetPropertyInt("fold.comment") == 2;
- bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
- bool foldpreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
- // Backtrack to previous line in case need to fix its fold status
- Sci_Position lineCurrent = styler.GetLine(startPos);
- if (startPos > 0) {
- if (lineCurrent > 0) {
- lineCurrent--;
- startPos = styler.LineStart(lineCurrent);
- }
- }
- // vars for style of previous/current/next lines
- int style = GetStyleFirstWord(lineCurrent,styler);
- int stylePrev = 0;
- // find the first previous line without continuation character at the end
- while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) ||
- (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) {
- lineCurrent--;
- startPos = styler.LineStart(lineCurrent);
- }
- if (lineCurrent > 0) {
- stylePrev = GetStyleFirstWord(lineCurrent-1,styler);
- }
- // vars for getting first word to check for keywords
- bool FirstWordStart = false;
- bool FirstWordEnd = false;
- char szKeyword[11]="";
- int szKeywordlen = 0;
- char szThen[5]="";
- int szThenlen = 0;
- bool ThenFoundLast = false;
- // var for indentlevel
- int levelCurrent = SC_FOLDLEVELBASE;
- if (lineCurrent > 0)
- levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
- int levelNext = levelCurrent;
- //
- int visibleChars = 0;
- char chNext = styler.SafeGetCharAt(startPos);
- char chPrev = ' ';
- //
- for (Sci_Position i = startPos; i < endPos; i++) {
- char ch = chNext;
- chNext = styler.SafeGetCharAt(i + 1);
- if (IsAWordChar(ch)) {
- visibleChars++;
- }
- // get the syle for the current character neede to check in comment
- int stylech = styler.StyleAt(i);
- // get first word for the line for indent check max 9 characters
- if (FirstWordStart && (!(FirstWordEnd))) {
- if (!IsAWordChar(ch)) {
- FirstWordEnd = true;
- szKeyword[szKeywordlen] = '\0';
- }
- else {
- if (szKeywordlen < 10) {
- szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch));
- }
- }
- }
- // start the capture of the first word
- if (!(FirstWordStart)) {
- if (IsAWordChar(ch) || IsAWordStart(ch) || ch == ';') {
- FirstWordStart = true;
- szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch));
- }
- }
- // only process this logic when not in comment section
- if (!(stylech == SCE_AU3_COMMENT)) {
- if (ThenFoundLast) {
- if (IsAWordChar(ch)) {
- ThenFoundLast = false;
- }
- }
- // find out if the word "then" is the last on a "if" line
- if (FirstWordEnd && strcmp(szKeyword,"if") == 0) {
- if (szThenlen == 4) {
- szThen[0] = szThen[1];
- szThen[1] = szThen[2];
- szThen[2] = szThen[3];
- szThen[3] = static_cast<char>(tolower(ch));
- if (strcmp(szThen,"then") == 0 ) {
- ThenFoundLast = true;
- }
- }
- else {
- szThen[szThenlen++] = static_cast<char>(tolower(ch));
- if (szThenlen == 5) {
- szThen[4] = '\0';
- }
- }
- }
- }
- // End of Line found so process the information
- if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
- // **************************
- // Folding logic for Keywords
- // **************************
- // if a keyword is found on the current line and the line doesn't end with _ (continuation)
- // and we are not inside a commentblock.
- if (szKeywordlen > 0 && (!(chPrev == '_')) &&
- ((!(IsStreamCommentStyle(style)) || foldInComment)) ) {
- szKeyword[szKeywordlen] = '\0';
- // only fold "if" last keyword is "then" (else its a one line if)
- if (strcmp(szKeyword,"if") == 0 && ThenFoundLast) {
- levelNext++;
- }
- // create new fold for these words
- if (strcmp(szKeyword,"do") == 0 || strcmp(szKeyword,"for") == 0 ||
- strcmp(szKeyword,"func") == 0 || strcmp(szKeyword,"while") == 0||
- strcmp(szKeyword,"with") == 0 || strcmp(szKeyword,"#region") == 0 ) {
- levelNext++;
- }
- // create double Fold for select&switch because Case will subtract one of the current level
- if (strcmp(szKeyword,"select") == 0 || strcmp(szKeyword,"switch") == 0) {
- levelNext++;
- levelNext++;
- }
- // end the fold for these words before the current line
- if (strcmp(szKeyword,"endfunc") == 0 || strcmp(szKeyword,"endif") == 0 ||
- strcmp(szKeyword,"next") == 0 || strcmp(szKeyword,"until") == 0 ||
- strcmp(szKeyword,"endwith") == 0 ||strcmp(szKeyword,"wend") == 0){
- levelNext--;
- levelCurrent--;
- }
- // end the fold for these words before the current line and Start new fold
- if (strcmp(szKeyword,"case") == 0 || strcmp(szKeyword,"else") == 0 ||
- strcmp(szKeyword,"elseif") == 0 ) {
- levelCurrent--;
- }
- // end the double fold for this word before the current line
- if (strcmp(szKeyword,"endselect") == 0 || strcmp(szKeyword,"endswitch") == 0 ) {
- levelNext--;
- levelNext--;
- levelCurrent--;
- levelCurrent--;
- }
- // end the fold for these words on the current line
- if (strcmp(szKeyword,"#endregion") == 0 ) {
- levelNext--;
- }
- }
- // Preprocessor and Comment folding
- int styleNext = GetStyleFirstWord(lineCurrent + 1,styler);
- // *************************************
- // Folding logic for preprocessor blocks
- // *************************************
- // process preprosessor line
- if (foldpreprocessor && style == SCE_AU3_PREPROCESSOR) {
- if (!(stylePrev == SCE_AU3_PREPROCESSOR) && (styleNext == SCE_AU3_PREPROCESSOR)) {
- levelNext++;
- }
- // fold till the last line for normal comment lines
- else if (stylePrev == SCE_AU3_PREPROCESSOR && !(styleNext == SCE_AU3_PREPROCESSOR)) {
- levelNext--;
- }
- }
- // *********************************
- // Folding logic for Comment blocks
- // *********************************
- if (foldComment && IsStreamCommentStyle(style)) {
- // Start of a comment block
- if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) {
- levelNext++;
- }
- // fold till the last line for normal comment lines
- else if (IsStreamCommentStyle(stylePrev)
- && !(styleNext == SCE_AU3_COMMENT)
- && stylePrev == SCE_AU3_COMMENT
- && style == SCE_AU3_COMMENT) {
- levelNext--;
- }
- // fold till the one but last line for Blockcomment lines
- else if (IsStreamCommentStyle(stylePrev)
- && !(styleNext == SCE_AU3_COMMENTBLOCK)
- && style == SCE_AU3_COMMENTBLOCK) {
- levelNext--;
- levelCurrent--;
- }
- }
- int levelUse = levelCurrent;
- int lev = levelUse | levelNext << 16;
- if (visibleChars == 0 && foldCompact)
- lev |= SC_FOLDLEVELWHITEFLAG;
- if (levelUse < levelNext) {
- lev |= SC_FOLDLEVELHEADERFLAG;
- }
- if (lev != styler.LevelAt(lineCurrent)) {
- styler.SetLevel(lineCurrent, lev);
- }
- // reset values for the next line
- lineCurrent++;
- stylePrev = style;
- style = styleNext;
- levelCurrent = levelNext;
- visibleChars = 0;
- // if the last character is an Underscore then don't reset since the line continues on the next line.
- if (!(chPrev == '_')) {
- szKeywordlen = 0;
- szThenlen = 0;
- FirstWordStart = false;
- FirstWordEnd = false;
- ThenFoundLast = false;
- }
- }
- // save the last processed character
- if (!isspacechar(ch)) {
- chPrev = ch;
- visibleChars++;
- }
- }
- }
- //
- static const char * const AU3WordLists[] = {
- "#autoit keywords",
- "#autoit functions",
- "#autoit macros",
- "#autoit Sent keys",
- "#autoit Pre-processors",
- "#autoit Special",
- "#autoit Expand",
- "#autoit UDF",
- 0
- };
- LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists);
|