diff options
Diffstat (limited to 'win32')
| -rw-r--r-- | win32/ExternalLexer.cxx | 283 | ||||
| -rw-r--r-- | win32/ExternalLexer.h | 74 | ||||
| -rw-r--r-- | win32/ScintillaWin.cxx | 68 | ||||
| -rw-r--r-- | win32/deps.mak | 7 | ||||
| -rw-r--r-- | win32/makefile | 8 | ||||
| -rw-r--r-- | win32/scintilla.mak | 5 | 
6 files changed, 439 insertions, 6 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; +		} +	} +} diff --git a/win32/ExternalLexer.h b/win32/ExternalLexer.h new file mode 100644 index 000000000..bbc2cf4f6 --- /dev/null +++ b/win32/ExternalLexer.h @@ -0,0 +1,74 @@ +// Scintilla source code edit control +/** @file ExternalLexer.h + ** 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. + +#ifndef EXTERNALLEXER_H +#define EXTERNALLEXER_H + +// External Lexer function definitions... +typedef void (__stdcall *ExtLexerFunction)(unsigned int lexer, unsigned int startPos, int length, int initStyle, +                  char *words[], WindowID window, char *props); +typedef void (__stdcall *ExtFoldFunction)(unsigned int lexer, unsigned int startPos, int length, int initStyle, +                  char *words[], WindowID window, char *props); +typedef void* (__stdcall *GetLexerFunction)(unsigned int Index); +typedef int (__stdcall *GetLexerCountFn)(); +typedef void (__stdcall *GetLexerNameFn)(unsigned int Index, char *name, int buflength); + +// Sub-class of LexerModule to use an external lexer. +class ExternalLexerModule : protected LexerModule { +protected: +	ExtLexerFunction fneLexer; +	ExtFoldFunction fneFolder; +	int externalLanguage; +	char name[100]; +public: +	ExternalLexerModule(int language_, LexerFunction fnLexer_,  +		const char *languageName_=0, LexerFunction fnFolder_=0) : LexerModule(language_, fnLexer_, 0, fnFolder_){ +		strncpy(name, languageName_, sizeof(name)); +		languageName = name; +	}; +	virtual void Lex(unsigned int startPos, int lengthDoc, int initStyle, +					WordList *keywordlists[], Accessor &styler); +	virtual void Fold(unsigned int startPos, int lengthDoc, int initStyle, +					WordList *keywordlists[], Accessor &styler); +	virtual void SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index); +}; + +// LexerMinder points to an ExternalLexerModule - so we don't leak them. +class LexerMinder { +public: +	ExternalLexerModule *self; +	LexerMinder *next; +}; + +// LexerLibrary exists for every External Lexer DLL, contains LexerMinders. +class LexerLibrary { +public: +	LexerLibrary(LPCTSTR ModuleName); +	~LexerLibrary(); +	void Release(); +	// Variables +	LexerLibrary	*next; +	SString			m_sModuleName; +private: +	HMODULE m_hModule; +	LexerMinder *first; +	LexerMinder *last; +}; + +// LexerManager manages external lexers, contains LexerLibrarys. +class LexerManager { +public: +	LexerManager(); +	~LexerManager(); +private: +	void EnumerateLexers(); +	static int UseCount; +	static LexerLibrary *first; +	static LexerLibrary *last; +}; + +#endif diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx index 79a3d1183..c0756938b 100644 --- a/win32/ScintillaWin.cxx +++ b/win32/ScintillaWin.cxx @@ -36,12 +36,33 @@  #include "ScintillaBase.h"  #include "UniConversion.h" +#ifdef SCI_LEXER +#include "ExternalLexer.h" +#endif +  //#include "CElapsed.h"  #ifndef SPI_GETWHEELSCROLLLINES  #define SPI_GETWHEELSCROLLLINES   104  #endif +// These undefinitions are required to work around differences between different versions +// of the mingw headers, some of which define these twice, in both winuser.h and imm.h. +#ifdef __MINGW_H +#undef WM_IME_STARTCOMPOSITION +#undef WM_IME_ENDCOMPOSITION +#undef WM_IME_COMPOSITION +#undef WM_IME_KEYLAST +#undef WM_IME_SETCONTEXT +#undef WM_IME_NOTIFY +#undef WM_IME_CONTROL +#undef WM_IME_COMPOSITIONFULL +#undef WM_IME_SELECT +#undef WM_IME_CHAR +#undef WM_IME_KEYDOWN +#undef WM_IME_KEYUP +#endif +  #ifndef WM_IME_STARTCOMPOSITION  #include <imm.h>  #endif @@ -126,6 +147,10 @@ class ScintillaWin :  	static HINSTANCE hInstance; +#ifdef SCI_LEXER +	LexerManager *lexMan; +#endif +  	ScintillaWin(HWND hwnd);  	ScintillaWin(const ScintillaWin &) : ScintillaBase() {}  	virtual ~ScintillaWin(); @@ -193,6 +218,12 @@ public:  	/// Implement important part of IDataObject  	STDMETHODIMP GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM); +	// External Lexers +#ifdef SCI_LEXER +	void SetLexerLanguage(const char *languageName); +	void SetLexer(uptr_t wParam); +#endif +  	bool IsUnicodeMode() const;  	static void Register(HINSTANCE hInstance_); @@ -235,6 +266,10 @@ void ScintillaWin::Initialise() {  	// no effect.  If the app hasnt, we really shouldnt ask them to call  	// it just so this internal feature works.  	OleInitialize(NULL); + +#ifdef SCI_LEXER +	lexMan = new LexerManager; +#endif  }  void ScintillaWin::Finalise() { @@ -242,6 +277,10 @@ void ScintillaWin::Finalise() {  	SetTicking(false);  	RevokeDragDrop(wMain.GetID());  	OleUninitialize(); + +#ifdef SCI_LEXER +	delete lexMan; +#endif  }  void ScintillaWin::StartDrag() { @@ -860,6 +899,35 @@ void ScintillaWin::ClaimSelection() {  	// Windows does not have a primary selection  } +#ifdef SCI_LEXER + +/*  + +  Initial Windows-Only implementation of the external lexer +  system in ScintillaWin class. Intention is to create a LexerModule +  subclass (?) to have lex and fold methods which will call out to their +  relevant DLLs... + +*/ + +void ScintillaWin::SetLexer(uptr_t wParam) { +	lexLanguage = wParam; +	lexCurrent = LexerModule::Find(lexLanguage); +	if (!lexCurrent) +		lexCurrent = LexerModule::Find(SCLEX_NULL); +} + +void ScintillaWin::SetLexerLanguage(const char *languageName) { +	lexLanguage = SCLEX_CONTAINER; +	lexCurrent = LexerModule::Find(languageName); +	if (!lexCurrent) +		lexCurrent = LexerModule::Find(SCLEX_NULL); +	if (lexCurrent) +		lexLanguage = lexCurrent->GetLanguage(); +} + +#endif +  /// Implement IUnknown  STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe); diff --git a/win32/deps.mak b/win32/deps.mak index f46cfa7ef..f2b1908d7 100644 --- a/win32/deps.mak +++ b/win32/deps.mak @@ -1,3 +1,7 @@ +ExternalLexer.o: ExternalLexer.cxx ..\include\SciLexer.h \ + ..\include\platform.h ..\include\propset.h ..\include\SString.h \ + ..\include\accessor.h ..\src\DocumentAccessor.h ..\include\KeyWords.h \ + ExternalLexer.h  PlatWin.o: PlatWin.cxx ..\include\Platform.h PlatformRes.h \   ..\src\UniConversion.h  ScintillaWin.o: ScintillaWin.cxx ..\include\Platform.h \ @@ -45,9 +49,6 @@ LexConf.o: ../src/LexConf.cxx ..\include\Platform.h \  LexCPP.o: ../src/LexCPP.cxx ..\include\Platform.h ..\include\PropSet.h \   ..\include\SString.h ..\include\Accessor.h ..\include\KeyWords.h \   ..\include\Scintilla.h ..\include\SciLexer.h -LexerManager.o: ../src/LexerManager.cxx ..\include\SciLexer.h \ - ..\include\platform.h ..\include\propset.h ..\include\SString.h \ - ..\include\accessor.h ..\include\KeyWords.h ..\include\LexerManager.h  LexHTML.o: ../src/LexHTML.cxx ..\include\Platform.h \   ..\include\PropSet.h ..\include\SString.h ..\include\Accessor.h \   ..\include\KeyWords.h ..\include\Scintilla.h ..\include\SciLexer.h diff --git a/win32/makefile b/win32/makefile index d177302b2..91407950a 100644 --- a/win32/makefile +++ b/win32/makefile @@ -52,7 +52,7 @@ LOBJS	= ScintillaWinL.o ScintillaBaseL.o Editor.o Document.o \  	ContractionState.o CellBuffer.o CallTip.o \  	ScintRes.o PlatWin.o KeyMap.o Indicator.o LineMarker.o RESearch.o \  	Style.o ViewStyle.o AutoComplete.o UniConversion.o KeyWords.o \ -	DocumentAccessor.o PropSet.o $(LEXOBJS) +	DocumentAccessor.o PropSet.o ExternalLexer.o $(LEXOBJS)  $(LEXCOMPONENT): $(LOBJS)  	$(DLLWRAP) --target i386-mingw32 -o $@ $(LOBJS) $(LDFLAGS) -s --relocatable @@ -63,11 +63,13 @@ include deps.mak  ScintillaBaseL.o: ScintillaBase.cxx Platform.h Scintilla.h SciLexer.h \   ContractionState.h CellBuffer.h CallTip.h KeyMap.h Indicator.h \   LineMarker.h Style.h AutoComplete.h ViewStyle.h Document.h Editor.h \ - ScintillaBase.h PropSet.h SString.h Accessor.h DocumentAccessor.h KeyWords.h + ScintillaBase.h PropSet.h SString.h Accessor.h DocumentAccessor.h \ + KeyWords.h ExternalLexer.h  ScintillaWinL.o: ScintillaWin.cxx Platform.h Scintilla.h SciLexer.h \   ContractionState.h CellBuffer.h CallTip.h KeyMap.h Indicator.h \   LineMarker.h Style.h AutoComplete.h ViewStyle.h Document.h Editor.h \ - ScintillaBase.h PropSet.h SString.h Accessor.h KeyWords.h UniConversion.h + ScintillaBase.h PropSet.h SString.h Accessor.h KeyWords.h \ + ExternalLexer.h UniConversion.h  ScintillaWinS.o: ScintillaWin.cxx Platform.h Scintilla.h \   ContractionState.h CellBuffer.h CallTip.h KeyMap.h Indicator.h \   LineMarker.h Style.h AutoComplete.h ViewStyle.h Document.h Editor.h \ diff --git a/win32/scintilla.mak b/win32/scintilla.mak index 5d6d9a3f5..89596d045 100644 --- a/win32/scintilla.mak +++ b/win32/scintilla.mak @@ -126,6 +126,7 @@ LOBJS=\  	$(DIR_O)\Document.obj \  	$(DIR_O)\DocumentAccessor.obj \  	$(DIR_O)\Editor.obj \ +	$(DIR_O)\ExternalLexer.obj \  	$(DIR_O)\Indicator.obj \  	$(DIR_O)\KeyMap.obj \  	$(DIR_O)\KeyWords.obj \ @@ -207,6 +208,10 @@ $(DIR_O)\Editor.obj: ..\src\Editor.cxx ..\include\Platform.h ..\include\Scintill   ..\src\CellBuffer.h ..\src\KeyMap.h ..\src\Indicator.h ..\src\LineMarker.h ..\src\Style.h ..\src\ViewStyle.h \   ..\src\Document.h ..\src\Editor.h +$(DIR_O)\ExternalLexer.obj: ExternalLexer.cxx ExternalLexer.h \ + ..\include\SciLexer.h ..\include\Platform.h ..\include\PropSet.h ..\include\SString.h \ + ..\include\Accessor.h ..\src\DocumentAccessor.h ..\include\KeyWords.h \ +  $(DIR_O)\Indicator.obj: ..\src\Indicator.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\Indicator.h  $(DIR_O)\KeyMap.obj: ..\src\KeyMap.cxx ..\include\Platform.h ..\include\Scintilla.h ..\src\KeyMap.h | 
