diff options
-rw-r--r-- | include/KeyWords.h | 23 | ||||
-rw-r--r-- | include/SciLexer.h | 1 | ||||
-rw-r--r-- | include/Scintilla.h | 1 | ||||
-rw-r--r-- | include/Scintilla.iface | 6 | ||||
-rw-r--r-- | src/KeyWords.cxx | 64 | ||||
-rw-r--r-- | src/LexCPP.cxx | 3 | ||||
-rw-r--r-- | src/ScintillaBase.cxx | 31 | ||||
-rw-r--r-- | src/ScintillaBase.h | 3 |
8 files changed, 111 insertions, 21 deletions
diff --git a/include/KeyWords.h b/include/KeyWords.h index d589d1228..43de26fe6 100644 --- a/include/KeyWords.h +++ b/include/KeyWords.h @@ -9,17 +9,30 @@ typedef void (*LexerFunction)(unsigned int startPos, int lengthDoc, int initStyl WordList *keywordlists[], Accessor &styler); /** + * A LexerModule is responsible for lexing and folding a particular language. + * The class maintains a list of LexerModules which can be searched to find a + * module appropriate to a particular language. */ class LexerModule { - static LexerModule *base; LexerModule *next; int language; - LexerFunction fn; + const char *languageName; + LexerFunction fnLexer; + LexerFunction fnFolder; + + static LexerModule *base; + static int nextLanguage; public: - LexerModule(int language_, LexerFunction fn_); - static void Colourise(unsigned int startPos, int lengthDoc, int initStyle, - int language, WordList *keywordlists[], Accessor &styler); + LexerModule(int language_, LexerFunction fnLexer_, + const char *languageName_=0, LexerFunction fnFolder_=0); + int GetLanguage() { return language; } + void Lex(unsigned int startPos, int lengthDoc, int initStyle, + WordList *keywordlists[], Accessor &styler); + void Fold(unsigned int startPos, int lengthDoc, int initStyle, + WordList *keywordlists[], Accessor &styler); + static LexerModule *Find(int language); + static LexerModule *Find(const char *languageName); }; /** diff --git a/include/SciLexer.h b/include/SciLexer.h index 88e8b954b..9274b31de 100644 --- a/include/SciLexer.h +++ b/include/SciLexer.h @@ -35,6 +35,7 @@ #define SCLEX_PASCAL 18 #define SCLEX_AVE 19 #define SCLEX_ADA 20 +#define SCLEX_AUTOMATIC 1000 #define SCE_P_DEFAULT 0 #define SCE_P_COMMENTLINE 1 #define SCE_P_NUMBER 2 diff --git a/include/Scintilla.h b/include/Scintilla.h index fa1003ab4..54c02de47 100644 --- a/include/Scintilla.h +++ b/include/Scintilla.h @@ -411,6 +411,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_COLOURISE 4003 #define SCI_SETPROPERTY 4004 #define SCI_SETKEYWORDS 4005 +#define SCI_SETLEXERLANGUAGE 4006 #define SC_MOD_INSERTTEXT 0x1 #define SC_MOD_DELETETEXT 0x2 #define SC_MOD_CHANGESTYLE 0x4 diff --git a/include/Scintilla.iface b/include/Scintilla.iface index 97f183ffc..be9468184 100644 --- a/include/Scintilla.iface +++ b/include/Scintilla.iface @@ -1102,6 +1102,9 @@ set void SetProperty=4004(string key, string value) # Set up the key words used by the lexer. set void SetKeyWords=4005(int keywordSet, string keyWords) +# Set the lexing language of the document based on string name. +set void SetLexerLanguage=4006(, string language) + # Notifications # Type of modification and the action which caused the modification # These are defined as a bit mask to make it easy to specify which notifications are wanted. @@ -1174,6 +1177,9 @@ val SCLEX_CONF=17 val SCLEX_PASCAL=18 val SCLEX_AVE=19 val SCLEX_ADA=20 +# When a lexer specifies its language as SCLEX_AUTOMATIC it receives a +# value assigned in sequence from SCLEX_AUTOMATIC+1. +val SCLEX_AUTOMATIC=1000 # Lexical states for SCLEX_PYTHON val SCE_P_DEFAULT=0 val SCE_P_COMMENTLINE=1 diff --git a/src/KeyWords.cxx b/src/KeyWords.cxx index a275c1963..f28fcecfb 100644 --- a/src/KeyWords.cxx +++ b/src/KeyWords.cxx @@ -20,32 +20,70 @@ #include "SciLexer.h" LexerModule *LexerModule::base = 0; +int LexerModule::nextLanguage = SCLEX_AUTOMATIC+1; -LexerModule::LexerModule(int language_, LexerFunction fn_) : - language(language_), fn(fn_) { +LexerModule::LexerModule(int language_, LexerFunction fnLexer_, + const char *languageName_, LexerFunction fnFolder_) : + language(language_), + languageName(languageName_), + fnLexer(fnLexer_), + fnFolder(fnFolder_) { next = base; base = this; + if (language == SCLEX_AUTOMATIC) { + language = nextLanguage; + nextLanguage++; + } } -void LexerModule::Colourise(unsigned int startPos, int lengthDoc, int initStyle, - int language, WordList *keywordlists[], Accessor &styler) { +LexerModule *LexerModule::Find(int language) { LexerModule *lm = base; while (lm) { if (lm->language == language) { - lm->fn(startPos, lengthDoc, initStyle, keywordlists, styler); - return; + return lm; } lm = lm->next; } - // Unknown language + return 0; +} + +LexerModule *LexerModule::Find(const char *languageName) { + if (languageName) { + LexerModule *lm = base; + while (lm) { + if (lm->languageName && 0 == strcmp(lm->languageName, languageName)) { + return lm; + } + lm = lm->next; + } + } + return 0; +} + +void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle, + WordList *keywordlists[], Accessor &styler) { + if (fnLexer) + fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler); +} + +void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle, + WordList *keywordlists[], Accessor &styler) { + if (fnFolder) + fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler); +} + +static void ColouriseNullDoc(unsigned int startPos, int length, int, WordList *[], + Accessor &styler) { // Null language means all style bytes are 0 so just mark the end - no need to fill in. - if (lengthDoc > 0) { - styler.StartAt(startPos + lengthDoc - 1); - styler.StartSegment(startPos + lengthDoc - 1); - styler.ColourTo(startPos + lengthDoc - 1, 0); + if (length > 0) { + styler.StartAt(startPos + length - 1); + styler.StartSegment(startPos + length - 1); + styler.ColourTo(startPos + length - 1, 0); } } +LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null"); + #ifdef __vms // The following code forces a reference to all of the Scintilla lexers. @@ -55,6 +93,7 @@ void LexerModule::Colourise(unsigned int startPos, int lengthDoc, int initStyle, // Taken from wxWindow's stc.cpp. Walter. int wxForceScintillaLexers(void) { + extern LexerModule lmAda; extern LexerModule lmCPP; extern LexerModule lmHTML; extern LexerModule lmXML; @@ -68,7 +107,8 @@ int wxForceScintillaLexers(void) { extern LexerModule lmVB; if ( - &lmCPP + &lmAda + && &lmCPP && &lmHTML && &lmXML && &lmProps diff --git a/src/LexCPP.cxx b/src/LexCPP.cxx index 966601ed3..826ac259f 100644 --- a/src/LexCPP.cxx +++ b/src/LexCPP.cxx @@ -328,7 +328,6 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo } styler.ColourTo(lengthDoc - 1, state); styler.Flush(); - FoldCppDoc(startPos, length, initStyle, keywordlists, styler); } -LexerModule lmCPP(SCLEX_CPP, ColouriseCppDoc); +LexerModule lmCPP(SCLEX_CPP, ColouriseCppDoc, "cpp", FoldCppDoc); diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx index fd2bef184..4eb0cf7a0 100644 --- a/src/ScintillaBase.cxx +++ b/src/ScintillaBase.cxx @@ -38,6 +38,7 @@ ScintillaBase::ScintillaBase() { listType = 0; #ifdef SCI_LEXER lexLanguage = SCLEX_CONTAINER; + lexCurrent = 0; for (int wl = 0;wl < numWordLists;wl++) keyWordLists[wl] = new WordList; #endif @@ -338,6 +339,22 @@ void ScintillaBase::ButtonDown(Point pt, unsigned int curTime, bool shift, bool } #ifdef SCI_LEXER +void ScintillaBase::SetLexer(uptr_t wParam) { + lexLanguage = wParam; + lexCurrent = LexerModule::Find(lexLanguage); + if (!lexCurrent) + lexCurrent = LexerModule::Find(SCLEX_NULL); +} + +void ScintillaBase::SetLexerLanguage(const char *languageName) { + lexLanguage = SCLEX_CONTAINER; + lexCurrent = LexerModule::Find(languageName); + if (!lexCurrent) + lexCurrent = LexerModule::Find(SCLEX_NULL); + if (lexCurrent) + lexLanguage = lexCurrent->GetLanguage(); +} + void ScintillaBase::Colourise(int start, int end) { int lengthDoc = pdoc->Length(); if (end == -1) @@ -352,8 +369,12 @@ void ScintillaBase::Colourise(int start, int end) { styleStart = styler.StyleAt(start - 1); styler.SetCodePage(pdoc->dbcsCodePage); - LexerModule::Colourise(start, len, styleStart, lexLanguage, keyWordLists, styler); - styler.Flush(); + if (lexCurrent) { // Should always succeed as null lexer should always be available + lexCurrent->Lex(start, len, styleStart, keyWordLists, styler); + styler.Flush(); + lexCurrent->Fold(start, len, styleStart, keyWordLists, styler); + styler.Flush(); + } } #endif @@ -482,6 +503,7 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara #ifdef SCI_LEXER case SCI_SETLEXER: + SetLexer(wParam); lexLanguage = wParam; break; @@ -504,6 +526,11 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara keyWordLists[wParam]->Set(reinterpret_cast<const char *>(lParam)); } break; + + case SCI_SETLEXERLANGUAGE: + SetLexerLanguage(reinterpret_cast<const char *>(lParam)); + break; + #endif default: diff --git a/src/ScintillaBase.h b/src/ScintillaBase.h index 758f75a4c..13172031a 100644 --- a/src/ScintillaBase.h +++ b/src/ScintillaBase.h @@ -40,9 +40,12 @@ protected: #ifdef SCI_LEXER int lexLanguage; + LexerModule *lexCurrent; PropSet props; enum {numWordLists=5}; WordList *keyWordLists[numWordLists]; + void SetLexer(uptr_t wParam); + void SetLexerLanguage(const char *languageName); void Colourise(int start, int end); #endif |