diff options
| -rw-r--r-- | src/AutoComplete.cxx | 3 | ||||
| -rw-r--r-- | src/CharClassify.cxx | 38 | ||||
| -rw-r--r-- | src/CharClassify.h | 15 | ||||
| -rw-r--r-- | src/Document.cxx | 97 | ||||
| -rw-r--r-- | src/Document.h | 61 | ||||
| -rw-r--r-- | src/Editor.cxx | 21 | ||||
| -rw-r--r-- | src/Editor.h | 2 | ||||
| -rw-r--r-- | src/ExternalLexer.cxx | 93 | ||||
| -rw-r--r-- | src/ExternalLexer.h | 19 | ||||
| -rw-r--r-- | src/PositionCache.cxx | 1 | ||||
| -rw-r--r-- | src/ScintillaBase.cxx | 283 | ||||
| -rw-r--r-- | src/ScintillaBase.h | 15 | 
12 files changed, 388 insertions, 260 deletions
| diff --git a/src/AutoComplete.cxx b/src/AutoComplete.cxx index cd58f6172..32cf7b2ed 100644 --- a/src/AutoComplete.cxx +++ b/src/AutoComplete.cxx @@ -8,10 +8,11 @@  #include <stdlib.h>  #include <string.h>  #include <stdio.h> +#include <assert.h>  #include "Platform.h" -#include "CharClassify.h" +#include "CharacterSet.h"  #include "AutoComplete.h"  #ifdef SCI_NAMESPACE diff --git a/src/CharClassify.cxx b/src/CharClassify.cxx index bbd25a0f8..c16af4547 100644 --- a/src/CharClassify.cxx +++ b/src/CharClassify.cxx @@ -10,6 +10,10 @@  #include "CharClassify.h" +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif +  // Shut up annoying Visual C++ warnings:  #ifdef _MSC_VER  #pragma warning(disable: 4514) @@ -42,37 +46,3 @@ void CharClassify::SetCharClasses(const unsigned char *chars, cc newCharClass) {  		}  	}  } - -int CompareCaseInsensitive(const char *a, const char *b) { -	while (*a && *b) { -		if (*a != *b) { -			char upperA = MakeUpperCase(*a); -			char upperB = MakeUpperCase(*b); -			if (upperA != upperB) -				return upperA - upperB; -		} -		a++; -		b++; -	} -	// Either *a or *b is nul -	return *a - *b; -} - -int CompareNCaseInsensitive(const char *a, const char *b, size_t len) { -	while (*a && *b && len) { -		if (*a != *b) { -			char upperA = MakeUpperCase(*a); -			char upperB = MakeUpperCase(*b); -			if (upperA != upperB) -				return upperA - upperB; -		} -		a++; -		b++; -		len--; -	} -	if (len == 0) -		return 0; -	else -		// Either *a or *b is nul -		return *a - *b; -} diff --git a/src/CharClassify.h b/src/CharClassify.h index d746fe02d..e8b798ecb 100644 --- a/src/CharClassify.h +++ b/src/CharClassify.h @@ -8,6 +8,10 @@  #ifndef CHARCLASSIFY_H  #define CHARCLASSIFY_H +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif +  class CharClassify {  public:  	CharClassify(); @@ -23,15 +27,8 @@ private:  	unsigned char charClass[maxChar];    // not type cc to save space  }; -// These functions are implemented because each platform calls them something different. -int CompareCaseInsensitive(const char *a, const char *b); -int CompareNCaseInsensitive(const char *a, const char *b, size_t len); - -inline char MakeUpperCase(char ch) { -	if (ch < 'a' || ch > 'z') -		return ch; -	else -		return static_cast<char>(ch - 'a' + 'A'); +#ifdef SCI_NAMESPACE  } +#endif  #endif diff --git a/src/Document.cxx b/src/Document.cxx index 08d35a893..0d9b8baa3 100644 --- a/src/Document.cxx +++ b/src/Document.cxx @@ -9,6 +9,7 @@  #include <string.h>  #include <stdio.h>  #include <ctype.h> +#include <assert.h>  #include <string>  #include <vector> @@ -23,13 +24,16 @@  #include "Platform.h" +#include "ILexer.h"  #include "Scintilla.h" +  #include "SplitVector.h"  #include "Partitioning.h"  #include "RunStyles.h"  #include "CellBuffer.h"  #include "PerLine.h"  #include "CharClassify.h" +#include "CharacterSet.h"  #include "Decoration.h"  #include "Document.h"  #include "RESearch.h" @@ -60,6 +64,36 @@ static inline bool IsUpperCase(char ch) {  	return isascii(ch) && isupper(ch);  } +void LexInterface::Colourise(int start, int end) { +	ElapsedTime et; +	if (pdoc && instance && !performingStyle) { +		// Protect against reentrance, which may occur, for example, when +		// fold points are discovered while performing styling and the folding +		// code looks for child lines which may trigger styling. +		performingStyle = true; + +		int lengthDoc = pdoc->Length(); +		if (end == -1) +			end = lengthDoc; +		int len = end - start; + +		PLATFORM_ASSERT(len >= 0); +		PLATFORM_ASSERT(start + len <= lengthDoc); + +		int styleStart = 0; +		if (start > 0) +			styleStart = pdoc->StyleAt(start - 1) & pdoc->stylingBitsMask; + +		if (len > 0) { +			instance->Lex(start, len, styleStart, pdoc); +			instance->Fold(start, len, styleStart, pdoc); +		} + +		performingStyle = false; +	} +	Platform::DebugPrintf("Style:%d %9.6g \n", performingStyle, et.Duration()); +} +  Document::Document() {  	refCount = 0;  #ifdef unix @@ -95,6 +129,8 @@ Document::Document() {  	perLineData[ldAnnotation] = new LineAnnotation();  	cb.SetPerLine(this); + +	pli = 0;  }  Document::~Document() { @@ -110,6 +146,8 @@ Document::~Document() {  	lenWatchers = 0;  	delete regex;  	regex = 0; +	delete pli; +	pli = 0;  }  void Document::Init() { @@ -208,7 +246,7 @@ int Document::LineFromHandle(int markerHandle) {  	return static_cast<LineMarkers *>(perLineData[ldMarkers])->LineFromHandle(markerHandle);  } -int Document::LineStart(int line) const { +int SCI_METHOD Document::LineStart(int line) const {  	return cb.LineStart(line);  } @@ -225,7 +263,14 @@ int Document::LineEnd(int line) const {  	}  } -int Document::LineFromPosition(int pos) const { +void SCI_METHOD Document::SetErrorStatus(int status) { +	// Tell the watchers the lexer has changed. +	for (int i = 0; i < lenWatchers; i++) { +		watchers[i].watcher->NotifyErrorOccurred(this, watchers[i].userData, status); +	} +} + +int SCI_METHOD Document::LineFromPosition(int pos) const {  	return cb.LineFromPosition(pos);  } @@ -250,7 +295,7 @@ int Document::VCHomePosition(int position) const {  		return startText;  } -int Document::SetLevel(int line, int level) { +int SCI_METHOD Document::SetLevel(int line, int level) {  	int prev = static_cast<LineLevels *>(perLineData[ldLevels])->SetLevel(line, level, LinesTotal());  	if (prev != level) {  		DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER, @@ -262,7 +307,7 @@ int Document::SetLevel(int line, int level) {  	return prev;  } -int Document::GetLevel(int line) const { +int SCI_METHOD Document::GetLevel(int line) const {  	return static_cast<LineLevels *>(perLineData[ldLevels])->GetLevel(line);  } @@ -476,6 +521,14 @@ int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) {  	return pos;  } +int SCI_METHOD Document::CodePage() const { +	return dbcsCodePage; +} + +bool SCI_METHOD Document::IsDBCSLeadByte(char ch) const { +	return Platform::IsDBCSLeadByte(dbcsCodePage, ch); +} +  void Document::ModifiedAt(int pos) {  	if (endStyled > pos)  		endStyled = pos; @@ -1303,12 +1356,12 @@ void Document::SetStylingBits(int bits) {  	stylingBitsMask = (1 << stylingBits) - 1;  } -void Document::StartStyling(int position, char mask) { +void SCI_METHOD Document::StartStyling(int position, char mask) {  	stylingMask = mask;  	endStyled = position;  } -bool Document::SetStyleFor(int length, char style) { +bool SCI_METHOD Document::SetStyleFor(int length, char style) {  	if (enteredStyling != 0) {  		return false;  	} else { @@ -1326,7 +1379,7 @@ bool Document::SetStyleFor(int length, char style) {  	}  } -bool Document::SetStyles(int length, const char *styles) { +bool SCI_METHOD Document::SetStyles(int length, const char *styles) {  	if (enteredStyling != 0) {  		return false;  	} else { @@ -1357,14 +1410,27 @@ bool Document::SetStyles(int length, const char *styles) {  void Document::EnsureStyledTo(int pos) {  	if ((enteredStyling == 0) && (pos > GetEndStyled())) {  		IncrementStyleClock(); -		// Ask the watchers to style, and stop as soon as one responds. -		for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) { -			watchers[i].watcher->NotifyStyleNeeded(this, watchers[i].userData, pos); +		if (pli) { +			int lineEndStyled = LineFromPosition(GetEndStyled()); +			int endStyled = LineStart(lineEndStyled); +			pli->Colourise(endStyled, pos); +		} else { +			// Ask the watchers to style, and stop as soon as one responds. +			for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) { +				watchers[i].watcher->NotifyStyleNeeded(this, watchers[i].userData, pos); +			}  		}  	}  } -int Document::SetLineState(int line, int state) { +void Document::LexerChanged() { +	// Tell the watchers the lexer has changed. +	for (int i = 0; i < lenWatchers; i++) { +		watchers[i].watcher->NotifyLexerChanged(this, watchers[i].userData); +	} +} + +int SCI_METHOD Document::SetLineState(int line, int state) {  	int statePrevious = static_cast<LineState *>(perLineData[ldState])->SetLineState(line, state);  	if (state != statePrevious) {  		DocModification mh(SC_MOD_CHANGELINESTATE, 0, 0, 0, 0, line); @@ -1373,7 +1439,7 @@ int Document::SetLineState(int line, int state) {  	return statePrevious;  } -int Document::GetLineState(int line) const { +int SCI_METHOD Document::GetLineState(int line) const {  	return static_cast<LineState *>(perLineData[ldState])->GetLineState(line);  } @@ -1381,6 +1447,11 @@ int Document::GetMaxLineState() {  	return static_cast<LineState *>(perLineData[ldState])->GetMaxLineState();  } +void SCI_METHOD Document::ChangeLexerState(int start, int end) { +	DocModification mh(SC_MOD_LEXERSTATE, start, end-start, 0, 0, 0); +	NotifyModified(mh); +} +  StyledText Document::MarginStyledText(int line) {  	LineAnnotation *pla = static_cast<LineAnnotation *>(perLineData[ldMargin]);  	return StyledText(pla->Length(line), pla->Text(line), @@ -1462,7 +1533,7 @@ void Document::IncrementStyleClock() {  	styleClock = (styleClock + 1) % 0x100000;  } -void Document::DecorationFillRange(int position, int value, int fillLength) { +void SCI_METHOD Document::DecorationFillRange(int position, int value, int fillLength) {  	if (decorations.FillRange(position, value, fillLength)) {  		DocModification mh(SC_MOD_CHANGEINDICATOR | SC_PERFORMED_USER,  							position, fillLength); diff --git a/src/Document.h b/src/Document.h index 1c270a556..a765c6299 100644 --- a/src/Document.h +++ b/src/Document.h @@ -133,9 +133,24 @@ public:  	void StandardASCII();  }; +class Document; + +class LexInterface { +protected: +	Document *pdoc; +	ILexer *instance; +	bool performingStyle;	///< Prevent reentrance +public: +	LexInterface(Document *pdoc_) : pdoc(pdoc_), instance(0), performingStyle(false) { +	} +	virtual ~LexInterface() { +	} +	void Colourise(int start, int end); +}; +  /**   */ -class Document : PerLine { +class Document : PerLine, public IDocument {  public:  	/** Used to pair watcher pointer with user data. */ @@ -172,6 +187,9 @@ private:  	RegexSearchBase *regex;  public: + +	LexInterface *pli; +  	int stylingBits;  	int stylingBitsMask; @@ -197,12 +215,20 @@ public:  	virtual void InsertLine(int line);  	virtual void RemoveLine(int line); -	int LineFromPosition(int pos) const; +	int SCI_METHOD Version() const { +		return dvOriginal; +	} + +	void SCI_METHOD SetErrorStatus(int status); + +	int SCI_METHOD LineFromPosition(int pos) const;  	int ClampPositionIntoDocument(int pos);  	bool IsCrLf(int pos);  	int LenChar(int pos);  	bool InGoodUTF8(int pos, int &start, int &end);  	int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true); +	int SCI_METHOD CodePage() const; +	bool SCI_METHOD IsDBCSLeadByte(char ch) const;  	// Gateways to modifying document  	void ModifiedAt(int pos); @@ -243,10 +269,10 @@ public:  	void DelCharBack(int pos);  	char CharAt(int position) { return cb.CharAt(position); } -	void GetCharRange(char *buffer, int position, int lengthRetrieve) const { +	void SCI_METHOD GetCharRange(char *buffer, int position, int lengthRetrieve) const {  		cb.GetCharRange(buffer, position, lengthRetrieve);  	} -	char StyleAt(int position) const { return cb.StyleAt(position); } +	char SCI_METHOD StyleAt(int position) const { return cb.StyleAt(position); }  	int GetMark(int line);  	int AddMark(int line, int markerNum);  	void AddMarkSet(int line, int valueSet); @@ -254,14 +280,14 @@ public:  	void DeleteMarkFromHandle(int markerHandle);  	void DeleteAllMarks(int markerNum);  	int LineFromHandle(int markerHandle); -	int LineStart(int line) const; +	int SCI_METHOD LineStart(int line) const;  	int LineEnd(int line) const;  	int LineEndPosition(int position) const;  	bool IsLineEndPosition(int position) const;  	int VCHomePosition(int position) const; -	int SetLevel(int line, int level); -	int GetLevel(int line) const; +	int SCI_METHOD SetLevel(int line, int level); +	int SCI_METHOD GetLevel(int line) const;  	void ClearLevels();  	int GetLastChild(int lineParent, int level=-1);  	int GetFoldParent(int line); @@ -270,7 +296,7 @@ public:  	int ExtendWordSelect(int pos, int delta, bool onlyWordCharacters=false);  	int NextWordStart(int pos, int delta);  	int NextWordEnd(int pos, int delta); -	int Length() const { return cb.Length(); } +	int SCI_METHOD Length() const { return cb.Length(); }  	void Allocate(int newSize) { cb.Allocate(newSize); }  	size_t ExtractChar(int pos, char *bytes);  	bool MatchesWordOptions(bool word, bool wordStart, int pos, int length); @@ -284,18 +310,23 @@ public:  	void SetDefaultCharClasses(bool includeWordClass);  	void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass);  	void SetStylingBits(int bits); -	void StartStyling(int position, char mask); -	bool SetStyleFor(int length, char style); -	bool SetStyles(int length, const char *styles); +	void SCI_METHOD StartStyling(int position, char mask); +	bool SCI_METHOD SetStyleFor(int length, char style); +	bool SCI_METHOD SetStyles(int length, const char *styles);  	int GetEndStyled() { return endStyled; }  	void EnsureStyledTo(int pos); +	void LexerChanged();  	int GetStyleClock() { return styleClock; }  	void IncrementStyleClock(); -	void DecorationFillRange(int position, int value, int fillLength); +	void SCI_METHOD DecorationSetCurrentIndicator(int indicator) { +		decorations.SetCurrentIndicator(indicator); +	} +	void SCI_METHOD DecorationFillRange(int position, int value, int fillLength); -	int SetLineState(int line, int state); -	int GetLineState(int line) const; +	int SCI_METHOD SetLineState(int line, int state); +	int SCI_METHOD GetLineState(int line) const;  	int GetMaxLineState(); +	void SCI_METHOD ChangeLexerState(int start, int end);  	StyledText MarginStyledText(int line);  	void MarginSetStyle(int line, int style); @@ -417,6 +448,8 @@ public:  	virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0;  	virtual void NotifyDeleted(Document *doc, void *userData) = 0;  	virtual void NotifyStyleNeeded(Document *doc, void *userData, int endPos) = 0; +	virtual void NotifyLexerChanged(Document *doc, void *userData) = 0; +	virtual void NotifyErrorOccurred(Document *doc, void *userData, int status) = 0;  };  #ifdef SCI_NAMESPACE diff --git a/src/Editor.cxx b/src/Editor.cxx index 6119944c3..be63ea839 100644 --- a/src/Editor.cxx +++ b/src/Editor.cxx @@ -9,6 +9,7 @@  #include <string.h>  #include <stdio.h>  #include <ctype.h> +#include <assert.h>  #include <string>  #include <vector> @@ -25,6 +26,7 @@  #include "Platform.h" +#include "ILexer.h"  #include "Scintilla.h"  #include "SplitVector.h" @@ -4132,6 +4134,13 @@ void Editor::NotifyStyleNeeded(Document *, void *, int endStyleNeeded) {  	NotifyStyleToNeeded(endStyleNeeded);  } +void Editor::NotifyLexerChanged(Document *, void *) { +} + +void Editor::NotifyErrorOccurred(Document *, void *, int status) { +	errorStatus = status; +} +  void Editor::NotifyChar(int ch) {  	SCNotification scn = {0};  	scn.nmhdr.code = SCN_CHARADDED; @@ -4315,6 +4324,14 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) {  			Redraw();  		}  	} +	if (mh.modificationType & SC_MOD_LEXERSTATE) { +		if (paintState == painting) { +			CheckForChangeOutsidePaint( +			    Range(mh.position, mh.position + mh.length)); +		} else { +			Redraw(); +		} +	}  	if (mh.modificationType & (SC_MOD_CHANGESTYLE | SC_MOD_CHANGEINDICATOR)) {  		if (mh.modificationType & SC_MOD_CHANGESTYLE) {  			pdoc->IncrementStyleClock(); @@ -8711,6 +8728,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  		sel.RangeMain() = SelectionRange(sel.RangeMain().anchor, sel.RangeMain().caret);  		break; +	case SCI_CHANGELEXERSTATE: +		pdoc->ChangeLexerState(wParam, lParam); +		break; +  	default:  		return DefWndProc(iMessage, wParam, lParam);  	} diff --git a/src/Editor.h b/src/Editor.h index e7aa2e6ce..aa4fc9236 100644 --- a/src/Editor.h +++ b/src/Editor.h @@ -431,6 +431,8 @@ protected:	// ScintillaBase subclass needs access to much of Editor  	void NotifyModified(Document *document, DocModification mh, void *userData);  	void NotifyDeleted(Document *document, void *userData);  	void NotifyStyleNeeded(Document *doc, void *userData, int endPos); +	void NotifyLexerChanged(Document *doc, void *userData); +	void NotifyErrorOccurred(Document *doc, void *userData, int status);  	void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam);  	void PageMove(int direction, Selection::selTypes sel=Selection::noSel, bool stuttered = false); diff --git a/src/ExternalLexer.cxx b/src/ExternalLexer.cxx index 1c00ec02e..ba0f52ab3 100644 --- a/src/ExternalLexer.cxx +++ b/src/ExternalLexer.cxx @@ -9,18 +9,18 @@  #include <stdio.h>  #include <string.h>  #include <ctype.h> +#include <assert.h>  #include <string>  #include "Platform.h" +#include "ILexer.h"  #include "Scintilla.h" -  #include "SciLexer.h" -#include "PropSet.h" -#include "Accessor.h" -#include "DocumentAccessor.h" -#include "KeyWords.h" + +#include "LexerModule.h" +#include "Catalogue.h"  #include "ExternalLexer.h"  #ifdef SCI_NAMESPACE @@ -35,76 +35,9 @@ LexerManager *LexerManager::theInstance = NULL;  //  //------------------------------------------ -char **WordListsToStrings(WordList *val[]) { -	int dim = 0; -	while (val[dim]) -		dim++; -	char **wls = new char * [dim + 1]; -	for (int i = 0; i < dim; i++) { -		std::string 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) const { -	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) const { -	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; +void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) { +	fneFactory = fFactory; +	fnFactory = fFactory(index);  	externalLanguage = index;  } @@ -132,8 +65,9 @@ LexerLibrary::LexerLibrary(const char *ModuleName) {  			// Find functions in the DLL  			GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName"); -			ExtLexerFunction Lexer = (ExtLexerFunction)(sptr_t)lib->FindFunction("Lex"); -			ExtFoldFunction Folder = (ExtFoldFunction)(sptr_t)lib->FindFunction("Fold"); +			//ExtLexerFunction fnLexer = (ExtLexerFunction)(sptr_t)lib->FindFunction("Lex"); +			//ExtFoldFunction fnFolder = (ExtFoldFunction)(sptr_t)lib->FindFunction("Fold"); +			GetLexerFactoryFunction fnFactory = (GetLexerFactoryFunction)(sptr_t)lib->FindFunction("GetLexerFactory");  			// Assign a buffer for the lexer name.  			char lexname[100]; @@ -144,6 +78,7 @@ LexerLibrary::LexerLibrary(const char *ModuleName) {  			for (int i = 0; i < nl; i++) {  				GetLexerName(i, lexname, 100);  				lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL); +				Catalogue::AddLexerModule(lex);  				// Create a LexerMinder so we don't leak the ExternalLexerModule...  				lm = new LexerMinder; @@ -158,8 +93,8 @@ LexerLibrary::LexerLibrary(const char *ModuleName) {  				}  				// 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); +				// do its lexing and folding, we tell it here. +				lex->SetExternal(fnFactory, i);  			}  		}  	} diff --git a/src/ExternalLexer.h b/src/ExternalLexer.h index eb2bad5d1..98d543ef1 100644 --- a/src/ExternalLexer.h +++ b/src/ExternalLexer.h @@ -18,22 +18,15 @@  namespace Scintilla {  #endif -// External Lexer function definitions... -typedef void (EXT_LEXER_DECL *ExtLexerFunction)(unsigned int lexer, unsigned int startPos, int length, int initStyle, -                  char *words[], WindowID window, char *props); -typedef void (EXT_LEXER_DECL *ExtFoldFunction)(unsigned int lexer, unsigned int startPos, int length, int initStyle, -                  char *words[], WindowID window, char *props);  typedef void*(EXT_LEXER_DECL *GetLexerFunction)(unsigned int Index);  typedef int (EXT_LEXER_DECL *GetLexerCountFn)();  typedef void (EXT_LEXER_DECL *GetLexerNameFn)(unsigned int Index, char *name, int buflength); - -//class DynamicLibrary; +typedef LexerFactoryFunction(EXT_LEXER_DECL *GetLexerFactoryFunction)(unsigned int Index);  /// Sub-class of LexerModule to use an external lexer. -class ExternalLexerModule : protected LexerModule { +class ExternalLexerModule : public LexerModule {  protected: -	ExtLexerFunction fneLexer; -	ExtFoldFunction fneFolder; +	GetLexerFactoryFunction fneFactory;  	int externalLanguage;  	char name[100];  public: @@ -43,11 +36,7 @@ public:  		name[sizeof(name)-1] = '\0';  		languageName = name;  	} -	virtual void Lex(unsigned int startPos, int lengthDoc, int initStyle, -					WordList *keywordlists[], Accessor &styler) const; -	virtual void Fold(unsigned int startPos, int lengthDoc, int initStyle, -					WordList *keywordlists[], Accessor &styler) const; -	virtual void SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index); +	virtual void SetExternal(GetLexerFactoryFunction fFactory, int index);  };  /// LexerMinder points to an ExternalLexerModule - so we don't leak them. diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx index d27205b5f..548b4d940 100644 --- a/src/PositionCache.cxx +++ b/src/PositionCache.cxx @@ -30,6 +30,7 @@  #include "ViewStyle.h"  #include "CharClassify.h"  #include "Decoration.h" +#include "ILexer.h"  #include "Document.h"  #include "Selection.h"  #include "PositionCache.h" diff --git a/src/ScintillaBase.cxx b/src/ScintillaBase.cxx index cecfc0952..2f84db7cd 100644 --- a/src/ScintillaBase.cxx +++ b/src/ScintillaBase.cxx @@ -9,20 +9,21 @@  #include <string.h>  #include <stdio.h>  #include <ctype.h> +#include <assert.h>  #include <string>  #include <vector>  #include "Platform.h" +#include "ILexer.h"  #include "Scintilla.h" -#include "PropSet.h" +  #include "PropSetSimple.h"  #ifdef SCI_LEXER  #include "SciLexer.h" -#include "Accessor.h" -#include "DocumentAccessor.h" -#include "KeyWords.h" +#include "LexerModule.h" +#include "Catalogue.h"  #endif  #include "SplitVector.h"  #include "Partitioning.h" @@ -53,21 +54,9 @@ ScintillaBase::ScintillaBase() {  	displayPopupMenu = true;  	listType = 0;  	maxListWidth = 0; -#ifdef SCI_LEXER -	lexLanguage = SCLEX_CONTAINER; -	performingStyle = false; -	lexCurrent = 0; -	for (int wl = 0; wl < numWordLists; wl++) -		keyWordLists[wl] = new WordList; -	keyWordLists[numWordLists] = 0; -#endif  }  ScintillaBase::~ScintillaBase() { -#ifdef SCI_LEXER -	for (int wl = 0; wl < numWordLists; wl++) -		delete keyWordLists[wl]; -#endif  }  void ScintillaBase::Finalise() { @@ -477,76 +466,189 @@ void ScintillaBase::ButtonDown(Point pt, unsigned int curTime, bool shift, bool  }  #ifdef SCI_LEXER -void ScintillaBase::SetLexer(uptr_t wParam) { -	lexLanguage = wParam; -	lexCurrent = LexerModule::Find(lexLanguage); -	if (!lexCurrent) -		lexCurrent = LexerModule::Find(SCLEX_NULL); -	int bits = lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5; -	vs.EnsureStyle((1 << bits) - 1); + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +class LexState : public LexInterface { +	const LexerModule *lexCurrent; +	void SetLexerModule(const LexerModule *lex); +	PropSetSimple props; +public: +	int lexLanguage; + +	LexState(Document *pdoc_); +	virtual ~LexState(); +	void SetLexer(uptr_t wParam); +	void SetLexerLanguage(const char *languageName); +	const char *DescribeWordListSets(); +	void SetWordList(int n, const char *wl); +	int GetStyleBitsNeeded() const; +	const char *GetName() const; +	void *PrivateCall(int operation, void *pointer); +	const char *PropertyNames(); +	int PropertyType(const char *name); +	const char *DescribeProperty(const char *name); +	void PropSet(const char *key, const char *val); +	const char *PropGet(const char *key) const; +	int PropGetInt(const char *key, int defaultValue=0) const; +	int PropGetExpanded(const char *key, char *result) const; +}; + +#ifdef SCI_NAMESPACE  } +#endif -void ScintillaBase::SetLexerLanguage(const char *languageName) { +LexState::LexState(Document *pdoc_) : LexInterface(pdoc_) { +	lexCurrent = 0; +	performingStyle = false;  	lexLanguage = SCLEX_CONTAINER; -	lexCurrent = LexerModule::Find(languageName); -	if (!lexCurrent) -		lexCurrent = LexerModule::Find(SCLEX_NULL); -	if (lexCurrent) -		lexLanguage = lexCurrent->GetLanguage(); -	int bits = lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5; -	vs.EnsureStyle((1 << bits) - 1);  } -void ScintillaBase::Colourise(int start, int end) { -	if (!performingStyle) { -		// Protect against reentrance, which may occur, for example, when -		// fold points are discovered while performing styling and the folding -		// code looks for child lines which may trigger styling. -		performingStyle = true; +LexState::~LexState() { +	if (instance) { +		instance->Release(); +		instance = 0; +	} +} + +LexState *ScintillaBase::DocumentLexState() { +	if (!pdoc->pli) { +		pdoc->pli = new LexState(pdoc); +	} +	return static_cast<LexState *>(pdoc->pli); +} -		int lengthDoc = pdoc->Length(); -		if (end == -1) -			end = lengthDoc; -		int len = end - start; +void LexState::SetLexerModule(const LexerModule *lex) { +	if (lex != lexCurrent) { +		if (instance) { +			instance->Release(); +			instance = 0; +		} +		lexCurrent = lex; +		instance = lexCurrent->Create(); +		pdoc->LexerChanged(); +	} +} -		PLATFORM_ASSERT(len >= 0); -		PLATFORM_ASSERT(start + len <= lengthDoc); +void LexState::SetLexer(uptr_t wParam) { +	lexLanguage = wParam; +	const LexerModule *lex = Catalogue::Find(lexLanguage); +	if (!lex) +		lex = Catalogue::Find(SCLEX_NULL); +	SetLexerModule(lex); +} -		//WindowAccessor styler(wMain.GetID(), props); -		DocumentAccessor styler(pdoc, props, wMain.GetID()); +void LexState::SetLexerLanguage(const char *languageName) { +	const LexerModule *lex = Catalogue::Find(languageName); +	if (!lex) +		lex = Catalogue::Find(SCLEX_NULL); +	if (lex) +		lexLanguage = lex->GetLanguage(); +	SetLexerModule(lex); +} -		int styleStart = 0; -		if (start > 0) -			styleStart = styler.StyleAt(start - 1) & pdoc->stylingBitsMask; -		styler.SetCodePage(pdoc->dbcsCodePage); +const char *LexState::DescribeWordListSets() { +	if (instance) { +		return instance->DescribeWordListSets(); +	} else { +		return 0; +	} +} -		if (lexCurrent && (len > 0)) {	// Should always succeed as null lexer should always be available -			lexCurrent->Lex(start, len, styleStart, keyWordLists, styler); -			styler.Flush(); -			if (styler.GetPropertyInt("fold")) { -				lexCurrent->Fold(start, len, styleStart, keyWordLists, styler); -				styler.Flush(); -			} +void LexState::SetWordList(int n, const char *wl) { +	if (instance) { +		int firstModification = instance->WordListSet(n, wl); +		if (firstModification >= 0) { +			pdoc->ModifiedAt(firstModification);  		} +	} +} -		performingStyle = false; +int LexState::GetStyleBitsNeeded() const { +	return lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5; +} + +const char *LexState::GetName() const { +	return lexCurrent ? lexCurrent->languageName : ""; +} + +void *LexState::PrivateCall(int operation, void *pointer) { +	if (pdoc && instance) { +		return instance->PrivateCall(operation, pointer); +	} else { +		return 0; +	} +} + +const char *LexState::PropertyNames() { +	if (instance) { +		return instance->PropertyNames(); +	} else { +		return 0; +	} +} + +int LexState::PropertyType(const char *name) { +	if (instance) { +		return instance->PropertyType(name); +	} else { +		return SC_TYPE_BOOLEAN;  	}  } + +const char *LexState::DescribeProperty(const char *name) { +	if (instance) { +		return instance->DescribeProperty(name); +	} else { +		return 0; +	} +} + +void LexState::PropSet(const char *key, const char *val) { +	props.Set(key, val); +	if (instance) { +		int firstModification = instance->PropertySet(key, val); +		if (firstModification >= 0) { +			pdoc->ModifiedAt(firstModification); +		} +	} +} + +const char *LexState::PropGet(const char *key) const { +	return props.Get(key); +} + +int LexState::PropGetInt(const char *key, int defaultValue) const { +	return props.GetInt(key, defaultValue); +} + +int LexState::PropGetExpanded(const char *key, char *result) const { +	return props.GetExpanded(key, result); +} +  #endif  void ScintillaBase::NotifyStyleToNeeded(int endStyleNeeded) {  #ifdef SCI_LEXER -	if (lexLanguage != SCLEX_CONTAINER) { -		int endStyled = WndProc(SCI_GETENDSTYLED, 0, 0); -		int lineEndStyled = WndProc(SCI_LINEFROMPOSITION, endStyled, 0); -		endStyled = WndProc(SCI_POSITIONFROMLINE, lineEndStyled, 0); -		Colourise(endStyled, endStyleNeeded); +	if (DocumentLexState()->lexLanguage != SCLEX_CONTAINER) { +		int lineEndStyled = pdoc->LineFromPosition(pdoc->GetEndStyled()); +		int endStyled = pdoc->LineStart(lineEndStyled); +		DocumentLexState()->Colourise(endStyled, endStyleNeeded);  		return;  	}  #endif  	Editor::NotifyStyleToNeeded(endStyleNeeded);  } +void ScintillaBase::NotifyLexerChanged(Document *, void *) { +#ifdef SCI_LEXER +	int bits = DocumentLexState()->GetStyleBitsNeeded(); +	vs.EnsureStyle((1 << bits) - 1); +#endif +} +  sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {  	switch (iMessage) {  	case SCI_AUTOCSHOW: @@ -709,61 +811,66 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara  #ifdef SCI_LEXER  	case SCI_SETLEXER: -		SetLexer(wParam); -		lexLanguage = wParam; +		DocumentLexState()->SetLexer(wParam);  		break;  	case SCI_GETLEXER: -		return lexLanguage; +		return DocumentLexState()->lexLanguage;  	case SCI_COLOURISE: -		if (lexLanguage == SCLEX_CONTAINER) { +		if (DocumentLexState()->lexLanguage == SCLEX_CONTAINER) {  			pdoc->ModifiedAt(wParam);  			NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : lParam);  		} else { -			Colourise(wParam, lParam); +			DocumentLexState()->Colourise(wParam, lParam);  		}  		Redraw();  		break;  	case SCI_SETPROPERTY: -		props.Set(reinterpret_cast<const char *>(wParam), +		DocumentLexState()->PropSet(reinterpret_cast<const char *>(wParam),  		          reinterpret_cast<const char *>(lParam));  		break;  	case SCI_GETPROPERTY: -			return StringResult(lParam, props.Get(reinterpret_cast<const char *>(wParam))); - -	case SCI_GETPROPERTYEXPANDED: { -			char *val = props.Expanded(reinterpret_cast<const char *>(wParam)); -			const int n = strlen(val); -			if (lParam != 0) { -				char *ptr = reinterpret_cast<char *>(lParam); -				strcpy(ptr, val); -			} -			delete []val; -			return n;	// Not including NUL -		} +		return StringResult(lParam, DocumentLexState()->PropGet(reinterpret_cast<const char *>(wParam))); + +	case SCI_GETPROPERTYEXPANDED: +		return DocumentLexState()->PropGetExpanded(reinterpret_cast<const char *>(wParam), +			reinterpret_cast<char *>(lParam));  	case SCI_GETPROPERTYINT: -		return props.GetInt(reinterpret_cast<const char *>(wParam), lParam); +		return DocumentLexState()->PropGetInt(reinterpret_cast<const char *>(wParam), lParam);  	case SCI_SETKEYWORDS: -		if (wParam < numWordLists) { -			keyWordLists[wParam]->Clear(); -			keyWordLists[wParam]->Set(reinterpret_cast<const char *>(lParam)); -		} +		DocumentLexState()->SetWordList(wParam, reinterpret_cast<const char *>(lParam));  		break;  	case SCI_SETLEXERLANGUAGE: -		SetLexerLanguage(reinterpret_cast<const char *>(lParam)); +		DocumentLexState()->SetLexerLanguage(reinterpret_cast<const char *>(lParam));  		break;  	case SCI_GETLEXERLANGUAGE: -		return StringResult(lParam, lexCurrent ? lexCurrent->languageName : ""); +		return StringResult(lParam, DocumentLexState()->GetName()); + +	case SCI_PRIVATELEXERCALL: +		return reinterpret_cast<sptr_t>( +			DocumentLexState()->PrivateCall(wParam, reinterpret_cast<void *>(lParam)));  	case SCI_GETSTYLEBITSNEEDED: -		return lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5; +		return DocumentLexState()->GetStyleBitsNeeded(); + +	case SCI_PROPERTYNAMES: +		return StringResult(lParam, DocumentLexState()->PropertyNames()); + +	case SCI_PROPERTYTYPE: +		return DocumentLexState()->PropertyType(reinterpret_cast<const char *>(wParam)); + +	case SCI_DESCRIBEPROPERTY: +		return StringResult(lParam, DocumentLexState()->DescribeProperty(reinterpret_cast<const char *>(wParam))); + +	case SCI_DESCRIBEKEYWORDSETS: +		return StringResult(lParam, DocumentLexState()->DescribeWordListSets());  #endif diff --git a/src/ScintillaBase.h b/src/ScintillaBase.h index 704ca88f8..203510844 100644 --- a/src/ScintillaBase.h +++ b/src/ScintillaBase.h @@ -12,6 +12,10 @@  namespace Scintilla {  #endif +#ifdef SCI_LEXER +class LexState; +#endif +  /**   */  class ScintillaBase : public Editor { @@ -44,12 +48,7 @@ protected:  	int maxListWidth;		/// Maximum width of list, in average character widths  #ifdef SCI_LEXER -	bool performingStyle;	///< Prevent reentrance -	int lexLanguage; -	const LexerModule *lexCurrent; -	PropSetSimple props; -	enum {numWordLists=KEYWORDSET_MAX+1}; -	WordList *keyWordLists[numWordLists+1]; +	LexState *DocumentLexState();  	void SetLexer(uptr_t wParam);  	void SetLexerLanguage(const char *languageName);  	void Colourise(int start, int end); @@ -87,7 +86,9 @@ protected:  	virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt); -	virtual void NotifyStyleToNeeded(int endStyleNeeded); +	void NotifyStyleToNeeded(int endStyleNeeded); +	void NotifyLexerChanged(Document *doc, void *userData); +  public:  	// Public so scintilla_send_message can use it  	virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); | 
