Support more folding icon styles: arrows, +/- and no lines
[geany-mirror.git] / scintilla / ExternalLexer.cxx
blob098df4dd5bc34ee8765052a8d522969c2571e371
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.
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <ctype.h>
13 #include <string>
15 #include "Platform.h"
17 #include "Scintilla.h"
19 #include "SciLexer.h"
20 #include "PropSet.h"
21 #include "Accessor.h"
22 #include "DocumentAccessor.h"
23 #include "KeyWords.h"
24 #include "ExternalLexer.h"
26 #ifdef SCI_NAMESPACE
27 using namespace Scintilla;
28 #endif
30 LexerManager *LexerManager::theInstance = NULL;
32 //------------------------------------------
34 // ExternalLexerModule
36 //------------------------------------------
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 += " ";
51 wls[i] = new char[words.length() + 1];
52 strcpy(wls[i], words.c_str());
54 wls[dim] = 0;
55 return wls;
58 void DeleteWLStrings(char *strs[]) {
59 int dim = 0;
60 while (strs[dim]) {
61 delete strs[dim];
62 dim++;
64 delete [] strs;
67 void ExternalLexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
68 WordList *keywordlists[], Accessor &styler) const {
69 if (!fneLexer)
70 return ;
72 char **kwds = WordListsToStrings(keywordlists);
73 char *ps = styler.GetProperties();
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();
80 fneLexer(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
82 delete ps;
83 DeleteWLStrings(kwds);
86 void ExternalLexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
87 WordList *keywordlists[], Accessor &styler) const {
88 if (!fneFolder)
89 return ;
91 char **kwds = WordListsToStrings(keywordlists);
92 char *ps = styler.GetProperties();
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();
99 fneFolder(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
101 delete ps;
102 DeleteWLStrings(kwds);
105 void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index) {
106 fneLexer = fLexer;
107 fneFolder = fFolder;
108 externalLanguage = index;
111 //------------------------------------------
113 // LexerLibrary
115 //------------------------------------------
117 LexerLibrary::LexerLibrary(const char* ModuleName) {
118 // Initialise some members...
119 first = NULL;
120 last = NULL;
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");
129 if (GetLexerCount) {
130 ExternalLexerModule *lex;
131 LexerMinder *lm;
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");
138 // Assign a buffer for the lexer name.
139 char lexname[100];
140 strcpy(lexname, "");
142 int nl = GetLexerCount();
144 for (int i = 0; i < nl; i++) {
145 GetLexerName(i, lexname, 100);
146 lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
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;
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);
166 next = NULL;
169 LexerLibrary::~LexerLibrary() {
170 Release();
171 delete lib;
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;
186 first = NULL;
187 last = NULL;
190 //------------------------------------------
192 // LexerManager
194 //------------------------------------------
196 /// Return the single LexerManager instance...
197 LexerManager *LexerManager::GetInstance() {
198 if(!theInstance)
199 theInstance = new LexerManager;
200 return theInstance;
203 /// Delete any LexerManager instance...
204 void LexerManager::DeleteInstance()
206 if(theInstance) {
207 delete theInstance;
208 theInstance = NULL;
212 /// protected constructor - this is a singleton...
213 LexerManager::LexerManager() {
214 first = NULL;
215 last = NULL;
218 LexerManager::~LexerManager() {
219 Clear();
222 void LexerManager::Load(const char* path)
224 LoadLexerLibrary(path);
227 void LexerManager::LoadLexerLibrary(const char* module)
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;
239 void LexerManager::Clear()
241 if (NULL != first) {
242 LexerLibrary *cur = first;
243 LexerLibrary *next;
244 while (cur) {
245 next = cur->next;
246 delete cur;
247 cur = next;
249 first = NULL;
250 last = NULL;
254 //------------------------------------------
256 // LexerManager
258 //------------------------------------------
260 LMMinder::~LMMinder()
262 LexerManager::DeleteInstance();
265 LMMinder minder;