1 // Scintilla source code edit control
2 /** @file ExternalLexer.cxx
3 ** Support external lexers in DLLs.
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.
17 #include "Scintilla.h"
22 #include "DocumentAccessor.h"
24 #include "ExternalLexer.h"
27 using namespace Scintilla
;
30 LexerManager
*LexerManager::theInstance
= NULL
;
32 //------------------------------------------
34 // ExternalLexerModule
36 //------------------------------------------
38 char **WordListsToStrings(WordList
*val
[]) {
42 char **wls
= new char * [dim
+ 1];
43 for (int i
= 0;i
< dim
;i
++) {
46 for (int n
= 0; n
< val
[i
]->len
; n
++) {
47 words
+= val
[i
]->words
[n
];
48 if (n
!= val
[i
]->len
- 1)
51 wls
[i
] = new char[words
.length() + 1];
52 strcpy(wls
[i
], words
.c_str());
58 void DeleteWLStrings(char *strs
[]) {
67 void ExternalLexerModule::Lex(unsigned int startPos
, int lengthDoc
, int initStyle
,
68 WordList
*keywordlists
[], Accessor
&styler
) const {
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
);
83 DeleteWLStrings(kwds
);
86 void ExternalLexerModule::Fold(unsigned int startPos
, int lengthDoc
, int initStyle
,
87 WordList
*keywordlists
[], Accessor
&styler
) const {
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
);
102 DeleteWLStrings(kwds
);
105 void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer
, ExtFoldFunction fFolder
, int index
) {
108 externalLanguage
= index
;
111 //------------------------------------------
115 //------------------------------------------
117 LexerLibrary::LexerLibrary(const char* ModuleName
) {
118 // Initialise some members...
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");
130 ExternalLexerModule
*lex
;
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.
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
;
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
);
169 LexerLibrary::~LexerLibrary() {
174 void LexerLibrary::Release() {
175 //TODO maintain a list of lexers created, and delete them!
190 //------------------------------------------
194 //------------------------------------------
196 /// Return the single LexerManager instance...
197 LexerManager
*LexerManager::GetInstance() {
199 theInstance
= new LexerManager
;
203 /// Delete any LexerManager instance...
204 void LexerManager::DeleteInstance()
212 /// protected constructor - this is a singleton...
213 LexerManager::LexerManager() {
218 LexerManager::~LexerManager() {
222 void LexerManager::Load(const char* path
)
224 LoadLexerLibrary(path
);
227 void LexerManager::LoadLexerLibrary(const char* module)
229 LexerLibrary
*lib
= new LexerLibrary(module);
239 void LexerManager::Clear()
242 LexerLibrary
*cur
= first
;
254 //------------------------------------------
258 //------------------------------------------
260 LMMinder::~LMMinder()
262 LexerManager::DeleteInstance();