1 // Scintilla source code edit control
\r
2 /** @file ExternalLexer.cxx
\r
3 ** Support external lexers in DLLs.
\r
5 // Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
\r
6 // The License.txt file describes the conditions under which this software may be distributed.
\r
13 #include "Platform.h"
\r
15 #include "Scintilla.h"
\r
17 #include "SciLexer.h"
\r
18 #include "PropSet.h"
\r
19 #include "Accessor.h"
\r
20 #include "DocumentAccessor.h"
\r
21 #include "KeyWords.h"
\r
22 #include "ExternalLexer.h"
\r
24 #ifdef SCI_NAMESPACE
\r
25 using namespace Scintilla;
\r
28 LexerManager *LexerManager::theInstance = NULL;
\r
30 //------------------------------------------
\r
32 // ExternalLexerModule
\r
34 //------------------------------------------
\r
36 char **WordListsToStrings(WordList *val[]) {
\r
40 char **wls = new char * [dim + 1];
\r
41 for (int i = 0;i < dim;i++) {
\r
44 for (int n = 0; n < val[i]->len; n++) {
\r
45 words += val[i]->words[n];
\r
46 if (n != val[i]->len - 1)
\r
49 wls[i] = new char[words.length() + 1];
\r
50 strcpy(wls[i], words.c_str());
\r
56 void DeleteWLStrings(char *strs[]) {
\r
65 void ExternalLexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
\r
66 WordList *keywordlists[], Accessor &styler) const {
\r
70 char **kwds = WordListsToStrings(keywordlists);
\r
71 char *ps = styler.GetProperties();
\r
73 // The accessor passed in is always a DocumentAccessor so this cast and the subsequent
\r
74 // access will work. Can not use the stricter dynamic_cast as that requires RTTI.
\r
75 DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
\r
76 WindowID wID = da.GetWindow();
\r
78 fneLexer(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
\r
81 DeleteWLStrings(kwds);
\r
84 void ExternalLexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
\r
85 WordList *keywordlists[], Accessor &styler) const {
\r
89 char **kwds = WordListsToStrings(keywordlists);
\r
90 char *ps = styler.GetProperties();
\r
92 // The accessor passed in is always a DocumentAccessor so this cast and the subsequent
\r
93 // access will work. Can not use the stricter dynamic_cast as that requires RTTI.
\r
94 DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
\r
95 WindowID wID = da.GetWindow();
\r
97 fneFolder(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
\r
100 DeleteWLStrings(kwds);
\r
103 void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index) {
\r
105 fneFolder = fFolder;
\r
106 externalLanguage = index;
\r
109 //------------------------------------------
\r
113 //------------------------------------------
\r
115 LexerLibrary::LexerLibrary(const char* ModuleName) {
\r
116 // Initialise some members...
\r
121 lib = DynamicLibrary::Load(ModuleName);
\r
122 if (lib->IsValid()) {
\r
123 m_sModuleName = ModuleName;
\r
124 //Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
\r
125 GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount");
\r
127 if (GetLexerCount) {
\r
128 ExternalLexerModule *lex;
\r
131 // Find functions in the DLL
\r
132 GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
\r
133 ExtLexerFunction Lexer = (ExtLexerFunction)(sptr_t)lib->FindFunction("Lex");
\r
134 ExtFoldFunction Folder = (ExtFoldFunction)(sptr_t)lib->FindFunction("Fold");
\r
136 // Assign a buffer for the lexer name.
\r
138 strcpy(lexname, "");
\r
140 int nl = GetLexerCount();
\r
142 for (int i = 0; i < nl; i++) {
\r
143 GetLexerName(i, lexname, 100);
\r
144 lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
\r
146 // Create a LexerMinder so we don't leak the ExternalLexerModule...
\r
147 lm = new LexerMinder;
\r
150 if (first != NULL) {
\r
158 // The external lexer needs to know how to call into its DLL to
\r
159 // do its lexing and folding, we tell it here. Folder may be null.
\r
160 lex->SetExternal(Lexer, Folder, i);
\r
167 LexerLibrary::~LexerLibrary() {
\r
172 void LexerLibrary::Release() {
\r
173 //TODO maintain a list of lexers created, and delete them!
\r
175 LexerMinder *lmNext;
\r
177 while (NULL != lm) {
\r
188 //------------------------------------------
\r
192 //------------------------------------------
\r
194 /// Return the single LexerManager instance...
\r
195 LexerManager *LexerManager::GetInstance() {
\r
197 theInstance = new LexerManager;
\r
198 return theInstance;
\r
201 /// Delete any LexerManager instance...
\r
202 void LexerManager::DeleteInstance()
\r
205 delete theInstance;
\r
206 theInstance = NULL;
\r
210 /// protected constructor - this is a singleton...
\r
211 LexerManager::LexerManager() {
\r
216 LexerManager::~LexerManager() {
\r
220 void LexerManager::Load(const char* path)
\r
222 LoadLexerLibrary(path);
\r
225 void LexerManager::LoadLexerLibrary(const char* module)
\r
227 LexerLibrary *lib = new LexerLibrary(module);
\r
228 if (NULL != first) {
\r
237 void LexerManager::Clear()
\r
239 if (NULL != first) {
\r
240 LexerLibrary *cur = first;
\r
241 LexerLibrary *next;
\r
252 //------------------------------------------
\r
256 //------------------------------------------
\r
258 LMMinder::~LMMinder()
\r
260 LexerManager::DeleteInstance();
\r