diff options
| -rw-r--r-- | src/LexGui4Cli.cxx | 309 | 
1 files changed, 309 insertions, 0 deletions
| diff --git a/src/LexGui4Cli.cxx b/src/LexGui4Cli.cxx new file mode 100644 index 000000000..2e3c02c1c --- /dev/null +++ b/src/LexGui4Cli.cxx @@ -0,0 +1,309 @@ +// Scintilla source code edit control +// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> +/* +This is the Lexer for Gui4Cli, included in SciLexer.dll +- by d. Keletsekis, 2/10/2003 + +To add to SciLexer.dll: +1. Add the values below to INCLUDE\Scintilla.iface +2. Run the include/HFacer.py script +3. Run the src/lexGen.py script + +val SCE_GC_DEFAULT=0 +val SCE_GC_COMMENTLINE=1 +val SCE_GC_COMMENTBLOCK=2 +val SCE_GC_GLOBAL=3 +val SCE_GC_EVENT=4 +val SCE_GC_ATTRIBUTE=5 +val SCE_GC_CONTROL=6 +val SCE_GC_COMMAND=7 +val SCE_GC_STRING=8 +val SCE_GC_OPERATOR=9 +*/ + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdarg.h> + +#include "Platform.h" + +#include "PropSet.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "KeyWords.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#define debug Platform::DebugPrintf + +static inline bool IsAWordChar(const int ch) { +	return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch =='\\'); +} + +static inline bool IsAWordStart(const int ch) { +	return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); +} + +inline bool isGCOperator(int ch) +{	if (isalnum(ch)) +		return false; +	// '.' left out as it is used to make up numbers +	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || +		 ch == '(' || ch == ')' || ch == '=' || ch == '%' || +		 ch == '[' || ch == ']' || ch == '<' || ch == '>' || +		 ch == ',' || ch == ';' || ch == ':') +		return true; +	return false; +} + +#define isSpace(x)		((x)==' ' || (x)=='\t') +#define isNL(x)			((x)=='\n' || (x)=='\r') +#define isSpaceOrNL(x)  (isSpace(x) || isNL(x)) +#define BUFFSIZE 500 +#define isFoldPoint(x)  ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024) + +static void colorFirstWord(WordList *keywordlists[], Accessor &styler, +									StyleContext *sc, char *buff, int length, int) +{ +	int c = 0; +	while (sc->More() && isSpaceOrNL(sc->ch)) +	{	sc->Forward(); +	} +	styler.ColourTo(sc->currentPos - 1, sc->state); + +	if (!IsAWordChar(sc->ch)) // comment, marker, etc.. +		return; + +	while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch)) +	{	buff[c] = static_cast<char>(sc->ch); +		++c; sc->Forward(); +	} +	buff[c] = '\0'; +	char *p = buff; +	while (*p)	// capitalize.. +	{	if (islower(*p)) *p = static_cast<char>(toupper(*p)); +		++p; +	} + +	WordList &kGlobal		= *keywordlists[0];	// keyword lists set by the user +	WordList &kEvent		= *keywordlists[1]; +	WordList &kAttribute	= *keywordlists[2]; +	WordList &kControl	= *keywordlists[3]; +	WordList &kCommand	= *keywordlists[4]; + +	int state = 0; +	// int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK; +	// debug ("line = %d, level = %d", line, level); + +	if	     (kGlobal.InList(buff))		state = SCE_GC_GLOBAL; +	else if (kAttribute.InList(buff))	state = SCE_GC_ATTRIBUTE; +	else if (kControl.InList(buff))		state = SCE_GC_CONTROL; +	else if (kCommand.InList(buff))		state = SCE_GC_COMMAND; +	else if (kEvent.InList(buff))			state = SCE_GC_EVENT; + +	if (state) +	{	sc->ChangeState(state); +		styler.ColourTo(sc->currentPos - 1, sc->state); +		sc->ChangeState(SCE_GC_DEFAULT); +	} +	else +	{	sc->ChangeState(SCE_GC_DEFAULT); +		styler.ColourTo(sc->currentPos - 1, sc->state); +	} +} + +// Main colorizing function called by Scintilla +static void +ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle, +                    WordList *keywordlists[], Accessor &styler) +{ +	styler.StartAt(startPos); + +	int quotestart = 0, oldstate, currentline = styler.GetLine(startPos); +	styler.StartSegment(startPos); +	bool noforward; +	char buff[BUFFSIZE+1];	// buffer for command name + +	StyleContext sc(startPos, length, initStyle, styler); +	buff[0] = '\0'; // cbuff = 0; + +	if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word.. +		colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); + +	while (sc.More()) +	{	noforward = 0; + +		switch (sc.ch) +		{ +			case '/': +				if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING) +					break; +				if (sc.chNext == '/')	// line comment +				{	sc.SetState (SCE_GC_COMMENTLINE); +					sc.Forward(); +					styler.ColourTo(sc.currentPos, sc.state); +				} +				else if (sc.chNext == '*')	// block comment +				{	sc.SetState(SCE_GC_COMMENTBLOCK); +					sc.Forward(); +					styler.ColourTo(sc.currentPos, sc.state); +				} +				else +					styler.ColourTo(sc.currentPos, sc.state); +				break; + +			case '*':	// end of comment block, or operator.. +				if (sc.state == SCE_GC_STRING) +					break; +				if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/') +				{	sc.Forward(); +					styler.ColourTo(sc.currentPos, sc.state); +					sc.ChangeState (SCE_GC_DEFAULT); +				} +				else +					styler.ColourTo(sc.currentPos, sc.state); +				break; + +			case '\'':	case '\"': // strings.. +				if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE) +					break; +				if (sc.state == SCE_GC_STRING) +				{	if (sc.ch == quotestart)	// match same quote char.. +					{	styler.ColourTo(sc.currentPos, sc.state); +						sc.ChangeState(SCE_GC_DEFAULT); +						quotestart = 0; +				}	} +				else +				{	styler.ColourTo(sc.currentPos - 1, sc.state); +					sc.ChangeState(SCE_GC_STRING); +					quotestart = sc.ch; +				} +				break; + +			case ';':	// end of commandline character +				if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && +					 sc.state != SCE_GC_STRING) +				{ +					styler.ColourTo(sc.currentPos - 1, sc.state); +					styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); +					sc.ChangeState(SCE_GC_DEFAULT); +					sc.Forward(); +					colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); +					noforward = 1; // don't move forward - already positioned at next char.. +				} +				break; + +			case '+': case '-': case '=':	case '!':	// operators.. +			case '<': case '>': case '&': case '|': case '$': +				if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE && +					 sc.state != SCE_GC_STRING) +				{ +					styler.ColourTo(sc.currentPos - 1, sc.state); +					styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); +					sc.ChangeState(SCE_GC_DEFAULT); +				} +				break; + +			case '\\':	// escape - same as operator, but also mark in strings.. +				if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE) +				{ +					oldstate = sc.state; +					styler.ColourTo(sc.currentPos - 1, sc.state); +					sc.Forward(); // mark also the next char.. +					styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR); +					sc.ChangeState(oldstate); +				} +				break; + +			case '\n': case '\r': +				++currentline; +				if (sc.state == SCE_GC_COMMENTLINE) +				{	styler.ColourTo(sc.currentPos, sc.state); +					sc.ChangeState (SCE_GC_DEFAULT); +				} +				else if (sc.state != SCE_GC_COMMENTBLOCK) +				{	colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline); +					noforward = 1; // don't move forward - already positioned at next char.. +				} +				break; + +//			case ' ': case '\t': +//			default : +		} + +		if (!noforward) sc.Forward(); + +	} +	styler.ColourTo(sc.currentPos, sc.state); +} + +// Main folding function called by Scintilla - (based on props (.ini) files function) +static void FoldGui4Cli(unsigned int startPos, int length, int, +								WordList *[], Accessor &styler) +{ +	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + +	unsigned int endPos = startPos + length; +	int visibleChars = 0; +	int lineCurrent = styler.GetLine(startPos); + +	char chNext = styler[startPos]; +	int styleNext = styler.StyleAt(startPos); +	bool headerPoint = false; + +	for (unsigned int i = startPos; i < endPos; i++) +	{ +		char ch = chNext; +		chNext = styler[i+1]; + +		int style = styleNext; +		styleNext = styler.StyleAt(i + 1); +		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + +		if (style == SCE_GC_EVENT || style == SCE_GC_GLOBAL) +		{	headerPoint = true; // fold at events and globals +		} + +		if (atEOL) +		{	int lev = SC_FOLDLEVELBASE+1; + +			if (headerPoint) +				lev = SC_FOLDLEVELBASE; + +			if (visibleChars == 0 && foldCompact) +				lev |= SC_FOLDLEVELWHITEFLAG; + +			if (headerPoint) +				lev |= SC_FOLDLEVELHEADERFLAG; + +			if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct +			{	styler.SetLevel(lineCurrent, lev); +			} + +			lineCurrent++;		// re-initialize our flags +			visibleChars = 0; +			headerPoint = false; +		} + +		if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK))) +			visibleChars++; +	} + +	int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1; +	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; +	styler.SetLevel(lineCurrent, lev | flagsNext); +} + +// I have no idea what these are for.. probably accessible by some message. +static const char * const gui4cliWordListDesc[] = { +	"Globals", "Events", "Attributes", "Control", "Commands", +	0 +}; + +// Declare language & pass our function pointers to Scintilla +LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc); + +#undef debug + | 
