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