Update Scintilla to 4.0.4
[TortoiseGit.git] / ext / scintilla / src / ExternalLexer.cxx
blob950ea3e32e37d6e0ed69c06db7b7c1474919f2fd
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 <cstdlib>
9 #include <cassert>
10 #include <cstring>
12 #include <stdexcept>
13 #include <string>
14 #include <vector>
15 #include <memory>
17 #include "Platform.h"
19 #include "ILexer.h"
20 #include "Scintilla.h"
21 #include "SciLexer.h"
23 #include "LexerModule.h"
24 #include "Catalogue.h"
25 #include "ExternalLexer.h"
27 using namespace Scintilla;
29 std::unique_ptr<LexerManager> LexerManager::theInstance;
31 //------------------------------------------
33 // ExternalLexerModule
35 //------------------------------------------
37 void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) {
38 fneFactory = fFactory;
39 fnFactory = fFactory(index);
42 //------------------------------------------
44 // LexerLibrary
46 //------------------------------------------
48 LexerLibrary::LexerLibrary(const char *moduleName_) {
49 // Load the DLL
50 lib.reset(DynamicLibrary::Load(moduleName_));
51 if (lib->IsValid()) {
52 moduleName = moduleName_;
53 //Cannot use reinterpret_cast because: ANSI C++ forbids casting between pointers to functions and objects
54 GetLexerCountFn GetLexerCount = (GetLexerCountFn)(sptr_t)lib->FindFunction("GetLexerCount");
56 if (GetLexerCount) {
57 // Find functions in the DLL
58 GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName");
59 GetLexerFactoryFunction fnFactory = (GetLexerFactoryFunction)(sptr_t)lib->FindFunction("GetLexerFactory");
61 const int nl = GetLexerCount();
63 for (int i = 0; i < nl; i++) {
64 // Assign a buffer for the lexer name.
65 char lexname[100] = "";
66 GetLexerName(i, lexname, sizeof(lexname));
67 ExternalLexerModule *lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
68 // This is storing a second reference to lex in the Catalogue as well as in modules.
69 // TODO: Should use std::shared_ptr or similar to ensure allocation safety.
70 Catalogue::AddLexerModule(lex);
72 // Remember ExternalLexerModule so we don't leak it
73 modules.push_back(std::unique_ptr<ExternalLexerModule>(lex));
75 // The external lexer needs to know how to call into its DLL to
76 // do its lexing and folding, we tell it here.
77 lex->SetExternal(fnFactory, i);
83 LexerLibrary::~LexerLibrary() {
86 //------------------------------------------
88 // LexerManager
90 //------------------------------------------
92 /// Return the single LexerManager instance...
93 LexerManager *LexerManager::GetInstance() {
94 if (!theInstance)
95 theInstance.reset(new LexerManager);
96 return theInstance.get();
99 /// Delete any LexerManager instance...
100 void LexerManager::DeleteInstance() {
101 theInstance.reset();
104 /// protected constructor - this is a singleton...
105 LexerManager::LexerManager() {
108 LexerManager::~LexerManager() {
109 Clear();
112 void LexerManager::Load(const char *path) {
113 for (const std::unique_ptr<LexerLibrary> &ll : libraries) {
114 if (ll->moduleName == path)
115 return;
117 libraries.push_back(std::make_unique<LexerLibrary>(path));
120 void LexerManager::Clear() {
121 libraries.clear();
124 //------------------------------------------
126 // LMMinder -- trigger to clean up at exit.
128 //------------------------------------------
130 LMMinder::~LMMinder() {
131 LexerManager::DeleteInstance();
134 LMMinder minder;