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); |