aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authornyamatongwe <unknown>2009-05-14 12:38:27 +0000
committernyamatongwe <unknown>2009-05-14 12:38:27 +0000
commitdbf6ed4d115282451b88844e8a8c75dccb9aec4a (patch)
tree655e5ba85b730eb189f54d8159b0e3fac99e44bf
parent56b8f2fb26d5c518712796a9832c3d43ea570c58 (diff)
downloadscintilla-mirror-dbf6ed4d115282451b88844e8a8c75dccb9aec4a.tar.gz
Updated MySQL lexer from Mike Lischke at Sun.
Adds SCE_MYSQL_HIDDENCOMMAND. List of keyword names terminated with 0.
-rw-r--r--include/SciLexer.h1
-rw-r--r--include/Scintilla.iface1
-rw-r--r--src/LexMySQL.cxx639
3 files changed, 381 insertions, 260 deletions
diff --git a/include/SciLexer.h b/include/SciLexer.h
index 56c9cbdc5..38f5d0de6 100644
--- a/include/SciLexer.h
+++ b/include/SciLexer.h
@@ -1270,6 +1270,7 @@
#define SCE_MYSQL_USER1 18
#define SCE_MYSQL_USER2 19
#define SCE_MYSQL_USER3 20
+#define SCE_MYSQL_HIDDENCOMMAND 21
#define SCE_PO_DEFAULT 0
#define SCE_PO_COMMENT 1
#define SCE_PO_MSGID 2
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index 9c9eeb1be..97cf8ac16 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -3450,6 +3450,7 @@ val SCE_MYSQL_QUOTEDIDENTIFIER=17
val SCE_MYSQL_USER1=18
val SCE_MYSQL_USER2=19
val SCE_MYSQL_USER3=20
+val SCE_MYSQL_HIDDENCOMMAND=21
# Lexical state for SCLEX_PO
lex Po=SCLEX_PO SCE_PO_
val SCE_PO_DEFAULT=0
diff --git a/src/LexMySQL.cxx b/src/LexMySQL.cxx
index 742ff4339..b6d7135b1 100644
--- a/src/LexMySQL.cxx
+++ b/src/LexMySQL.cxx
@@ -1,11 +1,14 @@
-// Scintilla source code edit control
-/** @file LexMySQL.cxx
- ** Lexer for MySQL
- **/
-// Adopted from LexSQL.cxx by Anders Karlsson <anders@mysql.com>
-// Original work 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.
+/**
+ * Scintilla source code edit control
+ * @file LexMySQL.cxx
+ * Lexer for MySQL
+ *
+ * Improved by Mike Lischke <mike.lischke@sun.com>
+ * Adopted from LexSQL.cxx by Anders Karlsson <anders@mysql.com>
+ * Original work 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>
#include <string.h>
@@ -49,287 +52,400 @@ static inline bool IsANumberChar(int ch) {
ch == '.' || ch == '-' || ch == '+');
}
-static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
- Accessor &styler) {
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Check if the current content context represent a keyword and set the context state if so.
+ */
+static void CheckForKeyword(StyleContext& sc, WordList* keywordlists[])
+{
+ int length = sc.LengthCurrent() + 1; // +1 for the next char
+ char* s = new char[length];
+ sc.GetCurrentLowered(s, length);
+ if (keywordlists[0]->InList(s))
+ sc.ChangeState(SCE_MYSQL_MAJORKEYWORD);
+ else
+ if (keywordlists[1]->InList(s))
+ sc.ChangeState(SCE_MYSQL_KEYWORD);
+ else
+ if (keywordlists[2]->InList(s))
+ sc.ChangeState(SCE_MYSQL_DATABASEOBJECT);
+ else
+ if (keywordlists[3]->InList(s))
+ sc.ChangeState(SCE_MYSQL_FUNCTION);
+ else
+ if (keywordlists[5]->InList(s))
+ sc.ChangeState(SCE_MYSQL_PROCEDUREKEYWORD);
+ else
+ if (keywordlists[6]->InList(s))
+ sc.ChangeState(SCE_MYSQL_USER1);
+ else
+ if (keywordlists[7]->InList(s))
+ sc.ChangeState(SCE_MYSQL_USER2);
+ else
+ if (keywordlists[8]->InList(s))
+ sc.ChangeState(SCE_MYSQL_USER3);
+ delete [] s;
+}
- WordList &major_keywords = *keywordlists[0];
- WordList &keywords = *keywordlists[1];
- WordList &database_objects = *keywordlists[2];
- WordList &functions = *keywordlists[3];
- WordList &system_variables = *keywordlists[4];
- WordList &procedure_keywords = *keywordlists[5];
- WordList &kw_user1 = *keywordlists[6];
- WordList &kw_user2 = *keywordlists[7];
- WordList &kw_user3 = *keywordlists[8];
+//--------------------------------------------------------------------------------------------------
+static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+ Accessor &styler)
+{
StyleContext sc(startPos, length, initStyle, styler);
- for (; sc.More(); sc.Forward()) {
+ for (; sc.More(); sc.Forward())
+ {
// Determine if the current state should terminate.
- switch (sc.state) {
- case SCE_MYSQL_OPERATOR:
- sc.SetState(SCE_MYSQL_DEFAULT);
- break;
- case SCE_MYSQL_NUMBER:
- // We stop the number definition on non-numerical non-dot non-eE non-sign char
- if (!IsANumberChar(sc.ch)) {
- sc.SetState(SCE_MYSQL_DEFAULT);
- }
- break;
- case SCE_MYSQL_IDENTIFIER:
- if (!IsAWordChar(sc.ch)) {
- int nextState = SCE_MYSQL_DEFAULT;
- char s[1000];
- sc.GetCurrentLowered(s, sizeof(s));
- if (major_keywords.InList(s)) {
- sc.ChangeState(SCE_MYSQL_MAJORKEYWORD);
- } else if (keywords.InList(s)) {
- sc.ChangeState(SCE_MYSQL_KEYWORD);
- } else if (database_objects.InList(s)) {
- sc.ChangeState(SCE_MYSQL_DATABASEOBJECT);
- } else if (functions.InList(s)) {
- sc.ChangeState(SCE_MYSQL_FUNCTION);
- } else if (procedure_keywords.InList(s)) {
- sc.ChangeState(SCE_MYSQL_PROCEDUREKEYWORD);
- } else if (kw_user1.InList(s)) {
- sc.ChangeState(SCE_MYSQL_USER1);
- } else if (kw_user2.InList(s)) {
- sc.ChangeState(SCE_MYSQL_USER2);
- } else if (kw_user3.InList(s)) {
- sc.ChangeState(SCE_MYSQL_USER3);
- }
- sc.SetState(nextState);
- }
- break;
- case SCE_MYSQL_VARIABLE:
- if (!IsAWordChar(sc.ch)) {
- sc.SetState(SCE_MYSQL_DEFAULT);
- }
- break;
- case SCE_MYSQL_SYSTEMVARIABLE:
- if (!IsAWordChar(sc.ch)) {
- char s[1000];
- sc.GetCurrentLowered(s, sizeof(s));
-// Check for known system variables here.
- if (system_variables.InList(&s[2])) {
- sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE);
- }
- sc.SetState(SCE_MYSQL_DEFAULT);
- }
- break;
- case SCE_MYSQL_QUOTEDIDENTIFIER:
- if (sc.ch == 0x60) {
- if (sc.chNext == 0x60) {
- sc.Forward(); // Ignore it
- } else {
- sc.ForwardSetState(SCE_MYSQL_DEFAULT);
- }
- }
- break;
- case SCE_MYSQL_COMMENT:
- if (sc.Match('*', '/')) {
- sc.Forward();
- sc.ForwardSetState(SCE_MYSQL_DEFAULT);
- }
- break;
- case SCE_MYSQL_COMMENTLINE:
- if (sc.atLineStart) {
- sc.SetState(SCE_MYSQL_DEFAULT);
- }
- break;
- case SCE_MYSQL_SQSTRING:
- if (sc.ch == '\\') {
- // Escape sequence
- sc.Forward();
- } else if (sc.ch == '\'') {
- if (sc.chNext == '\'') {
- sc.Forward();
- } else {
- sc.ChangeState(SCE_MYSQL_STRING);
- sc.ForwardSetState(SCE_MYSQL_DEFAULT);
- }
- }
- break;
- case SCE_MYSQL_DQSTRING:
- if (sc.ch == '\\') {
- // Escape sequence
- sc.Forward();
- } else if (sc.ch == '\"') {
- if (sc.chNext == '\"') {
- sc.Forward();
- } else {
- sc.ChangeState(SCE_MYSQL_STRING);
- sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ switch (sc.state)
+ {
+ case SCE_MYSQL_OPERATOR:
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ break;
+ case SCE_MYSQL_NUMBER:
+ // We stop the number definition on non-numerical non-dot non-eE non-sign char.
+ if (!IsANumberChar(sc.ch))
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ break;
+ case SCE_MYSQL_IDENTIFIER:
+ // Switch from identifier to keyword state and open a new state for the new char.
+ if (!IsAWordChar(sc.ch))
+ {
+ CheckForKeyword(sc, keywordlists);
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ }
+ break;
+ case SCE_MYSQL_VARIABLE:
+ if (!IsAWordChar(sc.ch))
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ break;
+ case SCE_MYSQL_SYSTEMVARIABLE:
+ if (!IsAWordChar(sc.ch))
+ {
+ int length = sc.LengthCurrent() + 1;
+ char* s = new char[length];
+ sc.GetCurrentLowered(s, length);
+
+ // Check for known system variables here.
+ if (keywordlists[4]->InList(&s[2]))
+ sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE);
+ delete [] s;
+
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ }
+ break;
+ case SCE_MYSQL_QUOTEDIDENTIFIER:
+ if (sc.ch == '`')
+ {
+ if (sc.chNext == '`')
+ sc.Forward(); // Ignore it
+ else
+ sc.ForwardSetState(SCE_MYSQL_DEFAULT);
}
- }
- break;
- }
+ break;
+ case SCE_MYSQL_COMMENT:
+ case SCE_MYSQL_HIDDENCOMMAND:
+ if (sc.Match('*', '/'))
+ {
+ sc.Forward();
+ sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ }
+ break;
+ case SCE_MYSQL_COMMENTLINE:
+ if (sc.atLineStart)
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ break;
+ case SCE_MYSQL_SQSTRING:
+ if (sc.ch == '\\')
+ sc.Forward(); // Escape sequence
+ else
+ if (sc.ch == '\'')
+ {
+ // End of single quoted string reached?
+ if (sc.chNext == '\'')
+ sc.Forward();
+ else
+ sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ }
+ break;
+ case SCE_MYSQL_DQSTRING:
+ if (sc.ch == '\\')
+ sc.Forward(); // Escape sequence
+ else
+ if (sc.ch == '\"')
+ {
+ // End of single quoted string reached?
+ if (sc.chNext == '\"')
+ sc.Forward();
+ else
+ sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ }
+ break;
+ }
- // Determine if a new state should be entered.
- if (sc.state == SCE_MYSQL_DEFAULT) {
- if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
- sc.SetState(SCE_MYSQL_NUMBER);
- } else if (IsAWordStart(sc.ch)) {
- sc.SetState(SCE_MYSQL_IDENTIFIER);
-// Note that the order of SYSTEMVARIABLE and VARIABLE is important here.
- } else if (sc.ch == 0x40 && sc.chNext == 0x40) {
- sc.SetState(SCE_MYSQL_SYSTEMVARIABLE);
- sc.Forward(); // Skip past the second at-sign.
- } else if (sc.ch == 0x40) {
- sc.SetState(SCE_MYSQL_VARIABLE);
- } else if (sc.ch == 0x60) {
- sc.SetState(SCE_MYSQL_QUOTEDIDENTIFIER);
- } else if (sc.Match('/', '*')) {
- sc.SetState(SCE_MYSQL_COMMENT);
- sc.Forward(); // Eat the * so it isn't used for the end of the comment
- } else if (sc.Match('-', '-') || sc.Match('#')) {
- sc.SetState(SCE_MYSQL_COMMENTLINE);
- } else if (sc.ch == '\'') {
- sc.SetState(SCE_MYSQL_SQSTRING);
- } else if (sc.ch == '\"') {
- sc.SetState(SCE_MYSQL_DQSTRING);
- } else if (isoperator(static_cast<char>(sc.ch))) {
- sc.SetState(SCE_MYSQL_OPERATOR);
- }
- }
- }
- sc.Complete();
+ // Determine if a new state should be entered.
+ if (sc.state == SCE_MYSQL_DEFAULT)
+ {
+ switch (sc.ch)
+ {
+ case '@':
+ if (sc.chNext == '@')
+ {
+ sc.SetState(SCE_MYSQL_SYSTEMVARIABLE);
+ sc.Forward(2); // Skip past @@.
+ }
+ else
+ if (IsAWordStart(sc.ch))
+ {
+ sc.SetState(SCE_MYSQL_VARIABLE);
+ sc.Forward(); // Skip past @.
+ }
+ else
+ sc.SetState(SCE_MYSQL_OPERATOR);
+ break;
+ case '`':
+ sc.SetState(SCE_MYSQL_QUOTEDIDENTIFIER);
+ break;
+ case '#':
+ sc.SetState(SCE_MYSQL_COMMENTLINE);
+ break;
+ case '\'':
+ sc.SetState(SCE_MYSQL_SQSTRING);
+ break;
+ case '\"':
+ sc.SetState(SCE_MYSQL_DQSTRING);
+ break;
+ default:
+ if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)))
+ sc.SetState(SCE_MYSQL_NUMBER);
+ else
+ if (IsAWordStart(sc.ch))
+ sc.SetState(SCE_MYSQL_IDENTIFIER);
+ else
+ if (sc.Match('/', '*'))
+ {
+ sc.SetState(SCE_MYSQL_COMMENT);
+
+ // Skip comment introducer and check for hidden command.
+ sc.Forward(2);
+ if (sc.ch == '!')
+ {
+ sc.ChangeState(SCE_MYSQL_HIDDENCOMMAND);
+ sc.Forward();
+ }
+ }
+ else
+ if (sc.Match("--"))
+ {
+ // Special MySQL single line comment.
+ sc.SetState(SCE_MYSQL_COMMENTLINE);
+ sc.Forward(2);
+
+ // Check the third character too. It must be a space or EOL.
+ if (sc.ch != ' ' && sc.ch != '\n' && sc.ch != '\r')
+ sc.ChangeState(SCE_MYSQL_OPERATOR);
+ }
+ else
+ if (isoperator(static_cast<char>(sc.ch)))
+ sc.SetState(SCE_MYSQL_OPERATOR);
+ }
+ }
+ }
+
+ // Do a final check for keywords if we currently have an identifier, to highlight them
+ // also at the end of a line.
+ if (sc.state == SCE_MYSQL_IDENTIFIER)
+ CheckForKeyword(sc, keywordlists);
+
+ sc.Complete();
}
-static bool IsStreamCommentStyle(int style) {
+//--------------------------------------------------------------------------------------------------
+
+/**
+ * Helper function to determine if we have a foldable comment currently.
+ */
+static bool IsStreamCommentStyle(int style)
+{
return style == SCE_MYSQL_COMMENT;
}
+//--------------------------------------------------------------------------------------------------
+
// 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(unsigned int startPos, int length, int initStyle,
- WordList *[], Accessor &styler) {
+static void FoldMySQLDoc(unsigned int startPos, int 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;
- unsigned int endPos = startPos + length;
+ StyleContext sc(startPos, length, initStyle, styler);
+
int visibleChars = 0;
int lineCurrent = styler.GetLine(startPos);
int levelCurrent = SC_FOLDLEVELBASE;
- if (lineCurrent > 0) {
+ if (lineCurrent > 0)
levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16;
- }
int levelNext = levelCurrent;
- char chNext = styler[startPos];
+
int styleNext = styler.StyleAt(startPos);
int style = initStyle;
- bool endFound = false;
+
+ bool endFound = false;
bool whenFound = false;
bool elseFound = false;
- for (unsigned int i = startPos; i < endPos; i++) {
- char ch = chNext;
- chNext = styler.SafeGetCharAt(i + 1);
+
+ for (unsigned int i = startPos; sc.More(); i++, sc.Forward())
+ {
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)) {
- levelNext++;
- } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
- // Comments don't end at end of line and the next character may be unstyled.
- levelNext--;
- }
- }
- if (foldComment && (style == SCE_MYSQL_COMMENTLINE)) {
- // MySQL needs -- comments to be followed by space or control char
- if ((ch == '-') && (chNext == '-')) {
- char chNext2 = styler.SafeGetCharAt(i + 2);
- char chNext3 = styler.SafeGetCharAt(i + 3);
- if (chNext2 == '{' || chNext3 == '{') {
- levelNext++;
- } else if (chNext2 == '}' || chNext3 == '}') {
- levelNext--;
- }
- }
- }
- if (style == SCE_MYSQL_OPERATOR) {
- if (ch == '(') {
- levelNext++;
- } else if (ch == ')') {
- levelNext--;
- }
- }
-
-// Style new keywords here.
- if ((style == SCE_MYSQL_MAJORKEYWORD && stylePrev != SCE_MYSQL_MAJORKEYWORD)
- || (style == SCE_MYSQL_KEYWORD && stylePrev != SCE_MYSQL_KEYWORD)
- || (style == SCE_MYSQL_PROCEDUREKEYWORD && stylePrev != SCE_MYSQL_PROCEDUREKEYWORD)) {
- 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 (!foldOnlyBegin && endFound && (strcmp(s, "if") == 0 || strcmp(s, "while") == 0 || strcmp(s, "loop") == 0)) {
- endFound = false;
- levelNext--;
- if (levelNext < SC_FOLDLEVELBASE) {
- levelNext = SC_FOLDLEVELBASE;
- }
-// Note that else is special here. It may or may be followed by an if then, but in aly case the level stays the
-// same. When followed by a if .. then, the level will be increased later, if not, at eol.
- } else if (!foldOnlyBegin && strcmp(s, "else") == 0) {
- levelNext--;
- elseFound = true;
- } else if (!foldOnlyBegin && strcmp(s, "then") == 0) {
- if(whenFound) {
- whenFound = false;
- } else {
- levelNext++;
- }
- } else if (strcmp(s, "if") == 0) {
- elseFound = false;
- } else if (strcmp(s, "when") == 0) {
- whenFound = true;
- } else if (strcmp(s, "begin") == 0) {
- levelNext++;
- } else if (!foldOnlyBegin && (strcmp(s, "loop") == 0 || strcmp(s, "repeat") == 0
- || strcmp(s, "while") == 0)) {
- if(endFound) {
- endFound = false;
- } else {
- levelNext++;
- }
- } else if (strcmp(s, "end") == 0) {
-// Multiple END in a row are counted multiple times!
- if (endFound) {
- levelNext--;
- if (levelNext < SC_FOLDLEVELBASE) {
- levelNext = SC_FOLDLEVELBASE;
- }
- }
- endFound = true;
- whenFound = false;
- }
- }
-// Handle this for a trailing end withiut an if / while etc, as in the case of a begin.
- if (endFound) {
+ bool atEOL = (sc.ch == '\r' && sc.chNext != '\n') || (sc.ch == '\n');
+
+ switch (style)
+ {
+ case SCE_MYSQL_COMMENT:
+ if (foldComment)
+ {
+ // Multiline comment style /* .. */.
+ if (IsStreamCommentStyle(style))
+ {
+ // Increase level if we just start a foldable comment.
+ if (!IsStreamCommentStyle(stylePrev))
+ levelNext++;
+ else
+ // If we are in the middle of a foldable comment check if it ends now.
+ // Don't end at the line end, though.
+ if (!IsStreamCommentStyle(styleNext) && !atEOL)
+ 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 (sc.Match('-', '-'))
+ {
+ 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 (style != stylePrev)
+ levelNext++;
+ else
+ if (style != styleNext)
+ levelNext--;
+ break;
+ case SCE_MYSQL_OPERATOR:
+ if (sc.ch == '(')
+ levelNext++;
+ else
+ if (sc.ch == ')')
+ levelNext--;
+ break;
+ case SCE_MYSQL_MAJORKEYWORD:
+ case SCE_MYSQL_KEYWORD:
+ case SCE_MYSQL_FUNCTION:
+ case SCE_MYSQL_PROCEDUREKEYWORD:
+ // Reserved and other keywords.
+ if (style != stylePrev)
+ {
+ bool beginFound = sc.MatchIgnoreCase("begin");
+ bool ifFound = sc.MatchIgnoreCase("if");
+ bool thenFound = sc.MatchIgnoreCase("then");
+ bool whileFound = sc.MatchIgnoreCase("while");
+ bool loopFound = sc.MatchIgnoreCase("loop");
+ bool repeatFound = sc.MatchIgnoreCase("repeat");
+
+ if (!foldOnlyBegin && endFound && (ifFound || whileFound || loopFound))
+ {
+ endFound = false;
+ levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
+
+ // Note that "else" is special here. It may or may not be followed by an "if .. then",
+ // but in any case the level stays the same. When followed by an "if .. then" the level
+ // will be increased later, if not, then at eol.
+ }
+ else
+ if (!foldOnlyBegin && sc.MatchIgnoreCase("else"))
+ {
+ levelNext--;
+ elseFound = true;
+ }
+ else
+ if (!foldOnlyBegin && thenFound)
+ {
+ if (whenFound)
+ whenFound = false;
+ else
+ levelNext++;
+ }
+ else
+ if (ifFound)
+ elseFound = false;
+ else
+ if (sc.MatchIgnoreCase("when"))
+ whenFound = true;
+ else
+ {
+ if (beginFound)
+ levelNext++;
+ else
+ if (!foldOnlyBegin && (loopFound || repeatFound || whileFound))
+ {
+ if (endFound)
+ endFound = false;
+ else
+ levelNext++;
+ }
+ else
+ if (sc.MatchIgnoreCase("end"))
+ {
+ // Multiple "end" in a row are counted multiple times!
+ if (endFound)
+ {
+ levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
+ }
+ endFound = true;
+ whenFound = false;
+ }
+ }
+ }
+ break;
+ }
+
+ // Handle the case of a trailing end without an if / while etc, as in the case of a begin.
+ if (endFound)
+ {
endFound = false;
levelNext--;
- if (levelNext < SC_FOLDLEVELBASE) {
- levelNext = SC_FOLDLEVELBASE;
- }
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
}
- if (atEOL) {
- if(elseFound)
+
+ if (atEOL)
+ {
+ if (elseFound)
+ {
levelNext++;
- elseFound = false;
+ elseFound = false;
+ }
int levelUse = levelCurrent;
int lev = levelUse | levelNext << 16;
@@ -337,21 +453,23 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle,
lev |= SC_FOLDLEVELWHITEFLAG;
if (levelUse < levelNext)
lev |= SC_FOLDLEVELHEADERFLAG;
- if (lev != styler.LevelAt(lineCurrent)) {
+ if (lev != styler.LevelAt(lineCurrent))
styler.SetLevel(lineCurrent, lev);
- }
+
lineCurrent++;
levelCurrent = levelNext;
visibleChars = 0;
endFound = false;
whenFound = false;
}
- if (!isspacechar(ch)) {
+
+ if (!isspacechar(static_cast<char>(sc.ch)))
visibleChars++;
- }
}
}
+//--------------------------------------------------------------------------------------------------
+
static const char * const mysqlWordListDesc[] = {
"Major Keywords",
"Keywords",
@@ -361,7 +479,8 @@ static const char * const mysqlWordListDesc[] = {
"Procedure keywords",
"User Keywords 1",
"User Keywords 2",
- "User Keywords 3"
+ "User Keywords 3",
+ 0
};
LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc);