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