aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/LexTeX.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'src/LexTeX.cxx')
-rw-r--r--src/LexTeX.cxx270
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[] = {