aboutsummaryrefslogtreecommitdiffhomepage
path: root/win32/ExternalLexer.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'win32/ExternalLexer.cxx')
-rw-r--r--win32/ExternalLexer.cxx283
1 files changed, 283 insertions, 0 deletions
diff --git a/win32/ExternalLexer.cxx b/win32/ExternalLexer.cxx
new file mode 100644
index 000000000..83aee0677
--- /dev/null
+++ b/win32/ExternalLexer.cxx
@@ -0,0 +1,283 @@
+// Scintilla source code edit control
+/** @file ExternalLexer.cxx
+ ** Support external lexers in DLLs.
+ **/
+// Copyright 2001 Simon Steele <ss@pnotepad.org>, portions copyright Neil Hodgson.
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "SciLexer.h"
+#include "Platform.h"
+#include "PropSet.h"
+#include "Accessor.h"
+#include "DocumentAccessor.h"
+#include "KeyWords.h"
+#include "ExternalLexer.h"
+
+// Initialise the static vars...
+int LexerManager::UseCount = 0;
+LexerLibrary *LexerManager::first = NULL;
+LexerLibrary *LexerManager::last = NULL;
+
+//------------------------------------------
+//
+// ExternalLexerModule
+//
+//------------------------------------------
+
+char **WordListsToStrings(WordList *val[]) {
+ int dim = 0;
+ while (val[dim])
+ dim++;
+ char **wls = new char * [dim + 1];
+ for (int i = 0;i < dim;i++) {
+ SString words;
+ words = "";
+ for (int n = 0; n < val[i]->len; n++) {
+ words += val[i]->words[n];
+ if (n != val[i]->len - 1)
+ words += " ";
+ }
+ wls[i] = new char[words.length() + 1];
+ strcpy(wls[i], words.c_str());
+ }
+ wls[dim] = 0;
+ return wls;
+}
+
+void DeleteWLStrings(char *strs[]) {
+ int dim = 0;
+ while (strs[dim]) {
+ delete strs[dim];
+ dim++;
+ }
+ delete [] strs;
+}
+
+void ExternalLexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+ if (!fneLexer)
+ return ;
+
+ char **kwds = WordListsToStrings(keywordlists);
+ char *ps = styler.GetProperties();
+
+ // The accessor passed in is always a DocumentAccessor so this cast and the subsequent
+ // access will work. Can not use the stricter dynamic_cast as that requires RTTI.
+ DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
+ WindowID wID = da.GetWindow();
+
+ fneLexer(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
+
+ delete ps;
+ DeleteWLStrings(kwds);
+}
+
+void ExternalLexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle,
+ WordList *keywordlists[], Accessor &styler) {
+ if (!fneFolder)
+ return ;
+
+ char **kwds = WordListsToStrings(keywordlists);
+ char *ps = styler.GetProperties();
+
+ // The accessor passed in is always a DocumentAccessor so this cast and the subsequent
+ // access will work. Can not use the stricter dynamic_cast as that requires RTTI.
+ DocumentAccessor &da = static_cast<DocumentAccessor &>(styler);
+ WindowID wID = da.GetWindow();
+
+ fneFolder(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps);
+
+ delete ps;
+ DeleteWLStrings(kwds);
+}
+
+void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index) {
+ fneLexer = fLexer;
+ fneFolder = fFolder;
+ externalLanguage = index;
+}
+
+//------------------------------------------
+//
+// LexerLibrary
+//
+//------------------------------------------
+
+LexerLibrary::LexerLibrary(LPCTSTR ModuleName) {
+ // Initialise some members...
+ first = NULL;
+ last = NULL;
+
+ // Load the DLL
+ m_hModule = LoadLibrary(ModuleName);
+ if (m_hModule) {
+ m_sModuleName = ModuleName;
+ GetLexerCountFn GetLexerCount = (GetLexerCountFn)GetProcAddress(m_hModule, "GetLexerCount");
+
+ if (GetLexerCount) {
+ ExternalLexerModule *lex;
+ LexerMinder *lm;
+
+ // Find functions in the DLL
+ GetLexerNameFn GetLexerName = (GetLexerNameFn)GetProcAddress(m_hModule, "GetLexerName");
+ ExtLexerFunction Lexer = (ExtLexerFunction)GetProcAddress(m_hModule, "Lex");
+ ExtFoldFunction Folder = (ExtFoldFunction)GetProcAddress(m_hModule, "Fold");
+
+ // Assign a buffer for the lexer name.
+ char lexname[100];
+ strcpy(lexname, "");
+
+ int nl = GetLexerCount();
+
+ for (int i = 0; i < nl; i++) {
+ GetLexerName(i, lexname, 100);
+ lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL);
+
+ // Create a LexerMinder so we don't leak the ExternalLexerModule...
+ lm = new LexerMinder;
+ lm->self = lex;
+ lm->next = NULL;
+ if (first != NULL) {
+ last->next = lm;
+ last = lm;
+ } else {
+ first = lm;
+ last = lm;
+ }
+
+ // The external lexer needs to know how to call into its DLL to
+ // do its lexing and folding, we tell it here. Folder may be null.
+ lex->SetExternal(Lexer, Folder, i);
+
+ }
+ }
+ }
+ next = NULL;
+}
+
+LexerLibrary::~LexerLibrary() {
+ Release();
+}
+
+void LexerLibrary::Release() {
+ //TODO maintain a list of lexers created, and delete them!
+ LexerMinder *lm;
+ LexerMinder *next;
+ lm = first;
+ while (NULL != lm) {
+ next = lm->next;
+ delete lm->self;
+ delete lm;
+ lm = next;
+ }
+
+ first = NULL;
+ last = NULL;
+
+ // Release the DLL
+ if (NULL != m_hModule) {
+ FreeLibrary(m_hModule);
+ }
+}
+
+//------------------------------------------
+//
+// LexerManager
+//
+//------------------------------------------
+
+int FindLastSlash(char *inp) {
+ int i;
+ int ret = -1;
+ for (i = strlen(inp) - 1; i >= 0; i--) {
+ if (inp[i] == '\\' || inp[i] == '/') {
+ // if you don't like break:
+ /*
+ if (ret == -1)
+ */
+ ret = i;
+ break;
+ }
+ }
+ return ret;
+}
+
+LexerManager::LexerManager() {
+
+ UseCount++;
+ if (1 == UseCount) {
+ EnumerateLexers();
+ }
+}
+
+void LexerManager::EnumerateLexers() {
+ HANDLE hFind;
+ WIN32_FIND_DATA FindFileData;
+
+ char path[MAX_PATH + 1];
+
+ GetModuleFileName(GetModuleHandle(NULL), path, MAX_PATH);
+
+ int i = FindLastSlash(path);
+
+ if (i == -1)
+ i = strlen(path);
+
+ SString sPath(path, 0, i);
+
+ // Ensure a trailing slash...
+ if ( sPath[sPath.size() - 1] != '/' && sPath[sPath.size() - 1] != '\\' ) {
+ sPath += '\\';
+ }
+
+ SString sPattern(sPath);
+
+ sPattern.append("*.lexer");
+
+ hFind = FindFirstFile(sPattern.c_str(), &FindFileData);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ //Found the first file...
+ BOOL found = TRUE;
+ LexerLibrary *lib = NULL;
+ SString to_open;
+
+ while (found) {
+ to_open.assign(sPath);
+ to_open += FindFileData.cFileName;
+ lib = new LexerLibrary(to_open.c_str());
+ if (NULL != first) {
+ last->next = lib;
+ last = lib;
+ } else {
+ first = lib;
+ last = lib;
+ }
+ found = FindNextFile(hFind, &FindFileData);
+ }
+
+ FindClose(hFind);
+
+ }
+}
+
+LexerManager::~LexerManager() {
+ // If this is the last LexerManager to be freed then
+ // we delete all of our LexerLibrarys.
+ UseCount--;
+ if (0 == UseCount) {
+ if (NULL != first) {
+ LexerLibrary *cur = first;
+ LexerLibrary *next = first->next;
+ while (first) {
+ delete cur;
+ cur = next;
+ }
+ first = NULL;
+ last = NULL;
+ }
+ }
+}