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