]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/LexTeX.cxx
1 // Scintilla source code edit control
3 // File: LexTeX.cxx - general context conformant tex coloring scheme
4 // Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com
5 // Version: September 28, 2003
7 // Copyright: 1998-2003 by Neil Hodgson <neilh@scintilla.org>
8 // The License.txt file describes the conditions under which this software may be distributed.
10 // This lexer is derived from the one written for the texwork environment (1999++) which in
11 // turn is inspired on texedit (1991++) which finds its roots in wdt (1986).
13 // If you run into strange boundary cases, just tell me and I'll look into it.
26 #include "Scintilla.h"
28 #include "StyleContext.h"
30 // val SCE_TEX_DEFAULT = 0
31 // val SCE_TEX_SPECIAL = 1
32 // val SCE_TEX_GROUP = 2
33 // val SCE_TEX_SYMBOL = 3
34 // val SCE_TEX_COMMAND = 4
35 // val SCE_TEX_TEXT = 5
37 // Definitions in SciTEGlobal.properties:
42 // style.tex.0=fore:#7F7F00
44 // style.tex.1=fore:#007F7F
46 // style.tex.2=fore:#880000
48 // style.tex.3=fore:#7F7F00
50 // style.tex.4=fore:#008800
52 // style.tex.5=fore:#000000
54 // lexer.tex.interface.default=0
55 // lexer.tex.comment.process=0
57 // todo: lexer.tex.auto.if
59 // Auxiliary functions:
61 static inline bool endOfLine(Accessor
&styler
, unsigned int i
) {
63 (styler
[i
] == '\n') || ((styler
[i
] == '\r') && (styler
.SafeGetCharAt(i
+ 1) != '\n')) ;
66 static inline bool isTeXzero(int ch
) {
71 static inline bool isTeXone(int ch
) {
73 (ch
== '[') || (ch
== ']') || (ch
== '=') || (ch
== '#') ||
74 (ch
== '(') || (ch
== ')') || (ch
== '<') || (ch
== '>') ||
78 static inline bool isTeXtwo(int ch
) {
80 (ch
== '{') || (ch
== '}') || (ch
== '$') ;
83 static inline bool isTeXthree(int ch
) {
85 (ch
== '~') || (ch
== '^') || (ch
== '_') || (ch
== '&') ||
86 (ch
== '-') || (ch
== '+') || (ch
== '\"') || (ch
== '`') ||
87 (ch
== '/') || (ch
== '|') || (ch
== '%') ;
90 static inline bool isTeXfour(int ch
) {
95 static inline bool isTeXfive(int ch
) {
97 ((ch
>= 'a') && (ch
<= 'z')) || ((ch
>= 'A') && (ch
<= 'Z')) ||
98 (ch
== '@') || (ch
== '!') || (ch
== '?') ;
101 static inline bool isTeXsix(int ch
) {
106 static inline bool isTeXseven(int ch
) {
111 // Interface determination
113 static int CheckTeXInterface(
114 unsigned int startPos
,
117 int defaultInterface
) {
119 char lineBuffer
[1024] ;
120 unsigned int linePos
= 0 ;
122 // some day we can make something lexer.tex.mapping=(all,0)(nl,1)(en,2)...
124 if (styler
.SafeGetCharAt(0) == '%') {
125 for (unsigned int i
= 0; i
< startPos
+ length
; i
++) {
126 lineBuffer
[linePos
++] = styler
.SafeGetCharAt(i
) ;
127 if (endOfLine(styler
, i
) || (linePos
>= sizeof(lineBuffer
) - 1)) {
128 lineBuffer
[linePos
] = '\0';
129 if (strstr(lineBuffer
, "interface=all")) {
131 } else if (strstr(lineBuffer
, "interface=tex")) {
133 } else if (strstr(lineBuffer
, "interface=nl")) {
135 } else if (strstr(lineBuffer
, "interface=en")) {
137 } else if (strstr(lineBuffer
, "interface=de")) {
139 } else if (strstr(lineBuffer
, "interface=cz")) {
141 } else if (strstr(lineBuffer
, "interface=it")) {
143 } else if (strstr(lineBuffer
, "interface=ro")) {
145 } else if (strstr(lineBuffer
, "interface=latex")) {
146 // we will move latex cum suis up to 91+ when more keyword lists are supported
148 } else if (styler
.SafeGetCharAt(1) == 'D' && strstr(lineBuffer
, "%D \\module")) {
149 // better would be to limit the search to just one line
152 return defaultInterface
;
158 return defaultInterface
;
161 static void ColouriseTeXDoc(
162 unsigned int startPos
,
165 WordList
*keywordlists
[],
168 styler
.StartAt(startPos
) ;
169 styler
.StartSegment(startPos
) ;
171 bool processComment
= styler
.GetPropertyInt("lexer.tex.comment.process", 0) == 1 ;
172 bool useKeywords
= styler
.GetPropertyInt("lexer.tex.use.keywords", 1) == 1 ;
173 bool autoIf
= styler
.GetPropertyInt("lexer.tex.auto.if", 1) == 1 ;
174 int defaultInterface
= styler
.GetPropertyInt("lexer.tex.interface.default", 1) ;
178 bool newifDone
= false ;
179 bool inComment
= false ;
181 int currentInterface
= CheckTeXInterface(startPos
,length
,styler
,defaultInterface
) ;
183 if (currentInterface
== 0) {
184 useKeywords
= false ;
185 currentInterface
= 1 ;
188 WordList
&keywords
= *keywordlists
[currentInterface
-1] ;
190 StyleContext
sc(startPos
, length
, SCE_TEX_TEXT
, styler
);
192 bool going
= sc
.More() ; // needed because of a fuzzy end of file state
194 for (; going
; sc
.Forward()) {
196 if (! sc
.More()) { going
= false ; } // we need to go one behind the end of text
200 sc
.SetState(SCE_TEX_TEXT
) ;
205 if (! isTeXfive(sc
.ch
)) {
206 if (sc
.state
== SCE_TEX_COMMAND
) {
207 if (sc
.LengthCurrent() == 1) { // \<noncstoken>
208 if (isTeXseven(sc
.ch
) && isTeXseven(sc
.chNext
)) {
209 sc
.Forward(2) ; // \^^ and \^^<token>
211 sc
.ForwardSetState(SCE_TEX_TEXT
) ;
213 sc
.GetCurrent(key
, sizeof(key
)-1) ;
215 memmove(key
,key
+1,k
) ; // shift left over escape token
218 if (! keywords
|| ! useKeywords
) {
219 sc
.SetState(SCE_TEX_COMMAND
) ;
221 } else if (k
== 1) { //\<cstoken>
222 sc
.SetState(SCE_TEX_COMMAND
) ;
224 } else if (keywords
.InList(key
)) {
225 sc
.SetState(SCE_TEX_COMMAND
) ;
226 newifDone
= autoIf
&& (strcmp(key
,"newif") == 0) ;
227 } else if (autoIf
&& ! newifDone
&& (key
[0] == 'i') && (key
[1] == 'f') && keywords
.InList("if")) {
228 sc
.SetState(SCE_TEX_COMMAND
) ;
230 sc
.ChangeState(SCE_TEX_TEXT
) ;
231 sc
.SetState(SCE_TEX_TEXT
) ;
236 if (isTeXzero(sc
.ch
)) {
237 sc
.SetState(SCE_TEX_SYMBOL
) ;
238 sc
.ForwardSetState(SCE_TEX_DEFAULT
) ;
239 inComment
= ! processComment
;
241 } else if (isTeXseven(sc
.ch
) && isTeXseven(sc
.chNext
)) {
242 sc
.SetState(SCE_TEX_TEXT
) ;
243 sc
.ForwardSetState(SCE_TEX_TEXT
) ;
244 } else if (isTeXone(sc
.ch
)) {
245 sc
.SetState(SCE_TEX_SPECIAL
) ;
247 } else if (isTeXtwo(sc
.ch
)) {
248 sc
.SetState(SCE_TEX_GROUP
) ;
250 } else if (isTeXthree(sc
.ch
)) {
251 sc
.SetState(SCE_TEX_SYMBOL
) ;
253 } else if (isTeXfour(sc
.ch
)) {
254 sc
.SetState(SCE_TEX_COMMAND
) ;
255 } else if (isTeXsix(sc
.ch
)) {
256 sc
.SetState(SCE_TEX_TEXT
) ;
257 } else if (sc
.atLineEnd
) {
258 sc
.SetState(SCE_TEX_TEXT
) ;
262 sc
.SetState(SCE_TEX_TEXT
) ;
264 } else if (sc
.state
!= SCE_TEX_COMMAND
) {
265 sc
.SetState(SCE_TEX_TEXT
) ;
269 sc
.ChangeState(SCE_TEX_TEXT
) ;
275 // Hooks into the system:
277 static const char * const texWordListDesc
[] = {
278 "TeX, eTeX, pdfTeX, Omega"
288 LexerModule
lmTeX(SCLEX_TEX
, ColouriseTeXDoc
, "tex", 0, texWordListDesc
);