]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/ExternalLexer.cxx
098df4dd5bc34ee8765052a8d522969c2571e371
[wxWidgets.git] / src / stc / scintilla / src / ExternalLexer.cxx
1 // Scintilla source code edit control
2 /** @file ExternalLexer.cxx
3 ** Support external lexers in DLLs.
4 **/
5 // Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
6 // The License.txt file describes the conditions under which this software may be distributed.
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <ctype.h>
12
13 #include <string>
14
15 #include "Platform.h"
16
17 #include "Scintilla.h"
18
19 #include "SciLexer.h"
20 #include "PropSet.h"
21 #include "Accessor.h"
22 #include "DocumentAccessor.h"
23 #include "KeyWords.h"
24 #include "ExternalLexer.h"
25
26 #ifdef SCI_NAMESPACE
27 using namespace Scintilla;
28 #endif
29
30 LexerManager *LexerManager::theInstance = NULL;
31
32 //------------------------------------------
33 //
34 // ExternalLexerModule
35 //
36 //------------------------------------------
37
38 char **WordListsToStrings(WordList *val[]) {
39 int dim = 0;
40 while (val[dim])
41 dim++;
42 char **wls = new char * [dim + 1];
43 for (int i = 0;i < dim;i++) {
44 std::string words;
45 words = "";
46 for (int n = 0; n < val[i]->len; n++) {
47 words += val[i]->words[n];
48 if (n != val[i]->len - 1)
49 words += " ";
50 }
51 wls[i] = new char[words.length() + 1];
52 strcpy(wls[i], words.c_str());
53 }
54 wls[dim] = 0;
55 return wls;
56 }
57
58 void DeleteWLStrings(char *strs[]) {
59 int dim = 0;
60 while (strs[dim]) {
61 delete strs[dim];
62 dim++;
63 }
64 delete [] strs;
65 }
66
67 void ExternalLexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
68 WordList *keywordlists[], Accessor &styler) const {
69 if (!fneLexer)
70 return ;
71
72 char **kwds = WordListsToStrings(keywordlists);
73 char *ps = styler.GetProperties();
74
75 // The accessor passed in is always a DocumentAccessor so this cast and the subsequent
76 // access will work. Can not use the stricter dynamic_cast as that requires RTTI.
77 DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
78 WindowID wID = da.GetWindow();
79
80 fneLexer(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
81
82 delete ps;
83 DeleteWLStrings(kwds);
84 }
85
86 void ExternalLexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
87 WordList *keywordlists[], Accessor &styler) const {
88 if (!fneFolder)
89 return ;
90
91 char **kwds = WordListsToStrings(keywordlists);
92 char *ps = styler.GetProperties();
93
94 // The accessor passed in is always a DocumentAccessor so this cast and the subsequent
95 // access will work. Can not use the stricter dynamic_cast as that requires RTTI.
96 DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
97 WindowID wID = da.GetWindow();
98
99 fneFolder(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
100
101 delete ps;
102 DeleteWLStrings(kwds);
103 }
104
105 void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index) {
106 fneLexer = fLexer;
107 fneFolder = fFolder;
108 externalLanguage = index;
109 }
110
111 //------------------------------------------
112 //
113 // LexerLibrary
114 //
115 //------------------------------------------
116
117 LexerLibrary::LexerLibrary(const char* ModuleName) {
118 // Initialise some members...
119 first = NULL;
120 last = NULL;
121
122 // Load the DLL
123 lib = DynamicLibrary::Load(ModuleName);
124 if (lib->IsValid()) {
125 m_sModuleName = ModuleName;
126 //Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
127 GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount");
128
129 if (GetLexerCount) {
130 ExternalLexerModule *lex;
131 LexerMinder *lm;
132
133 // Find functions in the DLL
134 GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
135 ExtLexerFunction Lexer = (ExtLexerFunction)(sptr_t)lib->FindFunction("Lex");
136 ExtFoldFunction Folder = (ExtFoldFunction)(sptr_t)lib->FindFunction("Fold");
137
138 // Assign a buffer for the lexer name.
139 char lexname[100];
140 strcpy(lexname, "");
141
142 int nl = GetLexerCount();
143
144 for (int i = 0; i < nl; i++) {
145 GetLexerName(i, lexname, 100);
146 lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
147
148 // Create a LexerMinder so we don't leak the ExternalLexerModule...
149 lm = new LexerMinder;
150 lm->self = lex;
151 lm->next = NULL;
152 if (first != NULL) {
153 last->next = lm;
154 last = lm;
155 } else {
156 first = lm;
157 last = lm;
158 }
159
160 // The external lexer needs to know how to call into its DLL to
161 // do its lexing and folding, we tell it here. Folder may be null.
162 lex->SetExternal(Lexer, Folder, i);
163 }
164 }
165 }
166 next = NULL;
167 }
168
169 LexerLibrary::~LexerLibrary() {
170 Release();
171 delete lib;
172 }
173
174 void LexerLibrary::Release() {
175 //TODO maintain a list of lexers created, and delete them!
176 LexerMinder *lm;
177 LexerMinder *lmNext;
178 lm = first;
179 while (NULL != lm) {
180 lmNext = lm->next;
181 delete lm->self;
182 delete lm;
183 lm = lmNext;
184 }
185
186 first = NULL;
187 last = NULL;
188 }
189
190 //------------------------------------------
191 //
192 // LexerManager
193 //
194 //------------------------------------------
195
196 /// Return the single LexerManager instance...
197 LexerManager *LexerManager::GetInstance() {
198 if(!theInstance)
199 theInstance = new LexerManager;
200 return theInstance;
201 }
202
203 /// Delete any LexerManager instance...
204 void LexerManager::DeleteInstance()
205 {
206 if(theInstance) {
207 delete theInstance;
208 theInstance = NULL;
209 }
210 }
211
212 /// protected constructor - this is a singleton...
213 LexerManager::LexerManager() {
214 first = NULL;
215 last = NULL;
216 }
217
218 LexerManager::~LexerManager() {
219 Clear();
220 }
221
222 void LexerManager::Load(const char* path)
223 {
224 LoadLexerLibrary(path);
225 }
226
227 void LexerManager::LoadLexerLibrary(const char* module)
228 {
229 LexerLibrary *lib = new LexerLibrary(module);
230 if (NULL != first) {
231 last->next = lib;
232 last = lib;
233 } else {
234 first = lib;
235 last = lib;
236 }
237 }
238
239 void LexerManager::Clear()
240 {
241 if (NULL != first) {
242 LexerLibrary *cur = first;
243 LexerLibrary *next;
244 while (cur) {
245 next = cur->next;
246 delete cur;
247 cur = next;
248 }
249 first = NULL;
250 last = NULL;
251 }
252 }
253
254 //------------------------------------------
255 //
256 // LexerManager
257 //
258 //------------------------------------------
259
260 LMMinder::~LMMinder()
261 {
262 LexerManager::DeleteInstance();
263 }
264
265 LMMinder minder;