OSDN Git Service

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