static void ColouriseErlangDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { StyleContext sc(startPos, length, initStyle, styler); WordList &reservedWords = *keywordlists[0]; WordList &erlangBIFs = *keywordlists[1]; WordList &erlangPreproc = *keywordlists[2]; WordList &erlangModulesAtt = *keywordlists[3]; WordList &erlangDoc = *keywordlists[4]; WordList &erlangDocMacro = *keywordlists[5]; int radix_digits = 0; int exponent_digits = 0; atom_parse_state_t parse_state = STATE_NULL; atom_parse_state_t old_parse_state = STATE_NULL; bool to_late_to_comment = false; char cur[100]; int old_style = SCE_ERLANG_DEFAULT; styler.StartAt(startPos); for (; sc.More(); sc.Forward()) { int style = SCE_ERLANG_DEFAULT; if (STATE_NULL != parse_state) { switch (parse_state) { case STATE_NULL : sc.SetState(SCE_ERLANG_DEFAULT); break; /* COMMENTS ------------------------------------------------------*/ case COMMENT : { if (sc.ch != '%') { to_late_to_comment = true; } else if (!to_late_to_comment && sc.ch == '%') { // Switch to comment level 2 (Function) sc.ChangeState(SCE_ERLANG_COMMENT_FUNCTION); old_style = SCE_ERLANG_COMMENT_FUNCTION; parse_state = COMMENT_FUNCTION; sc.Forward(); } } // V--- Falling through! case COMMENT_FUNCTION : { if (sc.ch != '%') { to_late_to_comment = true; } else if (!to_late_to_comment && sc.ch == '%') { // Switch to comment level 3 (Module) sc.ChangeState(SCE_ERLANG_COMMENT_MODULE); old_style = SCE_ERLANG_COMMENT_MODULE; parse_state = COMMENT_MODULE; sc.Forward(); } } // V--- Falling through! case COMMENT_MODULE : { if (parse_state != COMMENT) { // Search for comment documentation if (sc.chNext == '@') { old_parse_state = parse_state; parse_state = ('{' == sc.ch) ? COMMENT_DOC_MACRO : COMMENT_DOC; sc.ForwardSetState(sc.state); } } // All comments types fall here. if (sc.atLineEnd) { to_late_to_comment = false; sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; case COMMENT_DOC : // V--- Falling through! case COMMENT_DOC_MACRO : { if (!isalnum(sc.ch)) { // Try to match documentation comment sc.GetCurrent(cur, sizeof(cur)); if (parse_state == COMMENT_DOC_MACRO && erlangDocMacro.InList(cur)) { sc.ChangeState(SCE_ERLANG_COMMENT_DOC_MACRO); while (sc.ch != '}' && !sc.atLineEnd) sc.Forward(); } else if (erlangDoc.InList(cur)) { sc.ChangeState(SCE_ERLANG_COMMENT_DOC); } else { sc.ChangeState(old_style); } // Switch back to old state sc.SetState(old_style); parse_state = old_parse_state; } if (sc.atLineEnd) { to_late_to_comment = false; sc.ChangeState(old_style); sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; /* -------------------------------------------------------------- */ /* Atoms ---------------------------------------------------------*/ case ATOM_UNQUOTED : { if ('@' == sc.ch){ parse_state = NODE_NAME_UNQUOTED; } else if (sc.ch == ':') { // Searching for module name if (sc.chNext == ' ') { // error sc.ChangeState(SCE_ERLANG_UNKNOWN); parse_state = STATE_NULL; } else { sc.Forward(); if (isalnum(sc.ch)) { sc.GetCurrent(cur, sizeof(cur)); sc.ChangeState(SCE_ERLANG_MODULES); sc.SetState(SCE_ERLANG_MODULES); } } } else if (!IsAWordChar(sc.ch)) { sc.GetCurrent(cur, sizeof(cur)); if (reservedWords.InList(cur)) { style = SCE_ERLANG_KEYWORD; } else if (erlangBIFs.InList(cur) && strcmp(cur,"erlang:")){ style = SCE_ERLANG_BIFS; } else if (sc.ch == '(' || '/' == sc.ch){ style = SCE_ERLANG_FUNCTION_NAME; } else { style = SCE_ERLANG_ATOM; } sc.ChangeState(style); sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; case ATOM_QUOTED : { if ( '@' == sc.ch ){ parse_state = NODE_NAME_QUOTED; } else if ('\'' == sc.ch && '\\' != sc.chPrev) { sc.ChangeState(SCE_ERLANG_ATOM); sc.ForwardSetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; /* -------------------------------------------------------------- */ /* Node names ----------------------------------------------------*/ case NODE_NAME_UNQUOTED : { if ('@' == sc.ch) { sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } else if (!IsAWordChar(sc.ch)) { sc.ChangeState(SCE_ERLANG_NODE_NAME); sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; case NODE_NAME_QUOTED : { if ('@' == sc.ch) { sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } else if ('\'' == sc.ch && '\\' != sc.chPrev) { sc.ChangeState(SCE_ERLANG_NODE_NAME_QUOTED); sc.ForwardSetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; /* -------------------------------------------------------------- */ /* Records -------------------------------------------------------*/ case RECORD_START : { if ('\'' == sc.ch) { parse_state = RECORD_QUOTED; } else if (isalpha(sc.ch) && islower(sc.ch)) { parse_state = RECORD_UNQUOTED; } else { // error sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; case RECORD_UNQUOTED : { if (!IsAWordChar(sc.ch)) { sc.ChangeState(SCE_ERLANG_RECORD); sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; case RECORD_QUOTED : { if ('\'' == sc.ch && '\\' != sc.chPrev) { sc.ChangeState(SCE_ERLANG_RECORD_QUOTED); sc.ForwardSetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; /* -------------------------------------------------------------- */ /* Macros --------------------------------------------------------*/ case MACRO_START : { if ('\'' == sc.ch) { parse_state = MACRO_QUOTED; } else if (isalpha(sc.ch)) { parse_state = MACRO_UNQUOTED; } else { // error sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; case MACRO_UNQUOTED : { if (!IsAWordChar(sc.ch)) { sc.ChangeState(SCE_ERLANG_MACRO); sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; case MACRO_QUOTED : { if ('\'' == sc.ch && '\\' != sc.chPrev) { sc.ChangeState(SCE_ERLANG_MACRO_QUOTED); sc.ForwardSetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; /* -------------------------------------------------------------- */ /* Numerics ------------------------------------------------------*/ /* Simple integer */ case NUMERAL_START : { if (isdigit(sc.ch)) { radix_digits *= 10; radix_digits += sc.ch - '0'; // Assuming ASCII here! } else if ('#' == sc.ch) { if (2 > radix_digits || 36 < radix_digits) { sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } else { parse_state = NUMERAL_BASE_VALUE; } } else if ('.' == sc.ch && isdigit(sc.chNext)) { radix_digits = 0; parse_state = NUMERAL_FLOAT; } else if ('e' == sc.ch || 'E' == sc.ch) { exponent_digits = 0; parse_state = NUMERAL_EXPONENT; } else { radix_digits = 0; sc.ChangeState(SCE_ERLANG_NUMBER); sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; /* Integer in other base than 10 (x#yyy) */ case NUMERAL_BASE_VALUE : { if (!is_radix(radix_digits,sc.ch)) { radix_digits = 0; if (!isalnum(sc.ch)) sc.ChangeState(SCE_ERLANG_NUMBER); sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; /* Float (x.yyy) */ case NUMERAL_FLOAT : { if ('e' == sc.ch || 'E' == sc.ch) { exponent_digits = 0; parse_state = NUMERAL_EXPONENT; } else if (!isdigit(sc.ch)) { sc.ChangeState(SCE_ERLANG_NUMBER); sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; /* Exponent, either integer or float (xEyy, x.yyEzzz) */ case NUMERAL_EXPONENT : { if (('-' == sc.ch || '+' == sc.ch) && (isdigit(sc.chNext))) { sc.Forward(); } else if (!isdigit(sc.ch)) { if (0 < exponent_digits) sc.ChangeState(SCE_ERLANG_NUMBER); sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } else { ++exponent_digits; } } break; /* -------------------------------------------------------------- */ /* Preprocessor --------------------------------------------------*/ case PREPROCESSOR : { if (!IsAWordChar(sc.ch)) { sc.GetCurrent(cur, sizeof(cur)); if (erlangPreproc.InList(cur)) { style = SCE_ERLANG_PREPROC; } else if (erlangModulesAtt.InList(cur)) { style = SCE_ERLANG_MODULES_ATT; } sc.ChangeState(style); sc.SetState(SCE_ERLANG_DEFAULT); parse_state = STATE_NULL; } } break; } } /* End of : STATE_NULL != parse_state */ else { switch (sc.state) { case SCE_ERLANG_VARIABLE : { if (!IsAWordChar(sc.ch)) sc.SetState(SCE_ERLANG_DEFAULT); } break; case SCE_ERLANG_STRING : { if (sc.ch == '\"' && sc.chPrev != '\\') sc.ForwardSetState(SCE_ERLANG_DEFAULT); } break; case SCE_ERLANG_COMMENT : { if (sc.atLineEnd) sc.SetState(SCE_ERLANG_DEFAULT); } break; case SCE_ERLANG_CHARACTER : { if (sc.chPrev == '\\') { sc.ForwardSetState(SCE_ERLANG_DEFAULT); } else if (sc.ch != '\\') { sc.ForwardSetState(SCE_ERLANG_DEFAULT); } } break; case SCE_ERLANG_OPERATOR : { if (sc.chPrev == '.') { if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' || sc.ch == '^') { sc.ForwardSetState(SCE_ERLANG_DEFAULT); } else if (sc.ch == '\'') { sc.ForwardSetState(SCE_ERLANG_DEFAULT); } else { sc.SetState(SCE_ERLANG_DEFAULT); } } else { sc.SetState(SCE_ERLANG_DEFAULT); } } break; } } if (sc.state == SCE_ERLANG_DEFAULT) { bool no_new_state = false; switch (sc.ch) { case '\"' : sc.SetState(SCE_ERLANG_STRING); break; case '$' : sc.SetState(SCE_ERLANG_CHARACTER); break; case '%' : { parse_state = COMMENT; sc.SetState(SCE_ERLANG_COMMENT); } break; case '#' : { parse_state = RECORD_START; sc.SetState(SCE_ERLANG_UNKNOWN); } break; case '?' : { parse_state = MACRO_START; sc.SetState(SCE_ERLANG_UNKNOWN); } break; case '\'' : { parse_state = ATOM_QUOTED; sc.SetState(SCE_ERLANG_UNKNOWN); } break; case '+' : case '-' : { if (IsADigit(sc.chNext)) { parse_state = NUMERAL_START; radix_digits = 0; sc.SetState(SCE_ERLANG_UNKNOWN); } else if (sc.ch != '+') { parse_state = PREPROCESSOR; sc.SetState(SCE_ERLANG_UNKNOWN); } } break; default : no_new_state = true; } if (no_new_state) { if (isdigit(sc.ch)) { parse_state = NUMERAL_START; radix_digits = sc.ch - '0'; sc.SetState(SCE_ERLANG_UNKNOWN); } else if (isupper(sc.ch) || '_' == sc.ch) { sc.SetState(SCE_ERLANG_VARIABLE); } else if (isalpha(sc.ch)) { parse_state = ATOM_UNQUOTED; sc.SetState(SCE_ERLANG_UNKNOWN); } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '\\') { sc.SetState(SCE_ERLANG_OPERATOR); } } } } sc.Complete(); }
inline bool HandleCommentLine( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail ) { char ch; if( could_fail ) { cur++; if( cur >= one_too_much ) { styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); return false; // STOP } ch = styler.SafeGetCharAt( cur ); if( ch != '-' ) { styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); styler.StartSegment( cur ); return true; } cur++; if( cur >= one_too_much ) { styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); return false; // STOP } ch = styler.SafeGetCharAt( cur ); if( ( ch != ' ' ) && ( ch != '\t' ) ) { styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); styler.StartSegment( cur ); return true; } } // Wait for end of line bool fifteen_found = false; for( ; ; ) { cur++; if( cur >= one_too_much ) { styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE ); return false; // STOP } ch = styler.SafeGetCharAt( cur ); if( fifteen_found ) { /* if( ch == '\012' ) { // One newline on Windows (015, 012) } else { // One newline on MAC (015) and another char } */ cur--; styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE ); styler.StartSegment( cur ); return true; } else { if( ch == '\015' ) { fifteen_found = true; } else if( ch == '\012' ) { // One newline on Linux (012) styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_LINE ); styler.StartSegment( cur ); return true; } } } }
static void ColouriseOpalDoc( unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor & styler ) { styler.StartAt( startPos ); styler.StartSegment( startPos ); unsigned int & cur = startPos; const unsigned int one_too_much = startPos + length; int state = initStyle; for( ; ; ) { switch( state ) { case SCE_OPAL_KEYWORD: case SCE_OPAL_SORT: if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return; state = SCE_OPAL_DEFAULT; break; case SCE_OPAL_INTEGER: if( !HandleInteger( cur, one_too_much, styler ) ) return; state = SCE_OPAL_DEFAULT; break; case SCE_OPAL_COMMENT_BLOCK: if( !HandleCommentBlock( cur, one_too_much, styler, false ) ) return; state = SCE_OPAL_DEFAULT; break; case SCE_OPAL_COMMENT_LINE: if( !HandleCommentLine( cur, one_too_much, styler, false ) ) return; state = SCE_OPAL_DEFAULT; break; case SCE_OPAL_STRING: if( !HandleString( cur, one_too_much, styler ) ) return; state = SCE_OPAL_DEFAULT; break; default: // SCE_OPAL_DEFAULT: { char ch = styler.SafeGetCharAt( cur ); switch( ch ) { // String case '"': if( !HandleString( cur, one_too_much, styler ) ) return; break; // Comment block case '/': if( !HandleCommentBlock( cur, one_too_much, styler, true ) ) return; break; // Comment line case '-': if( !HandleCommentLine( cur, one_too_much, styler, true ) ) return; break; // Par case '(': case ')': case '[': case ']': case '{': case '}': if( !HandlePar( cur, styler ) ) return; break; // Whitespace case ' ': case '\t': case '\015': case '\012': if( !HandleSpace( cur, one_too_much, styler ) ) return; break; default: { // Integer if( isdigit( ch ) ) { if( !HandleInteger( cur, one_too_much, styler ) ) return; } // Keyword else if( islower( ch ) || isupper( ch ) ) { if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return; } // Skip else { if( !HandleSkip( cur, one_too_much, styler ) ) return; } } } break; } } } }
static void ColouriseMSSQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { styler.StartAt(startPos); bool fold = styler.GetPropertyInt("fold") != 0; int lineCurrent = styler.GetLine(startPos); int spaceFlags = 0; int state = initStyle; int prevState = initStyle; char chPrev = ' '; char chNext = styler[startPos]; styler.StartSegment(startPos); unsigned int lengthDoc = startPos + length; for (unsigned int i = startPos; i < lengthDoc; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags); int lev = indentCurrent; if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { // Only non whitespace lines can be headers int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags); if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) { lev |= SC_FOLDLEVELHEADERFLAG; } } if (fold) { styler.SetLevel(lineCurrent, lev); } } if (styler.IsLeadByte(ch)) { chNext = styler.SafeGetCharAt(i + 2); chPrev = ' '; i += 1; continue; } // When the last char isn't part of the state (have to deal with it too)... if ( (state == SCE_MSSQL_IDENTIFIER) || (state == SCE_MSSQL_STORED_PROCEDURE) || (state == SCE_MSSQL_DATATYPE) || //~ (state == SCE_MSSQL_COLUMN_NAME) || (state == SCE_MSSQL_FUNCTION) || //~ (state == SCE_MSSQL_GLOBAL_VARIABLE) || (state == SCE_MSSQL_VARIABLE)) { if (!iswordchar(ch)) { int stateTmp; if ((state == SCE_MSSQL_VARIABLE) || (state == SCE_MSSQL_COLUMN_NAME)) { styler.ColourTo(i - 1, state); stateTmp = state; } else stateTmp = classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState); prevState = state; if (stateTmp == SCE_MSSQL_IDENTIFIER || stateTmp == SCE_MSSQL_VARIABLE) state = SCE_MSSQL_DEFAULT_PREF_DATATYPE; else state = SCE_MSSQL_DEFAULT; } } else if (state == SCE_MSSQL_LINE_COMMENT) { if (ch == '\r' || ch == '\n') { styler.ColourTo(i - 1, state); prevState = state; state = SCE_MSSQL_DEFAULT; } } else if (state == SCE_MSSQL_GLOBAL_VARIABLE) { if ((ch != '@') && !iswordchar(ch)) { classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler, state, prevState); prevState = state; state = SCE_MSSQL_DEFAULT; } } // If is the default or one of the above succeeded if (state == SCE_MSSQL_DEFAULT || state == SCE_MSSQL_DEFAULT_PREF_DATATYPE) { if (iswordstart(ch)) { styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); prevState = state; state = SCE_MSSQL_IDENTIFIER; } else if (ch == '/' && chNext == '*') { styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); prevState = state; state = SCE_MSSQL_COMMENT; } else if (ch == '-' && chNext == '-') { styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); prevState = state; state = SCE_MSSQL_LINE_COMMENT; } else if (ch == '\'') { styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); prevState = state; state = SCE_MSSQL_STRING; } else if (ch == '"') { styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); prevState = state; state = SCE_MSSQL_COLUMN_NAME; } else if (ch == '[') { styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); prevState = state; state = SCE_MSSQL_COLUMN_NAME_2; } else if (isoperator(ch)) { styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); styler.ColourTo(i, SCE_MSSQL_OPERATOR); //~ style = SCE_MSSQL_DEFAULT; prevState = state; state = SCE_MSSQL_DEFAULT; } else if (ch == '@') { styler.ColourTo(i - 1, SCE_MSSQL_DEFAULT); prevState = state; if (chNext == '@') { state = SCE_MSSQL_GLOBAL_VARIABLE; // i += 2; } else state = SCE_MSSQL_VARIABLE; } // When the last char is part of the state... } else if (state == SCE_MSSQL_COMMENT) { if (ch == '/' && chPrev == '*') { if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_MSSQL_COMMENT) && (styler.GetStartSegment() == startPos)))) { styler.ColourTo(i, state); //~ state = SCE_MSSQL_COMMENT; prevState = state; state = SCE_MSSQL_DEFAULT; } } } else if (state == SCE_MSSQL_STRING) { if (ch == '\'') { if ( chNext == '\'' ) { i++; ch = chNext; chNext = styler.SafeGetCharAt(i + 1); } else { styler.ColourTo(i, state); prevState = state; state = SCE_MSSQL_DEFAULT; //i++; } //ch = chNext; //chNext = styler.SafeGetCharAt(i + 1); } } else if (state == SCE_MSSQL_COLUMN_NAME) { if (ch == '"') { if (chNext == '"') { i++; ch = chNext; chNext = styler.SafeGetCharAt(i + 1); } else { styler.ColourTo(i, state); prevState = state; state = SCE_MSSQL_DEFAULT_PREF_DATATYPE; //i++; } } } else if (state == SCE_MSSQL_COLUMN_NAME_2) { if (ch == ']') { styler.ColourTo(i, state); prevState = state; state = SCE_MSSQL_DEFAULT_PREF_DATATYPE; //i++; } } chPrev = ch; } styler.ColourTo(lengthDoc - 1, state); }
static char classifyWordSQL(unsigned int start, unsigned int end, WordList *keywordlists[], Accessor &styler, unsigned int actualState, unsigned int prevState) { char s[256]; bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.'); WordList &kwStatements = *keywordlists[KW_MSSQL_STATEMENTS]; WordList &kwDataTypes = *keywordlists[KW_MSSQL_DATA_TYPES]; WordList &kwSystemTables = *keywordlists[KW_MSSQL_SYSTEM_TABLES]; WordList &kwGlobalVariables = *keywordlists[KW_MSSQL_GLOBAL_VARIABLES]; WordList &kwFunctions = *keywordlists[KW_MSSQL_FUNCTIONS]; WordList &kwStoredProcedures = *keywordlists[KW_MSSQL_STORED_PROCEDURES]; WordList &kwOperators = *keywordlists[KW_MSSQL_OPERATORS]; for (unsigned int i = 0; i < end - start + 1 && i < 128; i++) { s[i] = static_cast<char>(tolower(styler[start + i])); s[i + 1] = '\0'; } char chAttr = SCE_MSSQL_IDENTIFIER; if (actualState == SCE_MSSQL_GLOBAL_VARIABLE) { if (kwGlobalVariables.InList(&s[2])) chAttr = SCE_MSSQL_GLOBAL_VARIABLE; } else if (wordIsNumber) { chAttr = SCE_MSSQL_NUMBER; } else if (prevState == SCE_MSSQL_DEFAULT_PREF_DATATYPE) { // Look first in datatypes if (kwDataTypes.InList(s)) chAttr = SCE_MSSQL_DATATYPE; else if (kwOperators.InList(s)) chAttr = SCE_MSSQL_OPERATOR; else if (kwStatements.InList(s)) chAttr = SCE_MSSQL_STATEMENT; else if (kwSystemTables.InList(s)) chAttr = SCE_MSSQL_SYSTABLE; else if (kwFunctions.InList(s)) chAttr = SCE_MSSQL_FUNCTION; else if (kwStoredProcedures.InList(s)) chAttr = SCE_MSSQL_STORED_PROCEDURE; } else { if (kwOperators.InList(s)) chAttr = SCE_MSSQL_OPERATOR; else if (kwStatements.InList(s)) chAttr = SCE_MSSQL_STATEMENT; else if (kwSystemTables.InList(s)) chAttr = SCE_MSSQL_SYSTABLE; else if (kwFunctions.InList(s)) chAttr = SCE_MSSQL_FUNCTION; else if (kwStoredProcedures.InList(s)) chAttr = SCE_MSSQL_STORED_PROCEDURE; else if (kwDataTypes.InList(s)) chAttr = SCE_MSSQL_DATATYPE; } styler.ColourTo(end, chAttr); return chAttr; }
static void ColouriseTACLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { styler.StartAt(startPos); int state = initStyle; if (state == SCE_C_CHARACTER) // Does not leak onto next line state = SCE_C_DEFAULT; char chPrev = ' '; char chNext = styler[startPos]; unsigned int lengthDoc = startPos + length; bool bInClassDefinition; int currentLine = styler.GetLine(startPos); if (currentLine > 0) { styler.SetLineState(currentLine, styler.GetLineState(currentLine-1)); bInClassDefinition = (styler.GetLineState(currentLine) == 1); } else { styler.SetLineState(currentLine, 0); bInClassDefinition = false; } bool bInAsm = (state == SCE_C_REGEX); if (bInAsm) state = SCE_C_DEFAULT; styler.StartSegment(startPos); int visibleChars = 0; unsigned int i; for (i = startPos; i < lengthDoc; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { // Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win) or on LF alone (Unix) // Avoid triggering two times on Dos/Win // End of line if (state == SCE_C_CHARACTER) { ColourTo(styler, i, state, bInAsm); state = SCE_C_DEFAULT; } visibleChars = 0; currentLine++; styler.SetLineState(currentLine, (bInClassDefinition ? 1 : 0)); } if (styler.IsLeadByte(ch)) { chNext = styler.SafeGetCharAt(i + 2); chPrev = ' '; i += 1; continue; } if (state == SCE_C_DEFAULT) { if (isTACLwordstart(ch)) { ColourTo(styler, i-1, state, bInAsm); state = SCE_C_IDENTIFIER; } else if (ch == '{') { ColourTo(styler, i-1, state, bInAsm); state = SCE_C_COMMENT; } else if (ch == '{' && chNext == '*') { ColourTo(styler, i-1, state, bInAsm); state = SCE_C_COMMENTDOC; } else if (ch == '=' && chNext == '=') { ColourTo(styler, i-1, state, bInAsm); state = SCE_C_COMMENTLINE; } else if (ch == '"') { ColourTo(styler, i-1, state, bInAsm); state = SCE_C_STRING; } else if (ch == '?' && visibleChars == 0) { ColourTo(styler, i-1, state, bInAsm); state = SCE_C_PREPROCESSOR; } else if (isTACLoperator(ch)) { ColourTo(styler, i-1, state, bInAsm); ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); } } else if (state == SCE_C_IDENTIFIER) { if (!isTACLwordchar(ch)) { int lStateChange = classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm); if(lStateChange == 1) { styler.SetLineState(currentLine, 1); bInClassDefinition = true; } else if(lStateChange == 2) { bInAsm = true; } else if(lStateChange == -1) { styler.SetLineState(currentLine, 0); bInClassDefinition = false; bInAsm = false; } if (lStateChange == 3) { state = SCE_C_COMMENTLINE; } else { state = SCE_C_DEFAULT; chNext = styler.SafeGetCharAt(i + 1); if (ch == '{') { state = SCE_C_COMMENT; } else if (ch == '{' && chNext == '*') { ColourTo(styler, i-1, state, bInAsm); state = SCE_C_COMMENTDOC; } else if (ch == '=' && chNext == '=') { state = SCE_C_COMMENTLINE; } else if (ch == '"') { state = SCE_C_STRING; } else if (isTACLoperator(ch)) { ColourTo(styler, i, SCE_C_OPERATOR, bInAsm); } } } } else { if (state == SCE_C_PREPROCESSOR) { if ((ch == '\r' || ch == '\n') && !(chPrev == '\\' || chPrev == '\r')) { ColourTo(styler, i-1, state, bInAsm); state = SCE_C_DEFAULT; } } else if (state == SCE_C_COMMENT) { if (ch == '}' || (ch == '\r' || ch == '\n') ) { ColourTo(styler, i, state, bInAsm); state = SCE_C_DEFAULT; } } else if (state == SCE_C_COMMENTDOC) { if (ch == '}' || (ch == '\r' || ch == '\n')) { if (((i > styler.GetStartSegment() + 2) || ( (initStyle == SCE_C_COMMENTDOC) && (styler.GetStartSegment() == static_cast<unsigned int>(startPos))))) { ColourTo(styler, i, state, bInAsm); state = SCE_C_DEFAULT; } } } else if (state == SCE_C_COMMENTLINE) { if (ch == '\r' || ch == '\n') { ColourTo(styler, i-1, state, bInAsm); state = SCE_C_DEFAULT; } } else if (state == SCE_C_STRING) { if (ch == '"' || ch == '\r' || ch == '\n') { ColourTo(styler, i, state, bInAsm); state = SCE_C_DEFAULT; } } } if (!isspacechar(ch)) visibleChars++; chPrev = ch; } // Process to end of document if (state == SCE_C_IDENTIFIER) { classifyWordTACL(styler.GetStartSegment(), i - 1, keywordlists, styler, bInAsm); } else ColourTo(styler, lengthDoc - 1, state, bInAsm); }
static void ColourTo(Accessor &styler, unsigned int end, unsigned int attr, bool bInAsm) { if ((bInAsm) && (attr == SCE_C_OPERATOR || attr == SCE_C_NUMBER || attr == SCE_C_DEFAULT || attr == SCE_C_WORD || attr == SCE_C_IDENTIFIER)) { styler.ColourTo(end, SCE_C_REGEX); } else styler.ColourTo(end, attr); }
static void ColouriseEclDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { WordList &keywords0 = *keywordlists[0]; WordList &keywords1 = *keywordlists[1]; WordList &keywords2 = *keywordlists[2]; WordList &keywords3 = *keywordlists[3]; //Value Types WordList &keywords4 = *keywordlists[4]; WordList &keywords5 = *keywordlists[5]; WordList &keywords6 = *keywordlists[6]; //Javadoc Tags WordList cplusplus; cplusplus.Set("beginc endc"); bool stylingWithinPreprocessor = false; CharacterSet setOKBeforeRE(CharacterSet::setNone, "(=,"); CharacterSet setDoxygen(CharacterSet::setLower, "$@\\&<>#{}[]"); CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); CharacterSet setQualified(CharacterSet::setNone, "uUxX"); int chPrevNonWhite = ' '; int visibleChars = 0; bool lastWordWasUUID = false; int styleBeforeDCKeyword = SCE_ECL_DEFAULT; bool continuationLine = false; if (initStyle == SCE_ECL_PREPROCESSOR) { // Set continuationLine if last character of previous line is '\' int lineCurrent = styler.GetLine(startPos); if (lineCurrent > 0) { int chBack = styler.SafeGetCharAt(startPos-1, 0); int chBack2 = styler.SafeGetCharAt(startPos-2, 0); int lineEndChar = '!'; if (chBack2 == '\r' && chBack == '\n') { lineEndChar = styler.SafeGetCharAt(startPos-3, 0); } else if (chBack == '\n' || chBack == '\r') { lineEndChar = chBack2; } continuationLine = lineEndChar == '\\'; } } // look back to set chPrevNonWhite properly for better regex colouring if (startPos > 0) { int back = startPos; while (--back && IsSpaceEquiv(styler.StyleAt(back))) ; if (styler.StyleAt(back) == SCE_ECL_OPERATOR) { chPrevNonWhite = styler.SafeGetCharAt(back); } } StyleContext sc(startPos, length, initStyle, styler); for (; sc.More(); sc.Forward()) { if (sc.atLineStart) { if (sc.state == SCE_ECL_STRING) { // Prevent SCE_ECL_STRINGEOL from leaking back to previous line which // ends with a line continuation by locking in the state upto this position. sc.SetState(SCE_ECL_STRING); } // Reset states to begining of colourise so no surprises // if different sets of lines lexed. visibleChars = 0; lastWordWasUUID = false; } // Handle line continuation generically. if (sc.ch == '\\') { if (sc.chNext == '\n' || sc.chNext == '\r') { sc.Forward(); if (sc.ch == '\r' && sc.chNext == '\n') { sc.Forward(); } continuationLine = true; continue; } } // Determine if the current state should terminate. switch (sc.state) { case SCE_ECL_ADDED: case SCE_ECL_DELETED: case SCE_ECL_CHANGED: case SCE_ECL_MOVED: if (sc.atLineStart) sc.SetState(SCE_ECL_DEFAULT); break; case SCE_ECL_OPERATOR: sc.SetState(SCE_ECL_DEFAULT); break; case SCE_ECL_NUMBER: // We accept almost anything because of hex. and number suffixes if (!setWord.Contains(sc.ch)) { sc.SetState(SCE_ECL_DEFAULT); } break; case SCE_ECL_IDENTIFIER: if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { char s[1000]; sc.GetCurrentLowered(s, sizeof(s)); if (keywords0.InList(s)) { lastWordWasUUID = strcmp(s, "uuid") == 0; sc.ChangeState(SCE_ECL_WORD0); } else if (keywords1.InList(s)) { sc.ChangeState(SCE_ECL_WORD1); } else if (keywords2.InList(s)) { sc.ChangeState(SCE_ECL_WORD2); } else if (keywords4.InList(s)) { sc.ChangeState(SCE_ECL_WORD4); } else if (keywords5.InList(s)) { sc.ChangeState(SCE_ECL_WORD5); } else //Data types are of from KEYWORD## { int i = static_cast<int>(strlen(s)) - 1; while(i >= 0 && (isdigit(s[i]) || s[i] == '_')) --i; char s2[1000]; strncpy(s2, s, i + 1); s2[i + 1] = 0; if (keywords3.InList(s2)) { sc.ChangeState(SCE_ECL_WORD3); } } sc.SetState(SCE_ECL_DEFAULT); } break; case SCE_ECL_PREPROCESSOR: if (sc.atLineStart && !continuationLine) { sc.SetState(SCE_ECL_DEFAULT); } else if (stylingWithinPreprocessor) { if (IsASpace(sc.ch)) { sc.SetState(SCE_ECL_DEFAULT); } } else { if (sc.Match('/', '*') || sc.Match('/', '/')) { sc.SetState(SCE_ECL_DEFAULT); } } break; case SCE_ECL_COMMENT: if (sc.Match('*', '/')) { sc.Forward(); sc.ForwardSetState(SCE_ECL_DEFAULT); } break; case SCE_ECL_COMMENTDOC: if (sc.Match('*', '/')) { sc.Forward(); sc.ForwardSetState(SCE_ECL_DEFAULT); } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support // Verify that we have the conditions to mark a comment-doc-keyword if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { styleBeforeDCKeyword = SCE_ECL_COMMENTDOC; sc.SetState(SCE_ECL_COMMENTDOCKEYWORD); } } break; case SCE_ECL_COMMENTLINE: if (sc.atLineStart) { sc.SetState(SCE_ECL_DEFAULT); } break; case SCE_ECL_COMMENTLINEDOC: if (sc.atLineStart) { sc.SetState(SCE_ECL_DEFAULT); } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support // Verify that we have the conditions to mark a comment-doc-keyword if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { styleBeforeDCKeyword = SCE_ECL_COMMENTLINEDOC; sc.SetState(SCE_ECL_COMMENTDOCKEYWORD); } } break; case SCE_ECL_COMMENTDOCKEYWORD: if ((styleBeforeDCKeyword == SCE_ECL_COMMENTDOC) && sc.Match('*', '/')) { sc.ChangeState(SCE_ECL_COMMENTDOCKEYWORDERROR); sc.Forward(); sc.ForwardSetState(SCE_ECL_DEFAULT); } else if (!setDoxygen.Contains(sc.ch)) { char s[1000]; sc.GetCurrentLowered(s, sizeof(s)); if (!IsASpace(sc.ch) || !keywords6.InList(s+1)) { sc.ChangeState(SCE_ECL_COMMENTDOCKEYWORDERROR); } sc.SetState(styleBeforeDCKeyword); } break; case SCE_ECL_STRING: if (sc.atLineEnd) { sc.ChangeState(SCE_ECL_STRINGEOL); } else if (sc.ch == '\\') { if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { sc.Forward(); } } else if (sc.ch == '\"') { sc.ForwardSetState(SCE_ECL_DEFAULT); } break; case SCE_ECL_CHARACTER: if (sc.atLineEnd) { sc.ChangeState(SCE_ECL_STRINGEOL); } else if (sc.ch == '\\') { if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { sc.Forward(); } } else if (sc.ch == '\'') { sc.ForwardSetState(SCE_ECL_DEFAULT); } break; case SCE_ECL_REGEX: if (sc.atLineStart) { sc.SetState(SCE_ECL_DEFAULT); } else if (sc.ch == '/') { sc.Forward(); while ((sc.ch < 0x80) && islower(sc.ch)) sc.Forward(); // gobble regex flags sc.SetState(SCE_ECL_DEFAULT); } else if (sc.ch == '\\') { // Gobble up the quoted character if (sc.chNext == '\\' || sc.chNext == '/') { sc.Forward(); } } break; case SCE_ECL_STRINGEOL: if (sc.atLineStart) { sc.SetState(SCE_ECL_DEFAULT); } break; case SCE_ECL_VERBATIM: if (sc.ch == '\"') { if (sc.chNext == '\"') { sc.Forward(); } else { sc.ForwardSetState(SCE_ECL_DEFAULT); } } break; case SCE_ECL_UUID: if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { sc.SetState(SCE_ECL_DEFAULT); } break; } // Determine if a new state should be entered. int lineCurrent = styler.GetLine(sc.currentPos); int lineState = styler.GetLineState(lineCurrent); if (sc.state == SCE_ECL_DEFAULT) { if (lineState) { sc.SetState(lineState); } else if (sc.Match('@', '\"')) { sc.SetState(SCE_ECL_VERBATIM); sc.Forward(); } else if (setQualified.Contains(sc.ch) && sc.chNext == '\'') { sc.SetState(SCE_ECL_CHARACTER); sc.Forward(); } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { if (lastWordWasUUID) { sc.SetState(SCE_ECL_UUID); lastWordWasUUID = false; } else { sc.SetState(SCE_ECL_NUMBER); } } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { if (lastWordWasUUID) { sc.SetState(SCE_ECL_UUID); lastWordWasUUID = false; } else { sc.SetState(SCE_ECL_IDENTIFIER); } } else if (sc.Match('/', '*')) { if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style sc.SetState(SCE_ECL_COMMENTDOC); } else { sc.SetState(SCE_ECL_COMMENT); } sc.Forward(); // Eat the * so it isn't used for the end of the comment } else if (sc.Match('/', '/')) { if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) // Support of Qt/Doxygen doc. style sc.SetState(SCE_ECL_COMMENTLINEDOC); else sc.SetState(SCE_ECL_COMMENTLINE); } else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite)) { sc.SetState(SCE_ECL_REGEX); // JavaScript's RegEx // } else if (sc.ch == '\"') { // sc.SetState(SCE_ECL_STRING); } else if (sc.ch == '\'') { sc.SetState(SCE_ECL_CHARACTER); } else if (sc.ch == '#' && visibleChars == 0) { // Preprocessor commands are alone on their line sc.SetState(SCE_ECL_PREPROCESSOR); // Skip whitespace between # and preprocessor word do { sc.Forward(); } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); if (sc.atLineEnd) { sc.SetState(SCE_ECL_DEFAULT); } } else if (isoperator(static_cast<char>(sc.ch))) { sc.SetState(SCE_ECL_OPERATOR); } } if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) { chPrevNonWhite = sc.ch; visibleChars++; } continuationLine = false; } sc.Complete(); }
static void ColouriseKixDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { WordList &keywords = *keywordlists[0]; WordList &keywords2 = *keywordlists[1]; WordList &keywords3 = *keywordlists[2]; // WordList &keywords4 = *keywordlists[3]; styler.StartAt(startPos); StyleContext sc(startPos, length, initStyle, styler); for (; sc.More(); sc.Forward()) { if (sc.state == SCE_KIX_COMMENT) { if (sc.atLineEnd) { sc.SetState(SCE_KIX_DEFAULT); } } else if (sc.state == SCE_KIX_STRING1) { // This is a doubles quotes string if (sc.ch == '\"') { sc.ForwardSetState(SCE_KIX_DEFAULT); } } else if (sc.state == SCE_KIX_STRING2) { // This is a single quote string if (sc.ch == '\'') { sc.ForwardSetState(SCE_KIX_DEFAULT); } } else if (sc.state == SCE_KIX_NUMBER) { if (!IsADigit(sc.ch)) { sc.SetState(SCE_KIX_DEFAULT); } } else if (sc.state == SCE_KIX_VAR) { if (!IsAWordChar(sc.ch)) { sc.SetState(SCE_KIX_DEFAULT); } } else if (sc.state == SCE_KIX_MACRO) { if (!IsAWordChar(sc.ch) && !IsADigit(sc.ch)) { char s[100]; sc.GetCurrentLowered(s, sizeof(s)); if (!keywords3.InList(&s[1])) { sc.ChangeState(SCE_KIX_DEFAULT); } sc.SetState(SCE_KIX_DEFAULT); } } else if (sc.state == SCE_KIX_OPERATOR) { if (!IsOperator(sc.ch)) { sc.SetState(SCE_KIX_DEFAULT); } } else if (sc.state == SCE_KIX_IDENTIFIER) { if (!IsAWordChar(sc.ch)) { char s[100]; sc.GetCurrentLowered(s, sizeof(s)); if (keywords.InList(s)) { sc.ChangeState(SCE_KIX_KEYWORD); } else if (keywords2.InList(s)) { sc.ChangeState(SCE_KIX_FUNCTIONS); } sc.SetState(SCE_KIX_DEFAULT); } } // Determine if a new state should be entered. if (sc.state == SCE_KIX_DEFAULT) { if (sc.ch == ';') { sc.SetState(SCE_KIX_COMMENT); } else if (sc.ch == '\"') { sc.SetState(SCE_KIX_STRING1); } else if (sc.ch == '\'') { sc.SetState(SCE_KIX_STRING2); } else if (sc.ch == '$') { sc.SetState(SCE_KIX_VAR); } else if (sc.ch == '@') { sc.SetState(SCE_KIX_MACRO); } else if (IsADigit(sc.ch) || ((sc.ch == '.' || sc.ch == '&') && IsADigit(sc.chNext))) { sc.SetState(SCE_KIX_NUMBER); } else if (IsOperator(sc.ch)) { sc.SetState(SCE_KIX_OPERATOR); } else if (IsAWordChar(sc.ch)) { sc.SetState(SCE_KIX_IDENTIFIER); } } } sc.Complete(); }
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++; } } }
// Store both the current line's fold level and the next lines in the // level store to make it easy to pick up with each increment // and to make it possible to fiddle the current level for "} else {". static void FoldEclDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { bool foldComment = true; bool foldPreprocessor = true; bool foldCompact = true; bool foldAtElse = true; unsigned int endPos = startPos + length; int visibleChars = 0; int lineCurrent = styler.GetLine(startPos); int levelCurrent = SC_FOLDLEVELBASE; if (lineCurrent > 0) levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; int levelMinCurrent = levelCurrent; int levelNext = levelCurrent; char chNext = styler[startPos]; int styleNext = styler.StyleAt(startPos); int style = initStyle; for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); int stylePrev = style; style = styleNext; styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); if (foldComment && IsStreamCommentStyle(style)) { if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_ECL_COMMENTLINEDOC)) { levelNext++; } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_ECL_COMMENTLINEDOC) && !atEOL) { // Comments don't end at end of line and the next character may be unstyled. levelNext--; } } if (foldComment && (style == SCE_ECL_COMMENTLINE)) { if ((ch == '/') && (chNext == '/')) { char chNext2 = styler.SafeGetCharAt(i + 2); if (chNext2 == '{') { levelNext++; } else if (chNext2 == '}') { levelNext--; } } } if (foldPreprocessor && (style == SCE_ECL_PREPROCESSOR)) { if (ch == '#') { unsigned int j = i + 1; while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { j++; } if (MatchNoCase(styler, j, "region") || MatchNoCase(styler, j, "if")) { levelNext++; } else if (MatchNoCase(styler, j, "endregion") || MatchNoCase(styler, j, "end")) { levelNext--; } } } if (style == SCE_ECL_OPERATOR) { if (ch == '{') { // Measure the minimum before a '{' to allow // folding on "} else {" if (levelMinCurrent > levelNext) { levelMinCurrent = levelNext; } levelNext++; } else if (ch == '}') { levelNext--; } } if (style == SCE_ECL_WORD2) { if (MatchNoCase(styler, i, "record") || MatchNoCase(styler, i, "transform") || MatchNoCase(styler, i, "type") || MatchNoCase(styler, i, "function") || MatchNoCase(styler, i, "module") || MatchNoCase(styler, i, "service") || MatchNoCase(styler, i, "interface") || MatchNoCase(styler, i, "ifblock") || MatchNoCase(styler, i, "macro") || MatchNoCase(styler, i, "beginc++")) { levelNext++; } else if (MatchNoCase(styler, i, "endmacro") || MatchNoCase(styler, i, "endc++") || MatchNoCase(styler, i, "end")) { levelNext--; } } if (atEOL || (i == endPos-1)) { int levelUse = levelCurrent; if (foldAtElse) { levelUse = levelMinCurrent; } 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); } lineCurrent++; levelCurrent = levelNext; levelMinCurrent = levelCurrent; if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) { // There is an empty line at end of file so give it same level and empty styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); } visibleChars = 0; } if (!IsASpace(ch)) visibleChars++; } }
// // 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 void FoldBashDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) { bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; Sci_PositionU endPos = startPos + length; int visibleChars = 0; int skipHereCh = 0; Sci_Position lineCurrent = styler.GetLine(startPos); int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; int levelCurrent = levelPrev; char chNext = styler[startPos]; int styleNext = styler.StyleAt(startPos); for (Sci_PositionU i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); int style = styleNext; styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); // Comment folding if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) { if (!IsCommentLine(lineCurrent - 1, styler) && IsCommentLine(lineCurrent + 1, styler)) levelCurrent++; else if (IsCommentLine(lineCurrent - 1, styler) && !IsCommentLine(lineCurrent + 1, styler)) levelCurrent--; } if (style == SCE_SH_OPERATOR) { if (ch == '{') { levelCurrent++; } else if (ch == '}') { levelCurrent--; } } // Here Document folding if (style == SCE_SH_HERE_DELIM) { if (ch == '<' && chNext == '<') { if (styler.SafeGetCharAt(i + 2) == '<') { skipHereCh = 1; } else { if (skipHereCh == 0) { levelCurrent++; } else { skipHereCh = 0; } } } } else if (style == SCE_SH_HERE_Q && styler.StyleAt(i+1) == SCE_SH_DEFAULT) { levelCurrent--; } if (atEOL) { int lev = levelPrev; if (visibleChars == 0 && foldCompact) lev |= SC_FOLDLEVELWHITEFLAG; if ((levelCurrent > levelPrev) && (visibleChars > 0)) lev |= SC_FOLDLEVELHEADERFLAG; if (lev != styler.LevelAt(lineCurrent)) { styler.SetLevel(lineCurrent, lev); } lineCurrent++; levelPrev = levelCurrent; visibleChars = 0; } if (!isspacechar(ch)) visibleChars++; } // Fill in the real level of the next line, keeping the current flags as they will be filled in later int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; styler.SetLevel(lineCurrent, levelPrev | flagsNext); }
static void ColouriseBashDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], Accessor &styler) { WordList &keywords = *keywordlists[0]; WordList cmdDelimiter, bashStruct, bashStruct_in; cmdDelimiter.Set("| || |& & && ; ;; ( ) { }"); bashStruct.Set("if elif fi while until else then do done esac eval"); bashStruct_in.Set("for case select"); CharacterSet setWordStart(CharacterSet::setAlpha, "_"); // note that [+-] are often parts of identifiers in shell scripts CharacterSet setWord(CharacterSet::setAlphaNum, "._+-"); CharacterSet setMetaCharacter(CharacterSet::setNone, "|&;()<> \t\r\n"); setMetaCharacter.Add(0); CharacterSet setBashOperator(CharacterSet::setNone, "^&%()-+=|{}[]:;>,*/<?!.~@"); CharacterSet setSingleCharOp(CharacterSet::setNone, "rwxoRWXOezsfdlpSbctugkTBMACahGLNn"); CharacterSet setParam(CharacterSet::setAlphaNum, "$_"); CharacterSet setHereDoc(CharacterSet::setAlpha, "_\\-+!%*,./:?@[]^`{}~"); CharacterSet setHereDoc2(CharacterSet::setAlphaNum, "_-+!%*,./:=?@[]^`{}~"); CharacterSet setLeftShift(CharacterSet::setDigits, "$"); class HereDocCls { // Class to manage HERE document elements public: int State; // 0: '<<' encountered // 1: collect the delimiter // 2: here doc text (lines after the delimiter) int Quote; // the char after '<<' bool Quoted; // true if Quote in ('\'','"','`') bool Indent; // indented delimiter (for <<-) int DelimiterLength; // strlen(Delimiter) char Delimiter[HERE_DELIM_MAX]; // the Delimiter HereDocCls() { State = 0; Quote = 0; Quoted = false; Indent = 0; DelimiterLength = 0; Delimiter[0] = '\0'; } void Append(int ch) { Delimiter[DelimiterLength++] = static_cast<char>(ch); Delimiter[DelimiterLength] = '\0'; } ~HereDocCls() { } }; HereDocCls HereDoc; class QuoteCls { // Class to manage quote pairs (simplified vs LexPerl) public: int Count; int Up, Down; QuoteCls() { Count = 0; Up = '\0'; Down = '\0'; } void Open(int u) { Count++; Up = u; Down = opposite(Up); } void Start(int u) { Count = 0; Open(u); } }; QuoteCls Quote; class QuoteStackCls { // Class to manage quote pairs that nest public: int Count; int Up, Down; int Style; int Depth; // levels pushed int CountStack[BASH_DELIM_STACK_MAX]; int UpStack [BASH_DELIM_STACK_MAX]; int StyleStack[BASH_DELIM_STACK_MAX]; QuoteStackCls() { Count = 0; Up = '\0'; Down = '\0'; Style = 0; Depth = 0; } void Start(int u, int s) { Count = 1; Up = u; Down = opposite(Up); Style = s; } void Push(int u, int s) { if (Depth >= BASH_DELIM_STACK_MAX) return; CountStack[Depth] = Count; UpStack [Depth] = Up; StyleStack[Depth] = Style; Depth++; Count = 1; Up = u; Down = opposite(Up); Style = s; } void Pop(void) { if (Depth <= 0) return; Depth--; Count = CountStack[Depth]; Up = UpStack [Depth]; Style = StyleStack[Depth]; Down = opposite(Up); } ~QuoteStackCls() { } }; QuoteStackCls QuoteStack; int numBase = 0; int digit; Sci_PositionU endPos = startPos + length; int cmdState = BASH_CMD_START; int testExprType = 0; // Always backtracks to the start of a line that is not a continuation // of the previous line (i.e. start of a bash command segment) Sci_Position ln = styler.GetLine(startPos); if (ln > 0 && startPos == static_cast<Sci_PositionU>(styler.LineStart(ln))) ln--; for (;;) { startPos = styler.LineStart(ln); if (ln == 0 || styler.GetLineState(ln) == BASH_CMD_START) break; ln--; } initStyle = SCE_SH_DEFAULT; StyleContext sc(startPos, endPos - startPos, initStyle, styler); for (; sc.More(); sc.Forward()) { // handle line continuation, updates per-line stored state if (sc.atLineStart) { ln = styler.GetLine(sc.currentPos); if (sc.state == SCE_SH_STRING || sc.state == SCE_SH_BACKTICKS || sc.state == SCE_SH_CHARACTER || sc.state == SCE_SH_HERE_Q || sc.state == SCE_SH_COMMENTLINE || sc.state == SCE_SH_PARAM) { // force backtrack while retaining cmdState styler.SetLineState(ln, BASH_CMD_BODY); } else { if (ln > 0) { if ((sc.GetRelative(-3) == '\\' && sc.GetRelative(-2) == '\r' && sc.chPrev == '\n') || sc.GetRelative(-2) == '\\') { // handle '\' line continuation // retain last line's state } else cmdState = BASH_CMD_START; } styler.SetLineState(ln, cmdState); } } // controls change of cmdState at the end of a non-whitespace element // states BODY|TEST|ARITH persist until the end of a command segment // state WORD persist, but ends with 'in' or 'do' construct keywords int cmdStateNew = BASH_CMD_BODY; if (cmdState == BASH_CMD_TEST || cmdState == BASH_CMD_ARITH || cmdState == BASH_CMD_WORD) cmdStateNew = cmdState; int stylePrev = sc.state; // Determine if the current state should terminate. switch (sc.state) { case SCE_SH_OPERATOR: sc.SetState(SCE_SH_DEFAULT); if (cmdState == BASH_CMD_DELIM) // if command delimiter, start new command cmdStateNew = BASH_CMD_START; else if (sc.chPrev == '\\') // propagate command state if line continued cmdStateNew = cmdState; break; case SCE_SH_WORD: // "." never used in Bash variable names but used in file names if (!setWord.Contains(sc.ch)) { char s[500]; char s2[10]; sc.GetCurrent(s, sizeof(s)); // allow keywords ending in a whitespace or command delimiter s2[0] = static_cast<char>(sc.ch); s2[1] = '\0'; bool keywordEnds = IsASpace(sc.ch) || cmdDelimiter.InList(s2); // 'in' or 'do' may be construct keywords if (cmdState == BASH_CMD_WORD) { if (strcmp(s, "in") == 0 && keywordEnds) cmdStateNew = BASH_CMD_BODY; else if (strcmp(s, "do") == 0 && keywordEnds) cmdStateNew = BASH_CMD_START; else sc.ChangeState(SCE_SH_IDENTIFIER); sc.SetState(SCE_SH_DEFAULT); break; } // a 'test' keyword starts a test expression if (strcmp(s, "test") == 0) { if (cmdState == BASH_CMD_START && keywordEnds) { cmdStateNew = BASH_CMD_TEST; testExprType = 0; } else sc.ChangeState(SCE_SH_IDENTIFIER); } // detect bash construct keywords else if (bashStruct.InList(s)) { if (cmdState == BASH_CMD_START && keywordEnds) cmdStateNew = BASH_CMD_START; else sc.ChangeState(SCE_SH_IDENTIFIER); } // 'for'|'case'|'select' needs 'in'|'do' to be highlighted later else if (bashStruct_in.InList(s)) { if (cmdState == BASH_CMD_START && keywordEnds) cmdStateNew = BASH_CMD_WORD; else sc.ChangeState(SCE_SH_IDENTIFIER); } // disambiguate option items and file test operators else if (s[0] == '-') { if (cmdState != BASH_CMD_TEST) sc.ChangeState(SCE_SH_IDENTIFIER); } // disambiguate keywords and identifiers else if (cmdState != BASH_CMD_START || !(keywords.InList(s) && keywordEnds)) { sc.ChangeState(SCE_SH_IDENTIFIER); } sc.SetState(SCE_SH_DEFAULT); } break; case SCE_SH_IDENTIFIER: if (sc.chPrev == '\\') { // for escaped chars sc.ForwardSetState(SCE_SH_DEFAULT); } else if (!setWord.Contains(sc.ch)) { sc.SetState(SCE_SH_DEFAULT); } else if (cmdState == BASH_CMD_ARITH && !setWordStart.Contains(sc.ch)) { sc.SetState(SCE_SH_DEFAULT); } break; case SCE_SH_NUMBER: digit = translateBashDigit(sc.ch); if (numBase == BASH_BASE_DECIMAL) { if (sc.ch == '#') { char s[10]; sc.GetCurrent(s, sizeof(s)); numBase = getBashNumberBase(s); if (numBase != BASH_BASE_ERROR) break; } else if (IsADigit(sc.ch)) break; } else if (numBase == BASH_BASE_HEX) { if (IsADigit(sc.ch, 16)) break; #ifdef PEDANTIC_OCTAL } else if (numBase == BASH_BASE_OCTAL || numBase == BASH_BASE_OCTAL_ERROR) { if (digit <= 7) break; if (digit <= 9) { numBase = BASH_BASE_OCTAL_ERROR; break; } #endif } else if (numBase == BASH_BASE_ERROR) { if (digit <= 9) break; } else { // DD#DDDD number style handling if (digit != BASH_BASE_ERROR) { if (numBase <= 36) { // case-insensitive if base<=36 if (digit >= 36) digit -= 26; } if (digit < numBase) break; if (digit <= 9) { numBase = BASH_BASE_ERROR; break; } } } // fallthrough when number is at an end or error if (numBase == BASH_BASE_ERROR #ifdef PEDANTIC_OCTAL || numBase == BASH_BASE_OCTAL_ERROR #endif ) { sc.ChangeState(SCE_SH_ERROR); } sc.SetState(SCE_SH_DEFAULT); break; case SCE_SH_COMMENTLINE: if (sc.atLineEnd && sc.chPrev != '\\') { sc.SetState(SCE_SH_DEFAULT); } break; case SCE_SH_HERE_DELIM: // From Bash info: // --------------- // Specifier format is: <<[-]WORD // Optional '-' is for removal of leading tabs from here-doc. // Whitespace acceptable after <<[-] operator // if (HereDoc.State == 0) { // '<<' encountered HereDoc.Quote = sc.chNext; HereDoc.Quoted = false; HereDoc.DelimiterLength = 0; HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; if (sc.chNext == '\'' || sc.chNext == '\"') { // a quoted here-doc delimiter (' or ") sc.Forward(); HereDoc.Quoted = true; HereDoc.State = 1; } else if (setHereDoc.Contains(sc.chNext) || (sc.chNext == '=' && cmdState != BASH_CMD_ARITH)) { // an unquoted here-doc delimiter, no special handling HereDoc.State = 1; } else if (sc.chNext == '<') { // HERE string <<< sc.Forward(); sc.ForwardSetState(SCE_SH_DEFAULT); } else if (IsASpace(sc.chNext)) { // eat whitespace } else if (setLeftShift.Contains(sc.chNext) || (sc.chNext == '=' && cmdState == BASH_CMD_ARITH)) { // left shift <<$var or <<= cases sc.ChangeState(SCE_SH_OPERATOR); sc.ForwardSetState(SCE_SH_DEFAULT); } else { // symbols terminates; deprecated zero-length delimiter HereDoc.State = 1; } } else if (HereDoc.State == 1) { // collect the delimiter // * if single quoted, there's no escape // * if double quoted, there are \\ and \" escapes if ((HereDoc.Quote == '\'' && sc.ch != HereDoc.Quote) || (HereDoc.Quoted && sc.ch != HereDoc.Quote && sc.ch != '\\') || (HereDoc.Quote != '\'' && sc.chPrev == '\\') || (setHereDoc2.Contains(sc.ch))) { HereDoc.Append(sc.ch); } else if (HereDoc.Quoted && sc.ch == HereDoc.Quote) { // closing quote => end of delimiter sc.ForwardSetState(SCE_SH_DEFAULT); } else if (sc.ch == '\\') { if (HereDoc.Quoted && sc.chNext != HereDoc.Quote && sc.chNext != '\\') { // in quoted prefixes only \ and the quote eat the escape HereDoc.Append(sc.ch); } else { // skip escape prefix } } else if (!HereDoc.Quoted) { sc.SetState(SCE_SH_DEFAULT); } if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) { // force blowup sc.SetState(SCE_SH_ERROR); HereDoc.State = 0; } } break; case SCE_SH_HERE_Q: // HereDoc.State == 2 if (sc.atLineStart) { sc.SetState(SCE_SH_HERE_Q); int prefixws = 0; while (sc.ch == '\t' && !sc.atLineEnd) { // tabulation prefix sc.Forward(); prefixws++; } if (prefixws > 0) sc.SetState(SCE_SH_HERE_Q); while (!sc.atLineEnd) { sc.Forward(); } char s[HERE_DELIM_MAX]; sc.GetCurrent(s, sizeof(s)); if (sc.LengthCurrent() == 0) { // '' or "" delimiters if ((prefixws == 0 || HereDoc.Indent) && HereDoc.Quoted && HereDoc.DelimiterLength == 0) sc.SetState(SCE_SH_DEFAULT); break; } if (s[strlen(s) - 1] == '\r') s[strlen(s) - 1] = '\0'; if (strcmp(HereDoc.Delimiter, s) == 0) { if ((prefixws == 0) || // indentation rule (prefixws > 0 && HereDoc.Indent)) { sc.SetState(SCE_SH_DEFAULT); break; } } } break; case SCE_SH_SCALAR: // variable names if (!setParam.Contains(sc.ch)) { if (sc.LengthCurrent() == 1) { // Special variable: $(, $_ etc. sc.ForwardSetState(SCE_SH_DEFAULT); } else { sc.SetState(SCE_SH_DEFAULT); } } break; case SCE_SH_STRING: // delimited styles, can nest case SCE_SH_BACKTICKS: if (sc.ch == '\\' && QuoteStack.Up != '\\') { if (QuoteStack.Style != BASH_DELIM_LITERAL) sc.Forward(); } else if (sc.ch == QuoteStack.Down) { QuoteStack.Count--; if (QuoteStack.Count == 0) { if (QuoteStack.Depth > 0) { QuoteStack.Pop(); } else sc.ForwardSetState(SCE_SH_DEFAULT); } } else if (sc.ch == QuoteStack.Up) { QuoteStack.Count++; } else { if (QuoteStack.Style == BASH_DELIM_STRING || QuoteStack.Style == BASH_DELIM_LSTRING ) { // do nesting for "string", $"locale-string" if (sc.ch == '`') { QuoteStack.Push(sc.ch, BASH_DELIM_BACKTICK); } else if (sc.ch == '$' && sc.chNext == '(') { sc.Forward(); QuoteStack.Push(sc.ch, BASH_DELIM_COMMAND); } } else if (QuoteStack.Style == BASH_DELIM_COMMAND || QuoteStack.Style == BASH_DELIM_BACKTICK ) { // do nesting for $(command), `command` if (sc.ch == '\'') { QuoteStack.Push(sc.ch, BASH_DELIM_LITERAL); } else if (sc.ch == '\"') { QuoteStack.Push(sc.ch, BASH_DELIM_STRING); } else if (sc.ch == '`') { QuoteStack.Push(sc.ch, BASH_DELIM_BACKTICK); } else if (sc.ch == '$') { if (sc.chNext == '\'') { sc.Forward(); QuoteStack.Push(sc.ch, BASH_DELIM_CSTRING); } else if (sc.chNext == '\"') { sc.Forward(); QuoteStack.Push(sc.ch, BASH_DELIM_LSTRING); } else if (sc.chNext == '(') { sc.Forward(); QuoteStack.Push(sc.ch, BASH_DELIM_COMMAND); } } } } break; case SCE_SH_PARAM: // ${parameter} if (sc.ch == '\\' && Quote.Up != '\\') { sc.Forward(); } else if (sc.ch == Quote.Down) { Quote.Count--; if (Quote.Count == 0) { sc.ForwardSetState(SCE_SH_DEFAULT); } } else if (sc.ch == Quote.Up) { Quote.Count++; } break; case SCE_SH_CHARACTER: // singly-quoted strings if (sc.ch == Quote.Down) { Quote.Count--; if (Quote.Count == 0) { sc.ForwardSetState(SCE_SH_DEFAULT); } } break; } // Must check end of HereDoc state 1 before default state is handled if (HereDoc.State == 1 && sc.atLineEnd) { // Begin of here-doc (the line after the here-doc delimiter): // Lexically, the here-doc starts from the next line after the >>, but the // first line of here-doc seem to follow the style of the last EOL sequence HereDoc.State = 2; if (HereDoc.Quoted) { if (sc.state == SCE_SH_HERE_DELIM) { // Missing quote at end of string! Syntax error in bash 4.3 // Mark this bit as an error, do not colour any here-doc sc.ChangeState(SCE_SH_ERROR); sc.SetState(SCE_SH_DEFAULT); } else { // HereDoc.Quote always == '\'' sc.SetState(SCE_SH_HERE_Q); } } else if (HereDoc.DelimiterLength == 0) { // no delimiter, illegal (but '' and "" are legal) sc.ChangeState(SCE_SH_ERROR); sc.SetState(SCE_SH_DEFAULT); } else { sc.SetState(SCE_SH_HERE_Q); } } // update cmdState about the current command segment if (stylePrev != SCE_SH_DEFAULT && sc.state == SCE_SH_DEFAULT) { cmdState = cmdStateNew; } // Determine if a new state should be entered. if (sc.state == SCE_SH_DEFAULT) { if (sc.ch == '\\') { // Bash can escape any non-newline as a literal sc.SetState(SCE_SH_IDENTIFIER); if (sc.chNext == '\r' || sc.chNext == '\n') sc.SetState(SCE_SH_OPERATOR); } else if (IsADigit(sc.ch)) { sc.SetState(SCE_SH_NUMBER); numBase = BASH_BASE_DECIMAL; if (sc.ch == '0') { // hex,octal if (sc.chNext == 'x' || sc.chNext == 'X') { numBase = BASH_BASE_HEX; sc.Forward(); } else if (IsADigit(sc.chNext)) { #ifdef PEDANTIC_OCTAL numBase = BASH_BASE_OCTAL; #else numBase = BASH_BASE_HEX; #endif } } } else if (setWordStart.Contains(sc.ch)) { sc.SetState(SCE_SH_WORD); } else if (sc.ch == '#') { if (stylePrev != SCE_SH_WORD && stylePrev != SCE_SH_IDENTIFIER && (sc.currentPos == 0 || setMetaCharacter.Contains(sc.chPrev))) { sc.SetState(SCE_SH_COMMENTLINE); } else { sc.SetState(SCE_SH_WORD); } // handle some zsh features within arithmetic expressions only if (cmdState == BASH_CMD_ARITH) { if (sc.chPrev == '[') { // [#8] [##8] output digit setting sc.SetState(SCE_SH_WORD); if (sc.chNext == '#') { sc.Forward(); } } else if (sc.Match("##^") && IsUpperCase(sc.GetRelative(3))) { // ##^A sc.SetState(SCE_SH_IDENTIFIER); sc.Forward(3); } else if (sc.chNext == '#' && !IsASpace(sc.GetRelative(2))) { // ##a sc.SetState(SCE_SH_IDENTIFIER); sc.Forward(2); } else if (setWordStart.Contains(sc.chNext)) { // #name sc.SetState(SCE_SH_IDENTIFIER); } } } else if (sc.ch == '\"') { sc.SetState(SCE_SH_STRING); QuoteStack.Start(sc.ch, BASH_DELIM_STRING); } else if (sc.ch == '\'') { sc.SetState(SCE_SH_CHARACTER); Quote.Start(sc.ch); } else if (sc.ch == '`') { sc.SetState(SCE_SH_BACKTICKS); QuoteStack.Start(sc.ch, BASH_DELIM_BACKTICK); } else if (sc.ch == '$') { if (sc.Match("$((")) { sc.SetState(SCE_SH_OPERATOR); // handle '((' later continue; } sc.SetState(SCE_SH_SCALAR); sc.Forward(); if (sc.ch == '{') { sc.ChangeState(SCE_SH_PARAM); Quote.Start(sc.ch); } else if (sc.ch == '\'') { sc.ChangeState(SCE_SH_STRING); QuoteStack.Start(sc.ch, BASH_DELIM_CSTRING); } else if (sc.ch == '"') { sc.ChangeState(SCE_SH_STRING); QuoteStack.Start(sc.ch, BASH_DELIM_LSTRING); } else if (sc.ch == '(') { sc.ChangeState(SCE_SH_BACKTICKS); QuoteStack.Start(sc.ch, BASH_DELIM_COMMAND); } else if (sc.ch == '`') { // $` seen in a configure script, valid? sc.ChangeState(SCE_SH_BACKTICKS); QuoteStack.Start(sc.ch, BASH_DELIM_BACKTICK); } else { continue; // scalar has no delimiter pair } } else if (sc.Match('<', '<')) { sc.SetState(SCE_SH_HERE_DELIM); HereDoc.State = 0; if (sc.GetRelative(2) == '-') { // <<- indent case HereDoc.Indent = true; sc.Forward(); } else { HereDoc.Indent = false; } } else if (sc.ch == '-' && // one-char file test operators setSingleCharOp.Contains(sc.chNext) && !setWord.Contains(sc.GetRelative(2)) && IsASpace(sc.chPrev)) { sc.SetState(SCE_SH_WORD); sc.Forward(); } else if (setBashOperator.Contains(sc.ch)) { char s[10]; bool isCmdDelim = false; sc.SetState(SCE_SH_OPERATOR); // globs have no whitespace, do not appear in arithmetic expressions if (cmdState != BASH_CMD_ARITH && sc.ch == '(' && sc.chNext != '(') { int i = GlobScan(sc); if (i > 1) { sc.SetState(SCE_SH_IDENTIFIER); sc.Forward(i); continue; } } // handle opening delimiters for test/arithmetic expressions - ((,[[,[ if (cmdState == BASH_CMD_START || cmdState == BASH_CMD_BODY) { if (sc.Match('(', '(')) { cmdState = BASH_CMD_ARITH; sc.Forward(); } else if (sc.Match('[', '[') && IsASpace(sc.GetRelative(2))) { cmdState = BASH_CMD_TEST; testExprType = 1; sc.Forward(); } else if (sc.ch == '[' && IsASpace(sc.chNext)) { cmdState = BASH_CMD_TEST; testExprType = 2; } } // special state -- for ((x;y;z)) in ... looping if (cmdState == BASH_CMD_WORD && sc.Match('(', '(')) { cmdState = BASH_CMD_ARITH; sc.Forward(); continue; } // handle command delimiters in command START|BODY|WORD state, also TEST if 'test' if (cmdState == BASH_CMD_START || cmdState == BASH_CMD_BODY || cmdState == BASH_CMD_WORD || (cmdState == BASH_CMD_TEST && testExprType == 0)) { s[0] = static_cast<char>(sc.ch); if (setBashOperator.Contains(sc.chNext)) { s[1] = static_cast<char>(sc.chNext); s[2] = '\0'; isCmdDelim = cmdDelimiter.InList(s); if (isCmdDelim) sc.Forward(); } if (!isCmdDelim) { s[1] = '\0'; isCmdDelim = cmdDelimiter.InList(s); } if (isCmdDelim) { cmdState = BASH_CMD_DELIM; continue; } } // handle closing delimiters for test/arithmetic expressions - )),]],] if (cmdState == BASH_CMD_ARITH && sc.Match(')', ')')) { cmdState = BASH_CMD_BODY; sc.Forward(); } else if (cmdState == BASH_CMD_TEST && IsASpace(sc.chPrev)) { if (sc.Match(']', ']') && testExprType == 1) { sc.Forward(); cmdState = BASH_CMD_BODY; } else if (sc.ch == ']' && testExprType == 2) { cmdState = BASH_CMD_BODY; } } } }// sc.state } sc.Complete(); if (sc.state == SCE_SH_HERE_Q) { styler.ChangeLexerState(sc.currentPos, styler.Length()); } sc.Complete(); }
static void FoldABAQUSDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { int startLine = styler.GetLine(startPos) ; int endLine = styler.GetLine(startPos+length-1) ; // bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; // We want to deal with all the cases // To know the correct indentlevel, we need to look back to the // previous command line indentation level // order of formatting keyline datalines commentlines int beginData = -1 ; int beginComment = -1 ; int prvKeyLine = startLine ; int prvKeyLineTp = 0 ; // Scan until we find the previous keyword line // this will give us the level reference that we need while ( prvKeyLine > 0 ) { prvKeyLine-- ; prvKeyLineTp = LineType(prvKeyLine, styler) ; if ( prvKeyLineTp & 4 ) break ; } // Determine the base line level of all lines following // the previous keyword // new keyword lines are placed on this level //if ( prvKeyLineTp & 4 ) { int level = styler.LevelAt(prvKeyLine) & ~SC_FOLDLEVELHEADERFLAG ; //} // uncomment line below if weird behaviour continues prvKeyLine = -1 ; // Now start scanning over the lines. for ( int line = startLine; line <= endLine; line++ ) { int lineType = LineType(line, styler) ; // Check for comment line if ( lineType == 8 ) { if ( beginComment < 0 ) { beginComment = line ; } } // Check for data line if ( (lineType == 1) || (lineType == 3) ) { if ( beginData < 0 ) { if ( beginComment >= 0 ) { beginData = beginComment ; } else { beginData = line ; } } beginComment = -1 ; } // Check for keywordline. // As soon as a keyword line is encountered, we can set the // levels of everything from the previous keyword line to this one if ( lineType & 4 ) { // this is a keyword, we can now place the previous keyword // all its data lines and the remainder // Write comments and data line if ( beginComment < 0 ) { beginComment = line ; } if ( beginData < 0 ) { beginData = beginComment ; if ( prvKeyLineTp != 5 ) SafeSetLevel(prvKeyLine, level, styler) ; else SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; } else { SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; } int datLevel = level + 1 ; if ( !(prvKeyLineTp & 4) ) { datLevel = level ; } for ( int ll = beginData; ll < beginComment; ll++ ) SafeSetLevel(ll, datLevel, styler) ; // The keyword we just found is going to be written at another level // if we have a type 5 and type 6 if ( prvKeyLineTp == 5 ) { level += 1 ; } if ( prvKeyLineTp == 6 ) { level -= 1 ; if ( level < 0 ) { level = 0 ; } } for ( int lll = beginComment; lll < line; lll++ ) SafeSetLevel(lll, level, styler) ; // wrap and reset beginComment = -1 ; beginData = -1 ; prvKeyLine = line ; prvKeyLineTp = lineType ; } } if ( beginComment < 0 ) { beginComment = endLine + 1 ; } else { // We need to find out whether this comment block is followed by // a data line or a keyword line const int docLines = styler.GetLine(styler.Length() - 1); for ( int line = endLine + 1; line <= docLines; line++ ) { int lineType = LineType(line, styler) ; if ( lineType != 8 ) { if ( !(lineType & 4) ) { beginComment = endLine + 1 ; } break ; } } } if ( beginData < 0 ) { beginData = beginComment ; if ( prvKeyLineTp != 5 ) SafeSetLevel(prvKeyLine, level, styler) ; else SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; } else { SafeSetLevel(prvKeyLine, level | SC_FOLDLEVELHEADERFLAG, styler) ; } int datLevel = level + 1 ; if ( !(prvKeyLineTp & 4) ) { datLevel = level ; } for ( int ll = beginData; ll < beginComment; ll++ ) SafeSetLevel(ll, datLevel, styler) ; if ( prvKeyLineTp == 5 ) { level += 1 ; } if ( prvKeyLineTp == 6 ) { level -= 1 ; } for ( int m = beginComment; m <= endLine; m++ ) SafeSetLevel(m, level, styler) ; }
static void ColourisePSDoc( unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { WordList &keywords1 = *keywordlists[0]; WordList &keywords2 = *keywordlists[1]; WordList &keywords3 = *keywordlists[2]; WordList &keywords4 = *keywordlists[3]; WordList &keywords5 = *keywordlists[4]; StyleContext sc(startPos, length, initStyle, styler); bool tokenizing = styler.GetPropertyInt("ps.tokenize") != 0; int pslevel = styler.GetPropertyInt("ps.level", 3); int lineCurrent = styler.GetLine(startPos); int nestTextCurrent = 0; if (lineCurrent > 0 && initStyle == SCE_PS_TEXT) nestTextCurrent = styler.GetLineState(lineCurrent - 1); int numRadix = 0; bool numHasPoint = false; bool numHasExponent = false; bool numHasSign = false; // Clear out existing tokenization if (tokenizing && length > 0) { styler.StartAt(startPos, static_cast<char>(INDIC2_MASK)); styler.ColourTo(startPos + length-1, 0); styler.Flush(); styler.StartAt(startPos); styler.StartSegment(startPos); } for (; sc.More(); sc.Forward()) { if (sc.atLineStart) lineCurrent = styler.GetLine(sc.currentPos); // Determine if the current state should terminate. if (sc.state == SCE_PS_COMMENT || sc.state == SCE_PS_DSC_VALUE) { if (sc.atLineEnd) { sc.SetState(SCE_C_DEFAULT); } } else if (sc.state == SCE_PS_DSC_COMMENT) { if (sc.ch == ':') { sc.Forward(); if (!sc.atLineEnd) sc.SetState(SCE_PS_DSC_VALUE); else sc.SetState(SCE_C_DEFAULT); } else if (sc.atLineEnd) { sc.SetState(SCE_C_DEFAULT); } else if (IsAWhitespaceChar(sc.ch) && sc.ch != '\r') { sc.ChangeState(SCE_PS_COMMENT); } } else if (sc.state == SCE_PS_NUMBER) { if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) { if ((sc.chPrev == '+' || sc.chPrev == '-' || sc.chPrev == 'E' || sc.chPrev == 'e') && numRadix == 0) sc.ChangeState(SCE_PS_NAME); sc.SetState(SCE_C_DEFAULT); } else if (sc.ch == '#') { if (numHasPoint || numHasExponent || numHasSign || numRadix != 0) { sc.ChangeState(SCE_PS_NAME); } else { char szradix[5]; sc.GetCurrent(szradix, 4); numRadix = atoi(szradix); if (numRadix < 2 || numRadix > 36) sc.ChangeState(SCE_PS_NAME); } } else if ((sc.ch == 'E' || sc.ch == 'e') && numRadix == 0) { if (numHasExponent) { sc.ChangeState(SCE_PS_NAME); } else { numHasExponent = true; if (sc.chNext == '+' || sc.chNext == '-') sc.Forward(); } } else if (sc.ch == '.') { if (numHasPoint || numHasExponent || numRadix != 0) { sc.ChangeState(SCE_PS_NAME); } else { numHasPoint = true; } } else if (numRadix == 0) { if (!IsABaseNDigit(sc.ch, 10)) sc.ChangeState(SCE_PS_NAME); } else { if (!IsABaseNDigit(sc.ch, numRadix)) sc.ChangeState(SCE_PS_NAME); } } else if (sc.state == SCE_PS_NAME || sc.state == SCE_PS_KEYWORD) { if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) { char s[100]; sc.GetCurrent(s, sizeof(s)); if ((pslevel >= 1 && keywords1.InList(s)) || (pslevel >= 2 && keywords2.InList(s)) || (pslevel >= 3 && keywords3.InList(s)) || keywords4.InList(s) || keywords5.InList(s)) { sc.ChangeState(SCE_PS_KEYWORD); } sc.SetState(SCE_C_DEFAULT); } } else if (sc.state == SCE_PS_LITERAL || sc.state == SCE_PS_IMMEVAL) { if (IsASelfDelimitingChar(sc.ch) || IsAWhitespaceChar(sc.ch)) sc.SetState(SCE_C_DEFAULT); } else if (sc.state == SCE_PS_PAREN_ARRAY || sc.state == SCE_PS_PAREN_DICT || sc.state == SCE_PS_PAREN_PROC) { sc.SetState(SCE_C_DEFAULT); } else if (sc.state == SCE_PS_TEXT) { if (sc.ch == '(') { nestTextCurrent++; } else if (sc.ch == ')') { if (--nestTextCurrent == 0) sc.ForwardSetState(SCE_PS_DEFAULT); } else if (sc.ch == '\\') { sc.Forward(); } } else if (sc.state == SCE_PS_HEXSTRING) { if (sc.ch == '>') { sc.ForwardSetState(SCE_PS_DEFAULT); } else if (!IsABaseNDigit(sc.ch, 16) && !IsAWhitespaceChar(sc.ch)) { sc.SetState(SCE_PS_HEXSTRING); styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR); } } else if (sc.state == SCE_PS_BASE85STRING) { if (sc.Match('~', '>')) { sc.Forward(); sc.ForwardSetState(SCE_PS_DEFAULT); } else if (!IsABase85Char(sc.ch) && !IsAWhitespaceChar(sc.ch)) { sc.SetState(SCE_PS_BASE85STRING); styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR); } } // Determine if a new state should be entered. if (sc.state == SCE_C_DEFAULT) { unsigned int tokenpos = sc.currentPos; if (sc.ch == '[' || sc.ch == ']') { sc.SetState(SCE_PS_PAREN_ARRAY); } else if (sc.ch == '{' || sc.ch == '}') { sc.SetState(SCE_PS_PAREN_PROC); } else if (sc.ch == '/') { if (sc.chNext == '/') { sc.SetState(SCE_PS_IMMEVAL); sc.Forward(); } else { sc.SetState(SCE_PS_LITERAL); } } else if (sc.ch == '<') { if (sc.chNext == '<') { sc.SetState(SCE_PS_PAREN_DICT); sc.Forward(); } else if (sc.chNext == '~') { sc.SetState(SCE_PS_BASE85STRING); sc.Forward(); } else { sc.SetState(SCE_PS_HEXSTRING); } } else if (sc.ch == '>' && sc.chNext == '>') { sc.SetState(SCE_PS_PAREN_DICT); sc.Forward(); } else if (sc.ch == '>' || sc.ch == ')') { sc.SetState(SCE_C_DEFAULT); styler.ColourTo(sc.currentPos, SCE_PS_BADSTRINGCHAR); } else if (sc.ch == '(') { sc.SetState(SCE_PS_TEXT); nestTextCurrent = 1; } else if (sc.ch == '%') { if (sc.chNext == '%' && sc.atLineStart) { sc.SetState(SCE_PS_DSC_COMMENT); sc.Forward(); if (sc.chNext == '+') { sc.Forward(); sc.ForwardSetState(SCE_PS_DSC_VALUE); } } else { sc.SetState(SCE_PS_COMMENT); } } else if ((sc.ch == '+' || sc.ch == '-' || sc.ch == '.') && IsABaseNDigit(sc.chNext, 10)) { sc.SetState(SCE_PS_NUMBER); numRadix = 0; numHasPoint = (sc.ch == '.'); numHasExponent = false; numHasSign = (sc.ch == '+' || sc.ch == '-'); } else if ((sc.ch == '+' || sc.ch == '-') && sc.chNext == '.' && IsABaseNDigit(sc.GetRelative(2), 10)) { sc.SetState(SCE_PS_NUMBER); numRadix = 0; numHasPoint = false; numHasExponent = false; numHasSign = true; } else if (IsABaseNDigit(sc.ch, 10)) { sc.SetState(SCE_PS_NUMBER); numRadix = 0; numHasPoint = false; numHasExponent = false; numHasSign = false; } else if (!IsAWhitespaceChar(sc.ch)) { sc.SetState(SCE_PS_NAME); } // Mark the start of tokens if (tokenizing && sc.state != SCE_C_DEFAULT && sc.state != SCE_PS_COMMENT && sc.state != SCE_PS_DSC_COMMENT && sc.state != SCE_PS_DSC_VALUE) { styler.Flush(); styler.StartAt(tokenpos, static_cast<char>(INDIC2_MASK)); styler.ColourTo(tokenpos, INDIC2_MASK); styler.Flush(); styler.StartAt(tokenpos); styler.StartSegment(tokenpos); } } if (sc.atLineEnd) styler.SetLineState(lineCurrent, nestTextCurrent); } sc.Complete(); }
//============================================================================= // Folding the code static void FoldNoBoxVHDLDoc( unsigned int startPos, int length, int, Accessor &styler) { // Decided it would be smarter to have the lexer have all keywords included. Therefore I // don't check if the style for the keywords that I use to adjust the levels. char words[] = "architecture begin case component else elsif end entity generate loop package process record then " "procedure function when"; WordList keywords; keywords.Set(words); bool foldComment = styler.GetPropertyInt("fold.comment", 1) != 0; bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; bool foldAtElse = styler.GetPropertyInt("fold.at.else", 1) != 0; bool foldAtBegin = styler.GetPropertyInt("fold.at.Begin", 1) != 0; bool foldAtParenthese = styler.GetPropertyInt("fold.at.Parenthese", 1) != 0; //bool foldAtWhen = styler.GetPropertyInt("fold.at.When", 1) != 0; //< fold at when in case statements int visibleChars = 0; unsigned int endPos = startPos + length; int lineCurrent = styler.GetLine(startPos); int levelCurrent = SC_FOLDLEVELBASE; if(lineCurrent > 0) levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; //int levelMinCurrent = levelCurrent; int levelMinCurrentElse = levelCurrent; //< Used for folding at 'else' int levelMinCurrentBegin = levelCurrent; //< Used for folding at 'begin' int levelNext = levelCurrent; /***************************************/ int lastStart = 0; char prevWord[32] = ""; /***************************************/ // Find prev word // The logic for going up or down a level depends on a the previous keyword // This code could be cleaned up. int end = 0; unsigned int j; for(j = startPos; j>0; j--) { char ch = styler.SafeGetCharAt(j); char chPrev = styler.SafeGetCharAt(j-1); int style = styler.StyleAt(j); int stylePrev = styler.StyleAt(j-1); if ((stylePrev != SCE_VHDL_COMMENT) && (stylePrev != SCE_VHDL_STRING)) { if(IsAWordChar(chPrev) && !IsAWordChar(ch)) { end = j-1; } } if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING)) { if(!IsAWordChar(chPrev) && IsAWordStart(ch) && (end != 0)) { char s[32]; unsigned int k; for(k=0; (k<31 ) && (k<end-j+1 ); k++) { s[k] = static_cast<char>(tolower(styler[j+k])); } s[k] = '\0'; if(keywords.InList(s)) { strcpy(prevWord, s); break; } } } } for(j=j+static_cast<unsigned int>(strlen(prevWord)); j<endPos; j++) { char ch = styler.SafeGetCharAt(j); int style = styler.StyleAt(j); if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING)) { if((ch == ';') && (strcmp(prevWord, "end") == 0)) { strcpy(prevWord, ";"); } } } char chNext = styler[startPos]; char chPrev = '\0'; char chNextNonBlank; int styleNext = styler.StyleAt(startPos); //Platform::DebugPrintf("Line[%04d] Prev[%20s] ************************* Level[%x]\n", lineCurrent+1, prevWord, levelCurrent); /***************************************/ for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); chPrev = styler.SafeGetCharAt(i - 1); chNextNonBlank = chNext; unsigned int j = i+1; while(IsABlank(chNextNonBlank) && j<endPos) { j ++ ; chNextNonBlank = styler.SafeGetCharAt(j); } int style = styleNext; styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) { if(!IsCommentLine(lineCurrent-1, styler) && IsCommentLine(lineCurrent+1, styler)) { levelNext++; } else if(IsCommentLine(lineCurrent-1, styler) && !IsCommentLine(lineCurrent+1, styler)) { levelNext--; } } if ((style == SCE_VHDL_OPERATOR) && foldAtParenthese) { if(ch == '(') { levelNext++; } else if (ch == ')') { levelNext--; } } if ((style != SCE_VHDL_COMMENT) && (style != SCE_VHDL_STRING)) { if((ch == ';') && (strcmp(prevWord, "end") == 0)) { strcpy(prevWord, ";"); } if(!IsAWordChar(chPrev) && IsAWordStart(ch)) { lastStart = i; } if(iswordchar(ch) && !iswordchar(chNext)) { char s[32]; unsigned int k; for(k=0; (k<31 ) && (k<i-lastStart+1 ); k++) { s[k] = static_cast<char>(tolower(styler[lastStart+k])); } s[k] = '\0'; if(keywords.InList(s)) { if ( strcmp(s, "architecture") == 0 || strcmp(s, "case") == 0 || strcmp(s, "component") == 0 || strcmp(s, "entity") == 0 || strcmp(s, "generate") == 0 || strcmp(s, "loop") == 0 || strcmp(s, "package") ==0 || strcmp(s, "process") == 0 || strcmp(s, "record") == 0 || strcmp(s, "then") == 0) { if (strcmp(prevWord, "end") != 0) { if (levelMinCurrentElse > levelNext) { levelMinCurrentElse = levelNext; } levelNext++; } } else if ( strcmp(s, "procedure") == 0 || strcmp(s, "function") == 0) { if (strcmp(prevWord, "end") != 0) // check for "end procedure" etc. { // This code checks to see if the procedure / function is a definition within a "package" // rather than the actual code in the body. int BracketLevel = 0; for(int j=i+1; j<styler.Length(); j++) { int LocalStyle = styler.StyleAt(j); char LocalCh = styler.SafeGetCharAt(j); if(LocalCh == '(') BracketLevel++; if(LocalCh == ')') BracketLevel--; if( (BracketLevel == 0) && (LocalStyle != SCE_VHDL_COMMENT) && (LocalStyle != SCE_VHDL_STRING) && !iswordchar(styler.SafeGetCharAt(j-1)) && styler.Match(j, "is") && !iswordchar(styler.SafeGetCharAt(j+2))) { if (levelMinCurrentElse > levelNext) { levelMinCurrentElse = levelNext; } levelNext++; break; } if((BracketLevel == 0) && (LocalCh == ';')) { break; } } } } else if (strcmp(s, "end") == 0) { levelNext--; } else if(strcmp(s, "elsif") == 0) { // elsif is followed by then so folding occurs correctly levelNext--; } else if (strcmp(s, "else") == 0) { if(strcmp(prevWord, "when") != 0) // ignore a <= x when y else z; { levelMinCurrentElse = levelNext - 1; // VHDL else is all on its own so just dec. the min level } } else if( ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "architecture") == 0)) || ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "function") == 0)) || ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "procedure") == 0))) { levelMinCurrentBegin = levelNext - 1; } //Platform::DebugPrintf("Line[%04d] Prev[%20s] Cur[%20s] Level[%x]\n", lineCurrent+1, prevWord, s, levelCurrent); strcpy(prevWord, s); } } } if (atEOL) { int levelUse = levelCurrent; if (foldAtElse && (levelMinCurrentElse < levelUse)) { levelUse = levelMinCurrentElse; } if (foldAtBegin && (levelMinCurrentBegin < levelUse)) { levelUse = levelMinCurrentBegin; } 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); } //Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent); lineCurrent++; levelCurrent = levelNext; //levelMinCurrent = levelCurrent; levelMinCurrentElse = levelCurrent; levelMinCurrentBegin = levelCurrent; visibleChars = 0; } /***************************************/ if (!isspacechar(ch)) visibleChars++; } /***************************************/ // Platform::DebugPrintf("Line[%04d] ---------------------------------------------------- Level[%x]\n", lineCurrent+1, levelCurrent); }
static void ColourisePyDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { int endPos = startPos + length; // Backtrack to previous line in case need to fix its tab whinging int lineCurrent = styler.GetLine(startPos); if (startPos > 0) { if (lineCurrent > 0) { lineCurrent--; // Look for backslash-continued lines while (lineCurrent > 0) { int eolPos = styler.LineStart(lineCurrent) - 1; int eolStyle = styler.StyleAt(eolPos); if (eolStyle == SCE_P_STRING || eolStyle == SCE_P_CHARACTER || eolStyle == SCE_P_STRINGEOL) { lineCurrent -= 1; } else { break; } } startPos = styler.LineStart(lineCurrent); } initStyle = startPos == 0 ? SCE_P_DEFAULT : styler.StyleAt(startPos - 1); } WordList &keywords = *keywordlists[0]; WordList &keywords2 = *keywordlists[1]; WordList &keywords3 = *keywordlists[2]; // property tab.timmy.whinge.level // For Python code, checks whether indenting is consistent. // The default, 0 turns off indentation checking, // 1 checks whether each line is potentially inconsistent with the previous line, // 2 checks whether any space characters occur before a tab character in the indentation, // 3 checks whether any spaces are in the indentation, and // 4 checks for any tab characters in the indentation. // 1 is a good level to use. const int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level"); // property lexer.python.literals.binary // Set to 0 to not recognise Python 3 binary and octal literals: 0b1011 0o712. bool base2or8Literals = styler.GetPropertyInt("lexer.python.literals.binary", 1) != 0; // property lexer.python.strings.u // Set to 0 to not recognise Python Unicode literals u"x" as used before Python 3. literalsAllowed allowedLiterals = (styler.GetPropertyInt("lexer.python.strings.u", 1)) ? litU : litNone; // property lexer.python.strings.b // Set to 0 to not recognise Python 3 bytes literals b"x". if (styler.GetPropertyInt("lexer.python.strings.b", 1)) allowedLiterals = static_cast<literalsAllowed>(allowedLiterals | litB); // property lexer.python.strings.over.newline // Set to 1 to allow strings to span newline characters. bool stringsOverNewline = styler.GetPropertyInt("lexer.python.strings.over.newline") != 0; // property lexer.python.keywords2.no.sub.identifiers // When enabled, it will not style keywords2 items that are used as a sub-identifier. // Example: when set, will not highlight "foo.open" when "open" is a keywords2 item. const bool keywords2NoSubIdentifiers = styler.GetPropertyInt("lexer.python.keywords2.no.sub.identifiers") != 0; initStyle = initStyle & 31; if (initStyle == SCE_P_STRINGEOL) { initStyle = SCE_P_DEFAULT; } kwType kwLast = kwOther; int spaceFlags = 0; styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment); bool base_n_number = false; StyleContext sc(startPos, endPos - startPos, initStyle, styler); bool indentGood = true; int startIndicator = sc.currentPos; bool inContinuedString = false; for (; sc.More(); sc.Forward()) { if (sc.atLineStart) { styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment); indentGood = true; if (whingeLevel == 1) { indentGood = (spaceFlags & wsInconsistent) == 0; } else if (whingeLevel == 2) { indentGood = (spaceFlags & wsSpaceTab) == 0; } else if (whingeLevel == 3) { indentGood = (spaceFlags & wsSpace) == 0; } else if (whingeLevel == 4) { indentGood = (spaceFlags & wsTab) == 0; } if (!indentGood) { styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 0); startIndicator = sc.currentPos; } } if (sc.atLineEnd) { if ((sc.state == SCE_P_DEFAULT) || (sc.state == SCE_P_TRIPLE) || (sc.state == SCE_P_TRIPLEDOUBLE)) { // Perform colourisation of white space and triple quoted strings at end of each line to allow // tab marking to work inside white space and triple quoted strings sc.SetState(sc.state); } lineCurrent++; if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) { if (inContinuedString || stringsOverNewline) { inContinuedString = false; } else { sc.ChangeState(SCE_P_STRINGEOL); sc.ForwardSetState(SCE_P_DEFAULT); } } if (!sc.More()) break; } bool needEOLCheck = false; // Check for a state end if (sc.state == SCE_P_OPERATOR) { kwLast = kwOther; sc.SetState(SCE_P_DEFAULT); } else if (sc.state == SCE_P_NUMBER) { if (!IsAWordChar(sc.ch) && !(!base_n_number && ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { sc.SetState(SCE_P_DEFAULT); } } else if (sc.state == SCE_P_IDENTIFIER) { if ((sc.ch == '.') || (!IsAWordChar(sc.ch))) { char s[100]; sc.GetCurrent(s, sizeof(s)); int style = SCE_P_IDENTIFIER; if ((kwLast == kwImport) && (strcmp(s, "as") == 0)) { style = SCE_P_WORD; } else if (keywords.InList(s)) { style = SCE_P_WORD; } else if (kwLast == kwClass) { style = SCE_P_CLASSNAME; } else if (kwLast == kwDef) { style = SCE_P_DEFNAME; } else if (kwLast == kwCDef || kwLast == kwCPDef) { int pos = sc.currentPos; unsigned char ch = styler.SafeGetCharAt(pos, '\0'); while (ch != '\0') { if (ch == '(') { style = SCE_P_DEFNAME; break; } else if (ch == ':') { style = SCE_P_CLASSNAME; break; } else if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') { pos++; ch = styler.SafeGetCharAt(pos, '\0'); } else { break; } } } else if (keywords2.InList(s)) { if (keywords2NoSubIdentifiers) { // We don't want to highlight keywords2 // that are used as a sub-identifier, // i.e. not open in "foo.open". int pos = styler.GetStartSegment() - 1; if (pos < 0 || (styler.SafeGetCharAt(pos, '\0') != '.')) style = SCE_P_WORD2; } else { style = SCE_P_WORD2; } } else if (keywords3.InList(s)) { style = SCE_P_WORD3; } sc.ChangeState(style); sc.SetState(SCE_P_DEFAULT); if (style == SCE_P_WORD) { if (0 == strcmp(s, "class")) kwLast = kwClass; else if (0 == strcmp(s, "def")) kwLast = kwDef; else if (0 == strcmp(s, "import")) kwLast = kwImport; else if (0 == strcmp(s, "cdef")) kwLast = kwCDef; else if (0 == strcmp(s, "cpdef")) kwLast = kwCPDef; else if (0 == strcmp(s, "cimport")) kwLast = kwImport; else if (kwLast != kwCDef && kwLast != kwCPDef) kwLast = kwOther; } else if (kwLast != kwCDef && kwLast != kwCPDef) { kwLast = kwOther; } } } else if ((sc.state == SCE_P_COMMENTLINE) || (sc.state == SCE_P_COMMENTBLOCK)) { if (sc.ch == '\r' || sc.ch == '\n') { sc.SetState(SCE_P_DEFAULT); } } else if (sc.state == SCE_P_DECORATOR) { if (!IsAWordChar(sc.ch)) { sc.SetState(SCE_P_DEFAULT); } } else if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) { if (sc.ch == '\\') { if ((sc.chNext == '\r') && (sc.GetRelative(2) == '\n')) { sc.Forward(); } if (sc.chNext == '\n' || sc.chNext == '\r') { inContinuedString = true; } else { // Don't roll over the newline. sc.Forward(); } } else if ((sc.state == SCE_P_STRING) && (sc.ch == '\"')) { sc.ForwardSetState(SCE_P_DEFAULT); needEOLCheck = true; } else if ((sc.state == SCE_P_CHARACTER) && (sc.ch == '\'')) { sc.ForwardSetState(SCE_P_DEFAULT); needEOLCheck = true; } } else if (sc.state == SCE_P_TRIPLE) { if (sc.ch == '\\') { sc.Forward(); } else if (sc.Match("\'\'\'")) { sc.Forward(); sc.Forward(); sc.ForwardSetState(SCE_P_DEFAULT); needEOLCheck = true; } } else if (sc.state == SCE_P_TRIPLEDOUBLE) { if (sc.ch == '\\') { sc.Forward(); } else if (sc.Match("\"\"\"")) { sc.Forward(); sc.Forward(); sc.ForwardSetState(SCE_P_DEFAULT); needEOLCheck = true; } } if (!indentGood && !IsASpaceOrTab(sc.ch)) { styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 1); startIndicator = sc.currentPos; indentGood = true; } // One cdef or cpdef line, clear kwLast only at end of line if ((kwLast == kwCDef || kwLast == kwCPDef) && sc.atLineEnd) { kwLast = kwOther; } // State exit code may have moved on to end of line if (needEOLCheck && sc.atLineEnd) { lineCurrent++; styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment); if (!sc.More()) break; } // Check for a new state starting character if (sc.state == SCE_P_DEFAULT) { if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { if (sc.ch == '0' && (sc.chNext == 'x' || sc.chNext == 'X')) { base_n_number = true; sc.SetState(SCE_P_NUMBER); } else if (sc.ch == '0' && (sc.chNext == 'o' || sc.chNext == 'O' || sc.chNext == 'b' || sc.chNext == 'B')) { if (base2or8Literals) { base_n_number = true; sc.SetState(SCE_P_NUMBER); } else { sc.SetState(SCE_P_NUMBER); sc.ForwardSetState(SCE_P_IDENTIFIER); } } else { base_n_number = false; sc.SetState(SCE_P_NUMBER); } } else if ((IsASCII(sc.ch) && isoperator(static_cast<char>(sc.ch))) || sc.ch == '`') { sc.SetState(SCE_P_OPERATOR); } else if (sc.ch == '#') { sc.SetState(sc.chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE); } else if (sc.ch == '@') { sc.SetState(SCE_P_DECORATOR); } else if (IsPyStringStart(sc.ch, sc.chNext, sc.GetRelative(2), allowedLiterals)) { unsigned int nextIndex = 0; sc.SetState(GetPyStringState(styler, sc.currentPos, &nextIndex, allowedLiterals)); while (nextIndex > (sc.currentPos + 1) && sc.More()) { sc.Forward(); } } else if (IsAWordStart(sc.ch)) { sc.SetState(SCE_P_IDENTIFIER); } } } styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 0); sc.Complete(); }
static void FoldTACLDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; unsigned int endPos = startPos + length; int visibleChars = 0; int lineCurrent = styler.GetLine(startPos); int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; int levelCurrent = levelPrev; char chNext = styler[startPos]; int styleNext = styler.StyleAt(startPos); int style = initStyle; bool section = false; int lastStart = 0; for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); int stylePrev = style; style = styleNext; styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); if (stylePrev == SCE_C_DEFAULT && (style == SCE_C_WORD || style == SCE_C_PREPROCESSOR)) { // Store last word start point. lastStart = i; } if (stylePrev == SCE_C_WORD || stylePrev == SCE_C_PREPROCESSOR) { if(isTACLwordchar(ch) && !isTACLwordchar(chNext)) { char s[100]; getRange(lastStart, i, styler, s, sizeof(s)); if (stylePrev == SCE_C_PREPROCESSOR && strcmp(s, "?section") == 0) { section = true; levelCurrent = 1; levelPrev = 0; } else if (stylePrev == SCE_C_WORD) levelCurrent += classifyFoldPointTACL(s); } } if (style == SCE_C_OPERATOR) { if (ch == '[') { levelCurrent++; } else if (ch == ']') { levelCurrent--; } } if (foldComment && (style == SCE_C_COMMENTLINE)) { if ((ch == '/') && (chNext == '/')) { char chNext2 = styler.SafeGetCharAt(i + 2); if (chNext2 == '{') { levelCurrent++; } else if (chNext2 == '}') { levelCurrent--; } } } if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { if (ch == '{' && chNext == '$') { unsigned int j=i+2; // skip {$ while ((j<endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { j++; } if (styler.Match(j, "region") || styler.Match(j, "if")) { levelCurrent++; } else if (styler.Match(j, "end")) { levelCurrent--; } } } if (foldComment && IsStreamCommentStyle(style)) { if (!IsStreamCommentStyle(stylePrev)) { levelCurrent++; } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { // Comments don't end at end of line and the next character may be unstyled. levelCurrent--; } } if (atEOL) { int lev = levelPrev | SC_FOLDLEVELBASE; if (visibleChars == 0 && foldCompact) lev |= SC_FOLDLEVELWHITEFLAG; if ((levelCurrent > levelPrev || section) && (visibleChars > 0)) lev |= SC_FOLDLEVELHEADERFLAG; if (lev != styler.LevelAt(lineCurrent)) { styler.SetLevel(lineCurrent, lev); } lineCurrent++; levelPrev = levelCurrent; visibleChars = 0; section = false; } if (!isspacechar(ch)) visibleChars++; } // Fill in the real level of the next line, keeping the current flags as they will be filled in later int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; styler.SetLevel(lineCurrent, levelPrev | flagsNext); }
static bool IsQuoteLine(int line, Accessor &styler) { int style = styler.StyleAt(styler.LineStart(line)) & 31; return ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE)); }
// Main colorizing function called by Scintilla static void ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { styler.StartAt(startPos); int quotestart = 0, oldstate, currentline = styler.GetLine(startPos); styler.StartSegment(startPos); bool noforward; char buff[BUFFSIZE+1]; // buffer for command name StyleContext sc(startPos, length, initStyle, styler); buff[0] = '\0'; // cbuff = 0; if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word.. colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); while (sc.More()) { noforward = 0; switch (sc.ch) { case '/': if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING) break; if (sc.chNext == '/') // line comment { sc.SetState (SCE_GC_COMMENTLINE); sc.Forward(); styler.ColourTo(sc.currentPos, sc.state); } else if (sc.chNext == '*') // block comment { sc.SetState(SCE_GC_COMMENTBLOCK); sc.Forward(); styler.ColourTo(sc.currentPos, sc.state); } else styler.ColourTo(sc.currentPos, sc.state); break; case '*': // end of comment block, or operator.. if (sc.state == SCE_GC_STRING) break; if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/') { sc.Forward(); styler.ColourTo(sc.currentPos, sc.state); sc.ChangeState (SCE_GC_DEFAULT); } else styler.ColourTo(sc.currentPos, sc.state); break; case '\'': case '\"': // strings.. if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE) break; if (sc.state == SCE_GC_STRING) { if (sc.ch == quotestart) // match same quote char.. { styler.ColourTo(sc.currentPos, sc.state); sc.ChangeState(SCE_GC_DEFAULT); quotestart = 0; } } else { styler.ColourTo(sc.currentPos - 1, sc.state); sc.ChangeState(SCE_GC_STRING); quotestart = sc.ch; } break; case ';': // end of commandline character if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && sc.state != SCE_GC_STRING) { styler.ColourTo(sc.currentPos - 1, sc.state); styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); sc.ChangeState(SCE_GC_DEFAULT); sc.Forward(); colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); noforward = 1; // don't move forward - already positioned at next char.. } break; case '+': case '-': case '=': case '!': // operators.. case '<': case '>': case '&': case '|': case '$': if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && sc.state != SCE_GC_STRING) { styler.ColourTo(sc.currentPos - 1, sc.state); styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); sc.ChangeState(SCE_GC_DEFAULT); } break; case '\\': // escape - same as operator, but also mark in strings.. if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE) { oldstate = sc.state; styler.ColourTo(sc.currentPos - 1, sc.state); sc.Forward(); // mark also the next char.. styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); sc.ChangeState(oldstate); } break; case '\n': case '\r': ++currentline; if (sc.state == SCE_GC_COMMENTLINE) { styler.ColourTo(sc.currentPos, sc.state); sc.ChangeState (SCE_GC_DEFAULT); } else if (sc.state != SCE_GC_COMMENTBLOCK) { colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); noforward = 1; // don't move forward - already positioned at next char.. } break; // case ' ': case '\t': // default : } if (!noforward) sc.Forward(); } sc.Complete(); }
static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unused*/, WordList *[], Accessor &styler) { const int maxPos = startPos + length; const int maxLines = (maxPos == styler.Length()) ? styler.GetLine(maxPos) : styler.GetLine(maxPos - 1); // Requested last line const int docLines = styler.GetLine(styler.Length()); // Available last line // property fold.quotes.python // This option enables folding multi-line quoted strings when using the Python lexer. const bool foldQuotes = styler.GetPropertyInt("fold.quotes.python") != 0; const bool foldCompact = styler.GetPropertyInt("fold.compact") != 0; // Backtrack to previous non-blank line so we can determine indent level // for any white space lines (needed esp. within triple quoted strings) // and so we can fix any preceding fold level (which is why we go back // at least one line in all cases) int spaceFlags = 0; int lineCurrent = styler.GetLine(startPos); int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); while (lineCurrent > 0) { lineCurrent--; indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) && (!IsCommentLine(lineCurrent, styler)) && (!IsQuoteLine(lineCurrent, styler))) break; } int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; // Set up initial loop state startPos = styler.LineStart(lineCurrent); int prev_state = SCE_P_DEFAULT & 31; if (lineCurrent >= 1) prev_state = styler.StyleAt(startPos - 1) & 31; int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) || (prev_state == SCE_P_TRIPLEDOUBLE)); // Process all characters to end of requested range or end of any triple quote //that hangs over the end of the range. Cap processing in all cases // to end of document (in case of unclosed quote at end). while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevQuote)) { // Gather info int lev = indentCurrent; int lineNext = lineCurrent + 1; int indentNext = indentCurrent; int quote = false; if (lineNext <= docLines) { // Information about next line is only available if not at end of document indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); int lookAtPos = (styler.LineStart(lineNext) == styler.Length()) ? styler.Length() - 1 : styler.LineStart(lineNext); int style = styler.StyleAt(lookAtPos) & 31; quote = foldQuotes && ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE)); } const int quote_start = (quote && !prevQuote); const int quote_continue = (quote && prevQuote); if (!quote || !prevQuote) indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; if (quote) indentNext = indentCurrentLevel; if (indentNext & SC_FOLDLEVELWHITEFLAG) indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; if (quote_start) { // Place fold point at start of triple quoted string lev |= SC_FOLDLEVELHEADERFLAG; } else if (quote_continue || prevQuote) { // Add level to rest of lines in the string lev = lev + 1; } // Skip past any blank lines for next indent level info; we skip also // comments (all comments, not just those starting in column 0) // which effectively folds them into surrounding code rather // than screwing up folding. while (!quote && (lineNext < docLines) && ((indentNext & SC_FOLDLEVELWHITEFLAG) || (lineNext <= docLines && IsCommentLine(lineNext, styler)))) { lineNext++; indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); } const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; const int levelBeforeComments = Maximum(indentCurrentLevel,levelAfterComments); // Now set all the indent levels on the lines we skipped // Do this from end to start. Once we encounter one line // which is indented more than the line after the end of // the comment-block, use the level of the block before int skipLine = lineNext; int skipLevel = levelAfterComments; while (--skipLine > lineCurrent) { int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL); if (foldCompact) { if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments) skipLevel = levelBeforeComments; int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; styler.SetLevel(skipLine, skipLevel | whiteFlag); } else { if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments && !(skipLineIndent & SC_FOLDLEVELWHITEFLAG) && !IsCommentLine(skipLine, styler)) skipLevel = levelBeforeComments; styler.SetLevel(skipLine, skipLevel); } } // Set fold header on non-quote line if (!quote && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) lev |= SC_FOLDLEVELHEADERFLAG; } // Keep track of triple quote state of previous line prevQuote = quote; // Set fold level for this line and move to next line styler.SetLevel(lineCurrent, foldCompact ? lev : lev & ~SC_FOLDLEVELWHITEFLAG); indentCurrent = indentNext; lineCurrent = lineNext; } // NOTE: Cannot set level of last line here because indentCurrent doesn't have // header flag set; the loop above is crafted to take care of this case! //styler.SetLevel(lineCurrent, indentCurrent); }
static void FoldMSSQLDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; unsigned int endPos = startPos + length; int visibleChars = 0; int lineCurrent = styler.GetLine(startPos); int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; int levelCurrent = levelPrev; char chNext = styler[startPos]; bool inComment = (styler.StyleAt(startPos-1) == SCE_MSSQL_COMMENT); char s[10] = ""; for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); int style = styler.StyleAt(i); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); // Comment folding if (foldComment) { if (!inComment && (style == SCE_MSSQL_COMMENT)) levelCurrent++; else if (inComment && (style != SCE_MSSQL_COMMENT)) levelCurrent--; inComment = (style == SCE_MSSQL_COMMENT); } if (style == SCE_MSSQL_STATEMENT) { // Folding between begin or case and end if (ch == 'b' || ch == 'B' || ch == 'c' || ch == 'C' || ch == 'e' || ch == 'E') { for (unsigned int j = 0; j < 5; j++) { if (!iswordchar(styler[i + j])) { break; } s[j] = static_cast<char>(tolower(styler[i + j])); s[j + 1] = '\0'; } if ((strcmp(s, "begin") == 0) || (strcmp(s, "case") == 0)) { levelCurrent++; } if (strcmp(s, "end") == 0) { levelCurrent--; } } } if (atEOL) { int lev = levelPrev; if (visibleChars == 0 && foldCompact) lev |= SC_FOLDLEVELWHITEFLAG; if ((levelCurrent > levelPrev) && (visibleChars > 0)) lev |= SC_FOLDLEVELHEADERFLAG; if (lev != styler.LevelAt(lineCurrent)) { styler.SetLevel(lineCurrent, lev); } lineCurrent++; levelPrev = levelCurrent; visibleChars = 0; } if (!isspacechar(ch)) visibleChars++; } // Fill in the real level of the next line, keeping the current flags as they will be filled in later int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; styler.SetLevel(lineCurrent, levelPrev | flagsNext); }
// Store both the current line's fold level and the next lines in the // level store to make it easy to pick up with each increment. static void FoldMySQLDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *[], Accessor &styler) { bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; bool foldOnlyBegin = styler.GetPropertyInt("fold.sql.only.begin", 0) != 0; int visibleChars = 0; Sci_Position lineCurrent = styler.GetLine(startPos); int levelCurrent = SC_FOLDLEVELBASE; if (lineCurrent > 0) levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; int levelNext = levelCurrent; int styleNext = styler.StyleAt(startPos); int style = initStyle; int activeState = (style == SCE_MYSQL_HIDDENCOMMAND) ? HIDDENCOMMAND_STATE : style & HIDDENCOMMAND_STATE; bool endPending = false; bool whenPending = false; bool elseIfPending = false; char nextChar = styler.SafeGetCharAt(startPos); for (Sci_PositionU i = startPos; length > 0; i++, length--) { int stylePrev = style; int lastActiveState = activeState; style = styleNext; styleNext = styler.StyleAt(i + 1); activeState = (style == SCE_MYSQL_HIDDENCOMMAND) ? HIDDENCOMMAND_STATE : style & HIDDENCOMMAND_STATE; char currentChar = nextChar; nextChar = styler.SafeGetCharAt(i + 1); bool atEOL = (currentChar == '\r' && nextChar != '\n') || (currentChar == '\n'); switch (MASKACTIVE(style)) { case SCE_MYSQL_COMMENT: if (foldComment) { // Multiline comment style /* .. */ just started or is still in progress. if (IsStreamCommentStyle(style) && !IsStreamCommentStyle(stylePrev)) levelNext++; } break; case SCE_MYSQL_COMMENTLINE: if (foldComment) { // Not really a standard, but we add support for single line comments // with special curly braces syntax as foldable comments too. // MySQL needs -- comments to be followed by space or control char if (styler.Match(i, "--")) { char chNext2 = styler.SafeGetCharAt(i + 2); char chNext3 = styler.SafeGetCharAt(i + 3); if (chNext2 == '{' || chNext3 == '{') levelNext++; else if (chNext2 == '}' || chNext3 == '}') levelNext--; } } break; case SCE_MYSQL_HIDDENCOMMAND: /* if (endPending) { // A conditional command is not a white space so it should end the current block // before opening a new one. endPending = false; levelNext--; if (levelNext < SC_FOLDLEVELBASE) levelNext = SC_FOLDLEVELBASE; } }*/ if (activeState != lastActiveState) levelNext++; break; case SCE_MYSQL_OPERATOR: if (endPending) { endPending = false; levelNext--; if (levelNext < SC_FOLDLEVELBASE) levelNext = SC_FOLDLEVELBASE; } if (currentChar == '(') levelNext++; else if (currentChar == ')') { levelNext--; if (levelNext < SC_FOLDLEVELBASE) levelNext = SC_FOLDLEVELBASE; } break; case SCE_MYSQL_MAJORKEYWORD: case SCE_MYSQL_KEYWORD: case SCE_MYSQL_FUNCTION: case SCE_MYSQL_PROCEDUREKEYWORD: // Reserved and other keywords. if (style != stylePrev) { // END decreases the folding level, regardless which keyword follows. bool endFound = MatchIgnoreCase(styler, i, "end"); if (endPending) { levelNext--; if (levelNext < SC_FOLDLEVELBASE) levelNext = SC_FOLDLEVELBASE; } else if (!endFound) { if (MatchIgnoreCase(styler, i, "begin")) levelNext++; else { if (!foldOnlyBegin) { bool whileFound = MatchIgnoreCase(styler, i, "while"); bool loopFound = MatchIgnoreCase(styler, i, "loop"); bool repeatFound = MatchIgnoreCase(styler, i, "repeat"); bool caseFound = MatchIgnoreCase(styler, i, "case"); if (whileFound || loopFound || repeatFound || caseFound) levelNext++; else { // IF alone does not increase the fold level as it is also used in non-block'ed // code like DROP PROCEDURE blah IF EXISTS. // Instead THEN opens the new level (if not part of an ELSEIF or WHEN (case) branch). if (MatchIgnoreCase(styler, i, "then")) { if (!elseIfPending && !whenPending) levelNext++; else { elseIfPending = false; whenPending = false; } } else { // Neither of if/then/while/loop/repeat/case, so check for // sub parts of IF and CASE. if (MatchIgnoreCase(styler, i, "elseif")) elseIfPending = true; if (MatchIgnoreCase(styler, i, "when")) whenPending = true; } } } } } // Keep the current end state for the next round. endPending = endFound; } break; default: if (!isspacechar(currentChar) && endPending) { // END followed by a non-whitespace character (not covered by other cases like identifiers) // also should end a folding block. Typical case: END followed by self defined delimiter. levelNext--; if (levelNext < SC_FOLDLEVELBASE) levelNext = SC_FOLDLEVELBASE; } break; } // Go up one level if we just ended a multi line comment. if (IsStreamCommentStyle(stylePrev) && !IsStreamCommentStyle(style)) { levelNext--; if (levelNext < SC_FOLDLEVELBASE) levelNext = SC_FOLDLEVELBASE; } if (activeState == 0 && lastActiveState != 0) { // Decrease fold level when we left a hidden command. levelNext--; if (levelNext < SC_FOLDLEVELBASE) levelNext = SC_FOLDLEVELBASE; } if (atEOL) { // Apply the new folding level to this line. // Leave pending states as they are otherwise a line break will de-sync // code folding and valid syntax. 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); lineCurrent++; levelCurrent = levelNext; visibleChars = 0; } if (!isspacechar(currentChar)) visibleChars++; } }
static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { //define the character sets CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true); CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); //used to tell if we're recursively folding the whole document, or just a small piece (ie: if statement or 1 function) bool isFoldingAll = true; int endPos = startPos + length; int lastLine = styler.GetLine(styler.Length()); //used to help fold the last line correctly // 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 = true; // Backtrack to previous line in case need to fix its fold status int lineCurrent = styler.GetLine(startPos); if (startPos > 0) { isFoldingAll = false; 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 isFirstWordStarted = false; bool isFirstWordEnded = false; const unsigned int FIRST_WORD_MAX_LEN = 10; char szFirstWord[FIRST_WORD_MAX_LEN] = ""; unsigned int firstWordLen = 0; char szDo[3]=""; int szDolen = 0; bool isDoLastWord = false; // var for indentlevel int levelCurrent = SC_FOLDLEVELBASE; if (lineCurrent > 0) levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; int levelNext = levelCurrent; int visibleChars = 0; int functionCount = 0; char chNext = styler.SafeGetCharAt(startPos); char chPrev = '\0'; char chPrevPrev = '\0'; char chPrevPrevPrev = '\0'; for (int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); if ((ch > 0) && setWord.Contains(ch)) visibleChars++; // get the syle for the current character neede to check in comment int stylech = styler.StyleAt(i); // start the capture of the first word if (!isFirstWordStarted && (ch > 0)) { if (setWord.Contains(ch) || setWordStart.Contains(ch) || ch == ';' || ch == '/') { isFirstWordStarted = true; if (firstWordLen < FIRST_WORD_MAX_LEN - 1) { szFirstWord[firstWordLen++] = static_cast<char>(tolower(ch)); szFirstWord[firstWordLen] = '\0'; } } } // continue capture of the first word on the line else if (isFirstWordStarted && !isFirstWordEnded && (ch > 0)) { if (!setWord.Contains(ch)) { isFirstWordEnded = true; } else if (firstWordLen < (FIRST_WORD_MAX_LEN - 1)) { szFirstWord[firstWordLen++] = static_cast<char>(tolower(ch)); szFirstWord[firstWordLen] = '\0'; } } if (stylech != SCE_POWERPRO_COMMENTLINE) { //reset isDoLastWord if we find a character(ignoring spaces) after 'do' if (isDoLastWord && (ch > 0) && setWord.Contains(ch)) isDoLastWord = false; // --find out if the word "do" is the last on a "if" line-- // collect each letter and put it into a buffer 2 chars long // if we end up with "do" in the buffer when we reach the end of // the line, "do" was the last word on the line if ((ch > 0) && isFirstWordEnded && strcmp(szFirstWord, "if") == 0) { if (szDolen == 2) { szDo[0] = szDo[1]; szDo[1] = static_cast<char>(tolower(ch)); szDo[2] = '\0'; if (strcmp(szDo, "do") == 0) isDoLastWord = true; } else if (szDolen < 2) { szDo[szDolen++] = static_cast<char>(tolower(ch)); szDo[szDolen] = '\0'; } } } // End of Line found so process the information if ((ch == '\r' && chNext != '\n') // \r\n || ch == '\n' // \n || i == endPos) { // end of selection // ************************** // 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 (firstWordLen > 0 && chPrev != '+' && chPrevPrev != ';' && chPrevPrevPrev !=';' && (!IsStreamCommentStyle(style) || foldInComment) ) { // only fold "if" last keyword is "then" (else its a one line if) if (strcmp(szFirstWord, "if") == 0 && isDoLastWord) levelNext++; // create new fold for these words if (strcmp(szFirstWord, "for") == 0) levelNext++; //handle folding for functions/labels //Note: Functions and labels don't have an explicit end like [end function] // 1. functions/labels end at the start of another function // 2. functions/labels end at the end of the file if ((strcmp(szFirstWord, "function") == 0) || (firstWordLen > 0 && szFirstWord[0] == '@')) { if (isFoldingAll) { //if we're folding the whole document (recursivly by lua script) if (functionCount > 0) { levelCurrent--; } else { levelNext++; } functionCount++; } else { //if just folding a small piece (by clicking on the minus sign next to the word) levelCurrent--; } } // end the fold for these words before the current line if (strcmp(szFirstWord, "endif") == 0 || strcmp(szFirstWord, "endfor") == 0) { levelNext--; levelCurrent--; } // end the fold for these words before the current line and Start new fold if (strcmp(szFirstWord, "else") == 0 || strcmp(szFirstWord, "elseif") == 0 ) levelCurrent--; } // Preprocessor and Comment folding int styleNext = GetStyleFirstWord(lineCurrent + 1,styler); // ********************************* // 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_POWERPRO_COMMENTLINE && stylePrev == SCE_POWERPRO_COMMENTLINE && style == SCE_POWERPRO_COMMENTLINE) { levelNext--; } // fold till the one but last line for Blockcomment lines else if (IsStreamCommentStyle(stylePrev) && styleNext != SCE_POWERPRO_COMMENTBLOCK && style == SCE_POWERPRO_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 characters are ;;+ then don't reset since the line continues on the next line. if (chPrev != '+' && chPrevPrev != ';' && chPrevPrevPrev != ';') { firstWordLen = 0; szDolen = 0; isFirstWordStarted = false; isFirstWordEnded = false; isDoLastWord = false; //blank out first word for (unsigned int i = 0; i < FIRST_WORD_MAX_LEN; i++) szFirstWord[i] = '\0'; } } // save the last processed characters if ((ch > 0) && !isspacechar(ch)) { chPrevPrevPrev = chPrevPrev; chPrevPrev = chPrev; chPrev = ch; } } //close folds on the last line - without this a 'phantom' //fold can appear when an open fold is on the last line //this can occur because functions and labels don't have an explicit end if (lineCurrent >= lastLine) { int lev = 0; lev |= SC_FOLDLEVELWHITEFLAG; styler.SetLevel(lineCurrent, lev); } }
static int LineStart(int line, Accessor &styler) { return styler.LineStart(line) ; }
inline bool HandleWord( unsigned int & cur, unsigned int one_too_much, Accessor & styler, WordList * keywordlists[] ) { char ch; const unsigned int beg = cur; cur++; for( ; ; ) { ch = styler.SafeGetCharAt( cur ); if( ( ch != '_' ) && ( ch != '-' ) && !islower( ch ) && !isupper( ch ) && !isdigit( ch ) ) break; cur++; if( cur >= one_too_much ) { break; } } const int ide_len = cur - beg + 1; char * ide = new char[ ide_len ]; getRange( beg, cur, styler, ide, ide_len ); WordList & keywords = *keywordlists[ 0 ]; WordList & classwords = *keywordlists[ 1 ]; if( keywords.InList( ide ) ) // Keyword { delete [] ide; styler.ColourTo( cur - 1, SCE_OPAL_KEYWORD ); if( cur >= one_too_much ) { return false; // STOP } else { styler.StartSegment( cur ); return true; } } else if( classwords.InList( ide ) ) // Sort { delete [] ide; styler.ColourTo( cur - 1, SCE_OPAL_SORT ); if( cur >= one_too_much ) { return false; // STOP } else { styler.StartSegment( cur ); return true; } } else if( !strcmp( ide, "true" ) || !strcmp( ide, "false" ) ) // Bool const { delete [] ide; styler.ColourTo( cur - 1, SCE_OPAL_BOOL_CONST ); if( cur >= one_too_much ) { return false; // STOP } else { styler.StartSegment( cur ); return true; } } else // Unknown keyword { delete [] ide; styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); if( cur >= one_too_much ) { return false; // STOP } else { styler.StartSegment( cur ); return true; } } }
// LineType // // bits determines the line type // 1 : data line // 2 : only whitespace // 3 : data line with only whitespace // 4 : keyword line // 5 : block open keyword line // 6 : block close keyword line // 7 : keyword line in error // 8 : comment line static int LineType(int line, Accessor &styler) { int pos = LineStart(line, styler) ; int eol_pos = LineEnd(line, styler) ; int c ; char ch = ' '; int i = pos ; while ( i < eol_pos ) { c = styler.SafeGetCharAt(i); ch = static_cast<char>(LowerCase(c)); // We can say something as soon as no whitespace // was encountered if ( !IsSpace(c) ) break ; i++ ; } if ( i >= eol_pos ) { // This is a whitespace line, currently // classifies as data line return 3 ; } if ( ch != '*' ) { // This is a data line return 1 ; } if ( i == eol_pos - 1 ) { // Only a single *, error but make keyword line return 4+3 ; } // This means we can have a second character // if that is also a * this means a comment // otherwise it is a keyword. c = styler.SafeGetCharAt(i+1); ch = static_cast<char>(LowerCase(c)); if ( ch == '*' ) { return 8 ; } // At this point we know this is a keyword line // the character at position i is a * // it is not a comment line char word[256] ; int wlen = 0; word[wlen] = '*' ; wlen++ ; i++ ; while ( (i < eol_pos) && (wlen < 255) ) { c = styler.SafeGetCharAt(i); ch = static_cast<char>(LowerCase(c)); if ( (!IsSpace(c)) && (!IsIdentifier(c)) ) break ; if ( IsIdentifier(c) ) { word[wlen] = ch ; wlen++ ; } i++ ; } word[wlen] = 0 ; // Make a comparison if ( !strcmp(word, "*step") || !strcmp(word, "*part") || !strcmp(word, "*instance") || !strcmp(word, "*assembly")) { return 4+1 ; } if ( !strcmp(word, "*endstep") || !strcmp(word, "*endpart") || !strcmp(word, "*endinstance") || !strcmp(word, "*endassembly")) { return 4+2 ; } return 4 ; }
inline bool HandleCommentBlock( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail ) { char ch; if( could_fail ) { cur++; if( cur >= one_too_much ) { styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); return false; // STOP } ch = styler.SafeGetCharAt( cur ); if( ch != '*' ) { styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); styler.StartSegment( cur ); return true; } } // Wait for comment close cur++; bool star_found = false; for( ; ; ) { if( cur >= one_too_much ) { styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_BLOCK ); return false; // STOP } ch = styler.SafeGetCharAt( cur ); if( star_found ) { if( ch == '/' ) { styler.ColourTo( cur, SCE_OPAL_COMMENT_BLOCK ); cur++; if( cur >= one_too_much ) { return false; // STOP } else { styler.StartSegment( cur ); return true; } } else if( ch != '*' ) { star_found = false; } } else if( ch == '*' ) { star_found = true; } cur++; } }
static void FoldErlangDoc( unsigned int startPos, int length, int initStyle, WordList** /*keywordlists*/, Accessor &styler ) { unsigned int endPos = startPos + length; int currentLine = styler.GetLine(startPos); int lev; int previousLevel = styler.LevelAt(currentLine) & SC_FOLDLEVELNUMBERMASK; int currentLevel = previousLevel; int styleNext = styler.StyleAt(startPos); int style = initStyle; int stylePrev; int keyword_start = 0; char ch; char chNext = styler.SafeGetCharAt(startPos); bool atEOL; for (unsigned int i = startPos; i < endPos; i++) { ch = chNext; chNext = styler.SafeGetCharAt(i + 1); // Get styles stylePrev = style; style = styleNext; styleNext = styler.StyleAt(i + 1); atEOL = ((ch == '\r') && (chNext != '\n')) || (ch == '\n'); if (stylePrev != SCE_ERLANG_KEYWORD && style == SCE_ERLANG_KEYWORD) { keyword_start = i; } // Fold on keywords if (stylePrev == SCE_ERLANG_KEYWORD && style != SCE_ERLANG_KEYWORD && style != SCE_ERLANG_ATOM ) { currentLevel += ClassifyErlangFoldPoint(styler, styleNext, keyword_start); } // Fold on comments if (style == SCE_ERLANG_COMMENT || style == SCE_ERLANG_COMMENT_MODULE || style == SCE_ERLANG_COMMENT_FUNCTION) { if (ch == '%' && chNext == '{') { currentLevel++; } else if (ch == '%' && chNext == '}') { currentLevel--; } } // Fold on braces if (style == SCE_ERLANG_OPERATOR) { if (ch == '{' || ch == '(' || ch == '[') { currentLevel++; } else if (ch == '}' || ch == ')' || ch == ']') { currentLevel--; } } if (atEOL) { lev = previousLevel; if (currentLevel > previousLevel) lev |= SC_FOLDLEVELHEADERFLAG; if (lev != styler.LevelAt(currentLine)) styler.SetLevel(currentLine, lev); currentLine++; previousLevel = currentLevel; } } // Fill in the real level of the next line, keeping the current flags as they will be filled in later styler.SetLevel(currentLine, previousLevel | (styler.LevelAt(currentLine) & ~SC_FOLDLEVELNUMBERMASK)); }