diff options
Diffstat (limited to 'src/LexTeX.cxx')
| -rw-r--r-- | src/LexTeX.cxx | 270 | 
1 files changed, 110 insertions, 160 deletions
| diff --git a/src/LexTeX.cxx b/src/LexTeX.cxx index 21a4d3944..a5b094670 100644 --- a/src/LexTeX.cxx +++ b/src/LexTeX.cxx @@ -2,7 +2,7 @@  // File: LexTeX.cxx - general context conformant tex coloring scheme  // Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com -// Version: August 18, 2003 +// Version: September 28, 2003  // Copyright: 1998-2003 by Neil Hodgson <neilh@scintilla.org>  // The License.txt file describes the conditions under which this software may be distributed. @@ -10,6 +10,8 @@  // This lexer is derived from the one written for the texwork environment (1999++) which in  // turn is inspired on texedit (1991++) which finds its roots in wdt (1986). +// If you run into strange boundary cases, just tell me and I'll look into it. +  #include <stdlib.h>  #include <string.h>  #include <ctype.h> @@ -52,6 +54,8 @@  // lexer.tex.interface.default=0  // lexer.tex.comment.process=0 +// todo: lexer.tex.auto.if +  // Auxiliary functions:  static inline bool endOfLine(Accessor &styler, unsigned int i) { @@ -59,187 +63,67 @@ static inline bool endOfLine(Accessor &styler, unsigned int i) {        (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')) ;  } -static inline bool isTeXzero(char ch) { +static inline bool isTeXzero(int ch) {  	return        (ch == '%') ;  } -static inline bool isTeXone(char ch) { +static inline bool isTeXone(int ch) {  	return        (ch == '[') || (ch == ']') || (ch == '=') || (ch == '#') ||        (ch == '(') || (ch == ')') || (ch == '<') || (ch == '>') ||        (ch == '"') ;  } -static inline bool isTeXtwo(char ch) { +static inline bool isTeXtwo(int ch) {  	return        (ch == '{') || (ch == '}') || (ch == '$') ;  } -static inline bool isTeXthree(char ch) { +static inline bool isTeXthree(int ch) {  	return        (ch == '~') || (ch == '^') || (ch == '_') || (ch == '&') ||        (ch == '-') || (ch == '+') || (ch == '\"') || (ch == '`') ||        (ch == '/') || (ch == '|') || (ch == '%') ;  } -static inline bool isTeXfour(char ch) { +static inline bool isTeXfour(int ch) {  	return        (ch == '\\') ;  } -static inline bool isTeXfive(char ch) { +static inline bool isTeXfive(int ch) {  	return        ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ||        (ch == '@') || (ch == '!') || (ch == '?') ;  } -static inline bool isTeXsix(char ch) { +static inline bool isTeXsix(int ch) {  	return        (ch == ' ') ;  } - -// Coloring functions: - -bool newifDone = false ; - -static void ColourTeXRange( -    unsigned int texMode, -    char *key, -    unsigned int endPos, -    WordList &keywords, -    bool useKeywords, -    Accessor &styler) { - -    bool autoIf = true ; - -    switch (texMode) { -        case 0 : -            styler.ColourTo(endPos, SCE_TEX_DEFAULT) ; -			newifDone = false ; -            break ; -        case 1 : -            styler.ColourTo(endPos, SCE_TEX_SPECIAL) ; -			newifDone = false ; -            break ; -        case 2 : -            styler.ColourTo(endPos, SCE_TEX_GROUP) ; -			newifDone = false ; -            break ; -        case 3 : -            styler.ColourTo(endPos, SCE_TEX_SYMBOL) ; -			newifDone = false ; -            break ; -        case 4 : -            if (! keywords || ! useKeywords) { -                styler.ColourTo(endPos, SCE_TEX_COMMAND) ; -				newifDone = false ; -            } else if (key[1] == '\0') { -                styler.ColourTo(endPos, SCE_TEX_COMMAND) ; -				newifDone = false ; -            } else if (keywords.InList(key)) { -                styler.ColourTo(endPos, SCE_TEX_COMMAND) ; -				newifDone = autoIf && (strcmp(key,"newif") == 0) ; -            } else if (autoIf && ! newifDone && (key[0] == 'i') && (key[1] == 'f') && keywords.InList("if")) { -                styler.ColourTo(endPos, SCE_TEX_COMMAND) ; -			} else { -                styler.ColourTo(endPos, SCE_TEX_TEXT) ; -				newifDone = false ; -            } -            break ; -        case 5 : -            styler.ColourTo(endPos, SCE_TEX_TEXT) ; -			newifDone = newifDone || (strspn(key," ") == strlen(key)) ; -            break ; -    } - +static inline bool isTeXseven(int ch) { +	return +      (ch == '^') ;  } -static void ColouriseTeXLine( -    char *lineBuffer, -    unsigned int lengthLine, -    unsigned int startPos, -    WordList &keywords, -    bool useKeywords, -    Accessor &styler) { - -    char ch; -    bool cs = false ; -    unsigned int offset = 0 ; -    unsigned int mode = 5 ; -    unsigned int k = 0 ; -    char key[1024] ; // length check in calling routine -    unsigned int start = startPos-1 ; - -    bool comment = (styler.GetPropertyInt("lexer.tex.comment.process", 0) == 0) ; - -    // we use a cheap append to key method, ugly, but fast and ok - -    while (offset < lengthLine) { - -        ch = lineBuffer[offset] ; - -        if (cs) { -			cs = false ; -			key[k] = ch ; ++k ; key[k] = '\0' ; // ugly but ok -        } else if ((comment) && ((mode == 0) || (isTeXzero(ch)))) { -            ColourTeXRange(mode,key,start,keywords,useKeywords,styler) ; k = 0 ; -            mode = 0 ; -        } else if (isTeXone(ch)) { -            if (mode != 1) { ColourTeXRange(mode,key,start,keywords,useKeywords,styler) ; k = 0 ; } -            mode = 1 ; -        } else if (isTeXtwo(ch)) { -            if (mode != 2) { ColourTeXRange(mode,key,start,keywords,useKeywords,styler) ; k = 0 ; } -            mode = 2 ; -        } else if (isTeXthree(ch)) { -            if (mode != 3) { ColourTeXRange(mode,key,start,keywords,useKeywords,styler) ; k = 0 ; } -            mode = 3 ; -        } else if (isTeXfour(ch)) { -			if (keywords || (mode != 4)) { -                ColourTeXRange(mode,key,start,keywords,useKeywords,styler) ; k = 0 ; cs = true ; -			} -			mode = 4 ; -        } else if (isTeXfive(ch)) { -            if (mode < 4) { -				ColourTeXRange(mode,key,start,keywords,useKeywords,styler) ; k = 0 ; mode = 5 ; -	            key[k] = ch ; ++k ; key[k] = '\0' ; // ugly but ok -			} else if ((mode == 4) && (k == 1) && isTeXfour(key[0])) { -				ColourTeXRange(mode,key,start,keywords,useKeywords,styler) ; k = 0 ; mode = 5 ; -			} else { -	            key[k] = ch ; ++k ; key[k] = '\0' ; // ugly but ok -			} -        } else if (isTeXsix(ch)) { -            if (mode != 5) { ColourTeXRange(mode,key,start,keywords,useKeywords,styler) ; k = 0 ; } -            mode = 5 ; -        } else if (mode != 5) { -            ColourTeXRange(mode,key,start,keywords,useKeywords,styler) ; k = 0 ; mode = 5 ; -        } - -        ++offset ; -        ++start ; - -    } - -    ColourTeXRange(mode,key,start,keywords,useKeywords,styler) ; - -} +// Interface determination  static int CheckTeXInterface(      unsigned int startPos,      int length, -    Accessor &styler) { +    Accessor &styler, +	int defaultInterface) {      char lineBuffer[1024] ;  	unsigned int linePos = 0 ; -    int defaultInterface = styler.GetPropertyInt("lexer.tex.interface.default", 1) ; -      // some day we can make something lexer.tex.mapping=(all,0)(nl,1)(en,2)...      if (styler.SafeGetCharAt(0) == '%') {          for (unsigned int i = 0; i < startPos + length; i++) { -            lineBuffer[linePos++] = styler[i]; +            lineBuffer[linePos++] = styler.SafeGetCharAt(i) ;              if (endOfLine(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {                  lineBuffer[linePos] = '\0';                  if (strstr(lineBuffer, "interface=all")) { @@ -259,7 +143,7 @@ static int CheckTeXInterface(                  } else if (strstr(lineBuffer, "interface=ro")) {                      return 7 ;                  } else if (strstr(lineBuffer, "interface=latex")) { -					// we will move latex cum suis up to 91+ when more keyword lists are supported  +					// we will move latex cum suis up to 91+ when more keyword lists are supported                      return 8 ;  				} else if (styler.SafeGetCharAt(1) == 'D' && strstr(lineBuffer, "%D \\module")) {  					// better would be to limit the search to just one line @@ -274,26 +158,27 @@ static int CheckTeXInterface(      return defaultInterface ;  } -// Main handler: -// -// The lexer works on a per line basis. I'm not familiar with the internals of scintilla, but -// since the lexer does not look back or forward beyond the current view, some optimization can -// be accomplished by providing just the viewport. The following code is more or less copied -// from the LexOthers.cxx file. -  static void ColouriseTeXDoc(      unsigned int startPos,      int length, -    int /*initStyle*/, +    int,      WordList *keywordlists[],      Accessor &styler) {  	styler.StartAt(startPos) ;  	styler.StartSegment(startPos) ; -    int currentInterface = CheckTeXInterface(startPos,length,styler) ; +	bool processComment   = styler.GetPropertyInt("lexer.tex.comment.process",   0) == 1 ; +    bool useKeywords      = styler.GetPropertyInt("lexer.tex.use.keywords",      1) == 1 ; +	bool autoIf           = styler.GetPropertyInt("lexer.tex.auto.if",           1) == 1 ; +    int  defaultInterface = styler.GetPropertyInt("lexer.tex.interface.default", 1) ; + +	char key[100] ; +	int  k ; +	bool newifDone = false ; +	bool inComment = false ; -    bool useKeywords = true ; +	int currentInterface = CheckTeXInterface(startPos,length,styler,defaultInterface) ;      if (currentInterface == 0) {          useKeywords = false ; @@ -302,26 +187,91 @@ static void ColouriseTeXDoc(      WordList &keywords = *keywordlists[currentInterface-1] ; -	char lineBuffer[1024] ; -	unsigned int linePos = 0 ; +	StyleContext sc(startPos, length, SCE_TEX_TEXT, styler); -    for (unsigned int i = startPos; i < startPos + length; i++) { -		lineBuffer[linePos++] = styler[i] ; -		if (endOfLine(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { -			// End of line (or of line buffer) met, colourise it -			lineBuffer[linePos] = '\0' ; -			ColouriseTeXLine(lineBuffer, linePos, i-linePos+1, keywords, useKeywords, styler) ; -			linePos = 0 ; -		} -	} +	bool going = sc.More() ; // needed because of a fuzzy end of file state + +	for (; going; sc.Forward()) { + +		if (! sc.More()) { going = false ; } // we need to go one behind the end of text -	if (linePos > 0) { -        // Last line does not have ending characters -		ColouriseTeXLine(lineBuffer, linePos, startPos+length-linePos, keywords, useKeywords, styler) ; +		if (inComment) { +			if (sc.atLineEnd) { +				sc.SetState(SCE_TEX_TEXT) ; +				newifDone = false ; +				inComment = false ; +			} +		} else { +			if (! isTeXfive(sc.ch)) { +				if (sc.state == SCE_TEX_COMMAND) { +					if (sc.LengthCurrent() == 1) { // \<noncstoken> +						if (isTeXseven(sc.ch) && isTeXseven(sc.chNext)) { +							sc.Forward(2) ; // \^^ and \^^<token> +						} +						sc.ForwardSetState(SCE_TEX_TEXT) ; +					} else { +						sc.GetCurrent(key, sizeof(key)-1) ; +						k = strlen(key) ; +						memmove(key,key+1,k) ; // shift left over escape token +						key[k] = '\0' ; +						k-- ; +						if (! keywords || ! useKeywords) { +							sc.SetState(SCE_TEX_COMMAND) ; +							newifDone = false ; +						} else if (k == 1) { //\<cstoken> +							sc.SetState(SCE_TEX_COMMAND) ; +							newifDone = false ; +						} else if (keywords.InList(key)) { +    						sc.SetState(SCE_TEX_COMMAND) ; +							newifDone = autoIf && (strcmp(key,"newif") == 0) ; +						} else if (autoIf && ! newifDone && (key[0] == 'i') && (key[1] == 'f') && keywords.InList("if")) { +	    					sc.SetState(SCE_TEX_COMMAND) ; +						} else { +							sc.ChangeState(SCE_TEX_TEXT) ; +							sc.SetState(SCE_TEX_TEXT) ; +							newifDone = false ; +						} +					} +				} +				if (isTeXzero(sc.ch)) { +					sc.SetState(SCE_TEX_SYMBOL) ; +					sc.ForwardSetState(SCE_TEX_DEFAULT) ; +					inComment = ! processComment ; +					newifDone = false ; +				} else if (isTeXseven(sc.ch) && isTeXseven(sc.chNext)) { +					sc.SetState(SCE_TEX_TEXT) ; +					sc.ForwardSetState(SCE_TEX_TEXT) ; +				} else if (isTeXone(sc.ch)) { +					sc.SetState(SCE_TEX_SPECIAL) ; +					newifDone = false ; +				} else if (isTeXtwo(sc.ch)) { +					sc.SetState(SCE_TEX_GROUP) ; +					newifDone = false ; +				} else if (isTeXthree(sc.ch)) { +					sc.SetState(SCE_TEX_SYMBOL) ; +					newifDone = false ; +				} else if (isTeXfour(sc.ch)) { +					sc.SetState(SCE_TEX_COMMAND) ; +				} else if (isTeXsix(sc.ch)) { +					sc.SetState(SCE_TEX_TEXT) ; +				} else if (sc.atLineEnd) { +					sc.SetState(SCE_TEX_TEXT) ; +					newifDone = false ; +					inComment = false ; +				} else { +					sc.SetState(SCE_TEX_TEXT) ; +				} +			} else if (sc.state != SCE_TEX_COMMAND) { +				sc.SetState(SCE_TEX_TEXT) ; +			} +		}  	} +	sc.ChangeState(SCE_TEX_TEXT) ; +	sc.Complete();  } +  // Hooks into the system:  static const char * const texWordListDesc[] = { | 
