aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/LexSQL.cxx
diff options
context:
space:
mode:
authornyamatongwe <unknown>2005-10-23 00:31:35 +0000
committernyamatongwe <unknown>2005-10-23 00:31:35 +0000
commit749513e26f6b6ba717768a6d344d3d9255b43dac (patch)
treee2c517cc9d8c2b4a69d15578a179eb10a938d1eb /src/LexSQL.cxx
parent7a0bd2611be4943586d40ef56ef172c61da30d40 (diff)
downloadscintilla-mirror-749513e26f6b6ba717768a6d344d3d9255b43dac.tar.gz
Large patch from Philippe rewrites the code to use StyleContext.
Folding is performed for '(', '--{', and '-- {' and for indentation.
Diffstat (limited to 'src/LexSQL.cxx')
-rw-r--r--src/LexSQL.cxx527
1 files changed, 230 insertions, 297 deletions
diff --git a/src/LexSQL.cxx b/src/LexSQL.cxx
index b1b2c1624..75a958cb6 100644
--- a/src/LexSQL.cxx
+++ b/src/LexSQL.cxx
@@ -1,8 +1,8 @@
// Scintilla source code edit control
/** @file LexSQL.cxx
- ** Lexer for SQL.
+ ** Lexer for SQL, including PL/SQL and SQL*Plus.
**/
-// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
@@ -15,313 +15,219 @@
#include "PropSet.h"
#include "Accessor.h"
+#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"
-
-static inline bool IsASpace(unsigned int ch) {
- return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
+static inline bool IsAWordChar(int ch) {
+ return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
}
-static bool MatchIgnoreCaseSubstring(const char *s, Accessor &styler, unsigned int startPos) {
- char ch = styler.SafeGetCharAt(startPos);
- bool isSubword = false;
- if (tolower(ch) != *s)
- return false;
- s++;
- if (*s == '~')
- {
- isSubword = true;
- s++;
- }
- int n;
- for (n = 1; *s; n++) {
- if (*s == '~')
- {
- isSubword = true;
- s++;
- }
- if (isSubword && IsASpace(styler.SafeGetCharAt(startPos + n)))
- return true;
- if (*s != tolower((styler.SafeGetCharAt(startPos + n))))
- return false;
- s++;
- }
- return (IsASpace(styler.SafeGetCharAt(startPos + n))
- || styler.SafeGetCharAt(startPos + n) == ';');
+static inline bool IsAWordStart(int ch) {
+ return (ch < 0x80) && (isalpha(ch) || ch == '_');
}
-static void getCurrent(unsigned int start,
- unsigned int end,
- Accessor &styler,
- char *s,
- unsigned int len) {
- for (unsigned int i = 0; i < end - start + 1 && i < len; i++) {
- s[i] = static_cast<char>(tolower(styler[start + i]));
- s[i + 1] = '\0';
- }
+static inline bool IsADoxygenChar(int ch) {
+ return (islower(ch) || ch == '$' || ch == '@' ||
+ ch == '\\' || ch == '&' || ch == '<' ||
+ ch == '>' || ch == '#' || ch == '{' ||
+ ch == '}' || ch == '[' || ch == ']');
}
-static void classifyWordSQL(unsigned int start, unsigned int end, WordList *keywordlists[], Accessor &styler) {
- char s[100];
- bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
- for (unsigned int i = 0; i < end - start + 1 && i < 80; i++) {
- s[i] = static_cast<char>(tolower(styler[start + i]));
- s[i + 1] = '\0';
- }
-
- WordList &keywords1 = *keywordlists[0];
- WordList &keywords2 = *keywordlists[1];
-// WordList &kw_pldoc = *keywordlists[2];
- WordList &kw_sqlplus = *keywordlists[3];
- WordList &kw_user1 = *keywordlists[4];
- WordList &kw_user2 = *keywordlists[5];
- WordList &kw_user3 = *keywordlists[6];
- WordList &kw_user4 = *keywordlists[7];
-
- char chAttr = SCE_SQL_IDENTIFIER;
- if (wordIsNumber)
- chAttr = SCE_SQL_NUMBER;
- else if (keywords1.InList(s))
- chAttr = SCE_SQL_WORD;
- else if (keywords2.InList(s))
- chAttr = SCE_SQL_WORD2;
- else if (kw_sqlplus.InListAbbreviated(s, '~'))
- chAttr = SCE_SQL_SQLPLUS;
- else if (kw_user1.InList(s))
- chAttr = SCE_SQL_USER1;
- else if (kw_user2.InList(s))
- chAttr = SCE_SQL_USER2;
- else if (kw_user3.InList(s))
- chAttr = SCE_SQL_USER3;
- else if (kw_user4.InList(s))
- chAttr = SCE_SQL_USER4;
-
- styler.ColourTo(end, chAttr);
+static inline bool IsANumberChar(int ch) {
+ // Not exactly following number definition (several dots are seen as OK, etc.)
+ // but probably enough in most cases.
+ return (ch < 0x80) &&
+ (isdigit(ch) || toupper(ch) == 'E' ||
+ ch == '.' || ch == '-' || ch == '+');
}
-static void ColouriseSQLDoc(unsigned int startPos, int length,
- int initStyle, WordList *keywordlists[], Accessor &styler) {
+static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler) {
+
+ WordList &keywords1 = *keywordlists[0];
+ WordList &keywords2 = *keywordlists[1];
WordList &kw_pldoc = *keywordlists[2];
- styler.StartAt(startPos);
+ WordList &kw_sqlplus = *keywordlists[3];
+ WordList &kw_user1 = *keywordlists[4];
+ WordList &kw_user2 = *keywordlists[5];
+ WordList &kw_user3 = *keywordlists[6];
+ WordList &kw_user4 = *keywordlists[7];
+
+ StyleContext sc(startPos, length, initStyle, styler);
- bool fold = styler.GetPropertyInt("fold") != 0;
bool sqlBackslashEscapes = styler.GetPropertyInt("sql.backslash.escapes", 0) != 0;
- bool sqlBackticksIdentifier = styler.GetPropertyInt("sql.backticks.identifier", 0) != 0;
+ bool sqlBackticksIdentifier = styler.GetPropertyInt("lexer.sql.backticks.identifier", 0) != 0;
+ int styleBeforeDCKeyword = SCE_C_DEFAULT;
+ bool fold = styler.GetPropertyInt("fold") != 0;
int lineCurrent = styler.GetLine(startPos);
- int spaceFlags = 0;
- int state = 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')) {
+ for (; sc.More(); sc.Forward()) {
+ // Fold based on indentation
+ if (sc.atLineStart) {
+ int spaceFlags = 0;
int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
- int lev = indentCurrent;
+ int level = 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;
+ level |= SC_FOLDLEVELHEADERFLAG;
}
}
if (fold) {
- styler.SetLevel(lineCurrent, lev);
+ styler.SetLevel(lineCurrent, level);
}
}
- if (styler.IsLeadByte(ch)) {
- chNext = styler.SafeGetCharAt(i + 2);
- chPrev = ' ';
- i += 1;
- continue;
- }
-
- if (state == SCE_SQL_DEFAULT) {
- if (MatchIgnoreCaseSubstring("rem~ark", styler, i)) {
- styler.ColourTo(i - 1, state);
- state = SCE_SQL_SQLPLUS_COMMENT;
- } else if (MatchIgnoreCaseSubstring("pro~mpt", styler, i)) {
- styler.ColourTo(i - 1, state);
- state = SCE_SQL_SQLPLUS_PROMPT;
- } else if (iswordstart(ch)) {
- styler.ColourTo(i - 1, state);
- state = SCE_SQL_WORD;
- } else if (ch == '/' && chNext == '*') {
- styler.ColourTo(i - 1, state);
- if ((styler.SafeGetCharAt(i + 2)) == '*') { // Support of Doxygen doc. style
- state = SCE_SQL_COMMENTDOC;
- } else {
- state = SCE_SQL_COMMENT;
- }
- } else if (ch == '-' && chNext == '-') {
- styler.ColourTo(i - 1, state);
- state = SCE_SQL_COMMENTLINE;
- } else if (ch == '#') {
- styler.ColourTo(i - 1, state);
- state = SCE_SQL_COMMENTLINEDOC;
- } else if (ch == '\'') {
- styler.ColourTo(i - 1, state);
- state = SCE_SQL_CHARACTER;
- } else if (ch == '"') {
- styler.ColourTo(i - 1, state);
- state = SCE_SQL_STRING;
- } else if (ch == 0x60 && sqlBackticksIdentifier) {
- styler.ColourTo(i - 1, state);
- state = SCE_SQL_QUOTEDIDENTIFIER;
- } else if (isoperator(ch)) {
- styler.ColourTo(i - 1, state);
- styler.ColourTo(i, SCE_SQL_OPERATOR);
+ // Determine if the current state should terminate.
+ switch (sc.state) {
+ case SCE_SQL_OPERATOR:
+ sc.SetState(SCE_SQL_DEFAULT);
+ break;
+ case SCE_SQL_NUMBER:
+ // We stop the number definition on non-numerical non-dot non-eE non-sign char
+ if (!IsANumberChar(sc.ch)) {
+ sc.SetState(SCE_SQL_DEFAULT);
}
- } else if (state == SCE_SQL_WORD) {
- if (!iswordchar(ch)) {
- classifyWordSQL(styler.GetStartSegment(), i - 1, keywordlists, styler);
- state = SCE_SQL_DEFAULT;
- if (ch == '/' && chNext == '*') {
- if ((styler.SafeGetCharAt(i + 2)) == '*') { // Support of Doxygen doc. style
- state = SCE_SQL_COMMENTDOC;
- } else {
- state = SCE_SQL_COMMENT;
+ break;
+ case SCE_SQL_IDENTIFIER:
+ if (!IsAWordChar(sc.ch)) {
+ int nextState = SCE_SQL_DEFAULT;
+ char s[1000];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (keywords1.InList(s)) {
+ sc.ChangeState(SCE_SQL_WORD);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_SQL_WORD2);
+ } else if (kw_sqlplus.InListAbbreviated(s, '~')) {
+ sc.ChangeState(SCE_SQL_SQLPLUS);
+ if (strncmp(s, "rem", 3) == 0) {
+ nextState = SCE_SQL_SQLPLUS_COMMENT;
+ } else if (strncmp(s, "pro", 3) == 0) {
+ nextState = SCE_SQL_SQLPLUS_PROMPT;
}
- } else if (ch == '-' && chNext == '-') {
- state = SCE_SQL_COMMENTLINE;
- } else if (ch == '#') {
- state = SCE_SQL_COMMENTLINEDOC;
- } else if (ch == '\'') {
- state = SCE_SQL_CHARACTER;
- } else if (ch == '"') {
- state = SCE_SQL_STRING;
- } else if (ch == 0x60 && sqlBackticksIdentifier) {
- state = SCE_SQL_QUOTEDIDENTIFIER;
- } else if (isoperator(ch)) {
- styler.ColourTo(i, SCE_SQL_OPERATOR);
+ } else if (kw_user1.InList(s)) {
+ sc.ChangeState(SCE_SQL_USER1);
+ } else if (kw_user2.InList(s)) {
+ sc.ChangeState(SCE_SQL_USER2);
+ } else if (kw_user3.InList(s)) {
+ sc.ChangeState(SCE_SQL_USER3);
+ } else if (kw_user4.InList(s)) {
+ sc.ChangeState(SCE_SQL_USER4);
}
+ sc.SetState(nextState);
}
- } else {
- if (state == SCE_SQL_COMMENT) {
- if (ch == '/' && chPrev == '*') {
- if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_C_COMMENT) &&
- (styler.GetStartSegment() == startPos)))) {
- styler.ColourTo(i, state);
- state = SCE_SQL_DEFAULT;
- }
- }
- } else if (state == SCE_SQL_COMMENTDOC) {
- if (ch == '/' && chPrev == '*') {
- if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_SQL_COMMENTDOC) &&
- (styler.GetStartSegment() == startPos)))) {
- styler.ColourTo(i, state);
- state = SCE_SQL_DEFAULT;
- }
- } else if (ch == '@') {
- // Verify that we have the conditions to mark a comment-doc-keyword
- if ((IsASpace(chPrev) || chPrev == '*') && (!IsASpace(chNext))) {
- styler.ColourTo(i - 1, state);
- state = SCE_SQL_COMMENTDOCKEYWORD;
- }
- }
- } else if (state == SCE_SQL_COMMENTLINE || state == SCE_SQL_COMMENTLINEDOC || state == SCE_SQL_SQLPLUS_COMMENT) {
- if (ch == '\r' || ch == '\n') {
- styler.ColourTo(i - 1, state);
- state = SCE_SQL_DEFAULT;
- }
- } else if (state == SCE_SQL_COMMENTDOCKEYWORD) {
- if (ch == '/' && chPrev == '*') {
- styler.ColourTo(i - 1, SCE_SQL_COMMENTDOCKEYWORDERROR);
- state = SCE_SQL_DEFAULT;
- } else if (!iswordchar(ch)) {
- char s[100];
- getCurrent(styler.GetStartSegment(), i - 1, styler, s, 30);
- if (!kw_pldoc.InList(s + 1)) {
- state = SCE_SQL_COMMENTDOCKEYWORDERROR;
- }
- styler.ColourTo(i - 1, state);
- state = SCE_SQL_COMMENTDOC;
+ break;
+ case SCE_SQL_QUOTEDIDENTIFIER:
+ if (sc.ch == 0x60) {
+ if (sc.chNext == 0x60) {
+ sc.Forward(); // Ignore it
+ } else {
+ sc.ForwardSetState(SCE_SQL_DEFAULT);
}
- } else if (state == SCE_SQL_SQLPLUS_PROMPT) {
- if (ch == '\r' || ch == '\n') {
- styler.ColourTo(i - 1, state);
- state = SCE_SQL_DEFAULT;
+ }
+ break;
+ case SCE_SQL_COMMENT:
+ if (sc.Match('*', '/')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_SQL_DEFAULT);
+ }
+ break;
+ case SCE_SQL_COMMENTDOC:
+ if (sc.Match('*', '/')) {
+ sc.Forward();
+ sc.ForwardSetState(SCE_SQL_DEFAULT);
+ } else if (sc.ch == '@' || sc.ch == '\\') { // 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_SQL_COMMENTDOC;
+ sc.SetState(SCE_SQL_COMMENTDOCKEYWORD);
}
- } else if (state == SCE_SQL_CHARACTER) {
- if (sqlBackslashEscapes && ch == '\\') {
- i++;
- ch = chNext;
- chNext = styler.SafeGetCharAt(i + 1);
- } else if (ch == '\'') {
- if (chNext == '\'') {
- i++;
- } else {
- styler.ColourTo(i, state);
- state = SCE_SQL_DEFAULT;
- i++;
- }
- ch = chNext;
- chNext = styler.SafeGetCharAt(i + 1);
+ }
+ break;
+ case SCE_SQL_COMMENTLINE:
+ case SCE_SQL_COMMENTLINEDOC:
+ case SCE_SQL_SQLPLUS_COMMENT:
+ case SCE_SQL_SQLPLUS_PROMPT:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_SQL_DEFAULT);
+ }
+ break;
+ case SCE_SQL_COMMENTDOCKEYWORD:
+ if ((styleBeforeDCKeyword == SCE_SQL_COMMENTDOC) && sc.Match('*', '/')) {
+ sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR);
+ sc.Forward();
+ sc.ForwardSetState(SCE_SQL_DEFAULT);
+ } else if (!IsADoxygenChar(sc.ch)) {
+ char s[100];
+ sc.GetCurrentLowered(s, sizeof(s));
+ if (!isspace(sc.ch) || !kw_pldoc.InList(s + 1)) {
+ sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR);
}
- } else if (state == SCE_SQL_STRING) {
- if (ch == '"') {
- if (chNext == '"') {
- i++;
- } else {
- styler.ColourTo(i, state);
- state = SCE_SQL_DEFAULT;
- i++;
- }
- ch = chNext;
- chNext = styler.SafeGetCharAt(i + 1);
+ sc.SetState(styleBeforeDCKeyword);
+ }
+ break;
+ case SCE_SQL_CHARACTER:
+ if (sqlBackslashEscapes && sc.ch == '\\') {
+ sc.Forward();
+ } else if (sc.ch == '\'') {
+ if (sc.chNext == '\"') {
+ sc.Forward();
+ } else {
+ sc.ForwardSetState(SCE_SQL_DEFAULT);
}
- } else if (state == SCE_SQL_QUOTEDIDENTIFIER) {
- if (ch == 0x60) {
- if (chNext == 0x60) {
- i++;
- } else {
- styler.ColourTo(i, state);
- state = SCE_SQL_DEFAULT;
- i++;
- }
- ch = chNext;
- chNext = styler.SafeGetCharAt(i + 1);
+ }
+ break;
+ case SCE_SQL_STRING:
+ if (sc.ch == '\\') {
+ // Escape sequence
+ sc.Forward();
+ } else if (sc.ch == '\"') {
+ if (sc.chNext == '\"') {
+ sc.Forward();
+ } else {
+ sc.ForwardSetState(SCE_SQL_DEFAULT);
}
}
- if (state == SCE_SQL_DEFAULT) { // One of the above succeeded
- if (ch == '/' && chNext == '*') {
- if ((styler.SafeGetCharAt(i + 2)) == '*') { // Support of Doxygen doc. style
- state = SCE_SQL_COMMENTDOC;
- } else {
- state = SCE_SQL_COMMENT;
- }
- } else if (ch == '-' && chNext == '-') {
- state = SCE_SQL_COMMENTLINE;
- } else if (ch == '#') {
- state = SCE_SQL_COMMENTLINEDOC;
- } else if (MatchIgnoreCaseSubstring("rem~ark", styler, i)) {
- state = SCE_SQL_SQLPLUS_COMMENT;
- } else if (MatchIgnoreCaseSubstring("pro~mpt", styler, i)) {
- state = SCE_SQL_SQLPLUS_PROMPT;
- } else if (ch == '\'') {
- state = SCE_SQL_CHARACTER;
- } else if (ch == '"') {
- state = SCE_SQL_STRING;
- } else if (ch == 0x60 && sqlBackticksIdentifier) {
- state = SCE_SQL_QUOTEDIDENTIFIER;
- } else if (iswordstart(ch)) {
- state = SCE_SQL_WORD;
- } else if (isoperator(ch)) {
- styler.ColourTo(i, SCE_SQL_OPERATOR);
+ break;
+ }
+
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_SQL_DEFAULT) {
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+ sc.SetState(SCE_SQL_NUMBER);
+ } else if (IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_SQL_IDENTIFIER);
+ } else if (sc.ch == 0x60 && sqlBackticksIdentifier) {
+ sc.SetState(SCE_SQL_QUOTEDIDENTIFIER);
+ } else if (sc.Match('/', '*')) {
+ if (sc.Match("/**") || sc.Match("/*!")) { // Support of Doxygen doc. style
+ sc.SetState(SCE_SQL_COMMENTDOC);
+ } else {
+ sc.SetState(SCE_SQL_COMMENT);
}
+ sc.Forward(); // Eat the * so it isn't used for the end of the comment
+ } else if (sc.Match('-', '-')) {
+ // MySQL requires a space or control char after --
+ // http://dev.mysql.com/doc/mysql/en/ansi-diff-comments.html
+ // Perhaps we should enforce that with proper property:
+//~ } else if (sc.Match("-- ")) {
+ sc.SetState(SCE_SQL_COMMENTLINE);
+ } else if (sc.ch == '#') {
+ sc.SetState(SCE_SQL_COMMENTLINEDOC);
+ } else if (sc.ch == '\'') {
+ sc.SetState(SCE_SQL_CHARACTER);
+ } else if (sc.ch == '\"') {
+ sc.SetState(SCE_SQL_STRING);
+ } else if (isoperator(static_cast<char>(sc.ch))) {
+ sc.SetState(SCE_SQL_OPERATOR);
}
}
- chPrev = ch;
}
- styler.ColourTo(lengthDoc - 1, state);
+ sc.Complete();
}
static bool IsStreamCommentStyle(int style) {
@@ -332,18 +238,18 @@ static bool IsStreamCommentStyle(int style) {
}
// 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 {".
+// level store to make it easy to pick up with each increment.
static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
- WordList *[], Accessor &styler) {
+ 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 levelCurrent = SC_FOLDLEVELBASE;
- if (lineCurrent > 0)
- levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
+ if (lineCurrent > 0) {
+ levelCurrent = styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK;
+ }
int levelNext = levelCurrent;
char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos);
@@ -365,53 +271,80 @@ static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
}
}
if (foldComment && (style == SCE_SQL_COMMENTLINE)) {
+ // MySQL needs -- comments to be followed by space or control char
if ((ch == '-') && (chNext == '-')) {
char chNext2 = styler.SafeGetCharAt(i + 2);
- if (chNext2 == '{') {
+ char chNext3 = styler.SafeGetCharAt(i + 3);
+ if (chNext2 == '{' || chNext3 == '{') {
levelNext++;
- } else if (chNext2 == '}') {
+ } else if (chNext2 == '}' || chNext3 == '}') {
levelNext--;
}
}
}
- if (style == SCE_SQL_WORD) {
- if (MatchIgnoreCaseSubstring("elsif", styler, i)) {
- // ignore elsif
- i += 4;
- } else if (MatchIgnoreCaseSubstring("if", styler, i)
- || MatchIgnoreCaseSubstring("loop", styler, i)){
- if (endFound){
- // ignore
- endFound = false;
- } else {
- levelNext++;
- }
- } else if (MatchIgnoreCaseSubstring("begin", styler, i)){
+ if (style == SCE_SQL_OPERATOR) {
+ if (ch == '(') {
levelNext++;
- } else if (MatchIgnoreCaseSubstring("end", styler, i)) {
+ } else if (ch == ')') {
+ levelNext--;
+ }
+ }
+ // If new keyword (cannot trigger on elseif or nullif, does less tests)
+ if (style == SCE_SQL_WORD && stylePrev != SCE_SQL_WORD) {
+ const int MAX_KW_LEN = 6; // Maximum length of folding keywords
+ char s[MAX_KW_LEN + 2];
+ unsigned int j = 0;
+ for (; j < MAX_KW_LEN + 1; j++) {
+ if (!iswordchar(styler[i + j])) {
+ break;
+ }
+ s[j] = static_cast<char>(tolower(styler[i + j]));
+ }
+ if (j == MAX_KW_LEN + 1) {
+ // Keyword too long, don't test it
+ s[0] = '\0';
+ } else {
+ s[j] = '\0';
+ }
+ if (strcmp(s, "if") == 0 || strcmp(s, "loop") == 0) {
+ if (endFound) {
+ // ignore
+ endFound = false;
+ } else {
+ levelNext++;
+ }
+ } else if (strcmp(s, "begin") == 0) {
+ levelNext++;
+ } else if (strcmp(s, "end") == 0 ||
+ // DROP TABLE IF EXISTS or CREATE TABLE IF NOT EXISTS
+ strcmp(s, "exists") == 0) {
endFound = true;
levelNext--;
- if (levelNext < SC_FOLDLEVELBASE)
+ if (levelNext < SC_FOLDLEVELBASE) {
levelNext = SC_FOLDLEVELBASE;
+ }
}
}
if (atEOL) {
- 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);
+ int level = levelCurrent;
+ if (visibleChars == 0 && foldCompact) {
+ // Empty line
+ level |= SC_FOLDLEVELWHITEFLAG;
+ }
+ if (visibleChars > 0 && levelNext > levelCurrent) {
+ level |= SC_FOLDLEVELHEADERFLAG;
+ }
+ if (level != styler.LevelAt(lineCurrent)) {
+ styler.SetLevel(lineCurrent, level);
}
lineCurrent++;
levelCurrent = levelNext;
visibleChars = 0;
endFound = false;
}
- if (!isspacechar(ch))
+ if (!isspacechar(ch)) {
visibleChars++;
+ }
}
}