]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/stc/scintilla/src/LexTeX.cxx
Updated wxSTC's copy of Scintilla to version 1.61
[wxWidgets.git] / contrib / src / stc / scintilla / src / LexTeX.cxx
1 // Scintilla source code edit control
2
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
6
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.
9
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).
12
13 // If you run into strange boundary cases, just tell me and I'll look into it.
14
15 #include <stdlib.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <stdio.h>
19 #include <stdarg.h>
20
21 #include "Platform.h"
22
23 #include "PropSet.h"
24 #include "Accessor.h"
25 #include "KeyWords.h"
26 #include "Scintilla.h"
27 #include "SciLexer.h"
28 #include "StyleContext.h"
29
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
36
37 // Definitions in SciTEGlobal.properties:
38 //
39 // TeX Highlighting
40 //
41 // # Default
42 // style.tex.0=fore:#7F7F00
43 // # Special
44 // style.tex.1=fore:#007F7F
45 // # Group
46 // style.tex.2=fore:#880000
47 // # Symbol
48 // style.tex.3=fore:#7F7F00
49 // # Command
50 // style.tex.4=fore:#008800
51 // # Text
52 // style.tex.5=fore:#000000
53
54 // lexer.tex.interface.default=0
55 // lexer.tex.comment.process=0
56
57 // todo: lexer.tex.auto.if
58
59 // Auxiliary functions:
60
61 static inline bool endOfLine(Accessor &styler, unsigned int i) {
62 return
63 (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')) ;
64 }
65
66 static inline bool isTeXzero(int ch) {
67 return
68 (ch == '%') ;
69 }
70
71 static inline bool isTeXone(int ch) {
72 return
73 (ch == '[') || (ch == ']') || (ch == '=') || (ch == '#') ||
74 (ch == '(') || (ch == ')') || (ch == '<') || (ch == '>') ||
75 (ch == '"') ;
76 }
77
78 static inline bool isTeXtwo(int ch) {
79 return
80 (ch == '{') || (ch == '}') || (ch == '$') ;
81 }
82
83 static inline bool isTeXthree(int ch) {
84 return
85 (ch == '~') || (ch == '^') || (ch == '_') || (ch == '&') ||
86 (ch == '-') || (ch == '+') || (ch == '\"') || (ch == '`') ||
87 (ch == '/') || (ch == '|') || (ch == '%') ;
88 }
89
90 static inline bool isTeXfour(int ch) {
91 return
92 (ch == '\\') ;
93 }
94
95 static inline bool isTeXfive(int ch) {
96 return
97 ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ||
98 (ch == '@') || (ch == '!') || (ch == '?') ;
99 }
100
101 static inline bool isTeXsix(int ch) {
102 return
103 (ch == ' ') ;
104 }
105
106 static inline bool isTeXseven(int ch) {
107 return
108 (ch == '^') ;
109 }
110
111 // Interface determination
112
113 static int CheckTeXInterface(
114 unsigned int startPos,
115 int length,
116 Accessor &styler,
117 int defaultInterface) {
118
119 char lineBuffer[1024] ;
120 unsigned int linePos = 0 ;
121
122 // some day we can make something lexer.tex.mapping=(all,0)(nl,1)(en,2)...
123
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")) {
130 return 0 ;
131 } else if (strstr(lineBuffer, "interface=tex")) {
132 return 1 ;
133 } else if (strstr(lineBuffer, "interface=nl")) {
134 return 2 ;
135 } else if (strstr(lineBuffer, "interface=en")) {
136 return 3 ;
137 } else if (strstr(lineBuffer, "interface=de")) {
138 return 4 ;
139 } else if (strstr(lineBuffer, "interface=cz")) {
140 return 5 ;
141 } else if (strstr(lineBuffer, "interface=it")) {
142 return 6 ;
143 } else if (strstr(lineBuffer, "interface=ro")) {
144 return 7 ;
145 } else if (strstr(lineBuffer, "interface=latex")) {
146 // we will move latex cum suis up to 91+ when more keyword lists are supported
147 return 8 ;
148 } else if (styler.SafeGetCharAt(1) == 'D' && strstr(lineBuffer, "%D \\module")) {
149 // better would be to limit the search to just one line
150 return 3 ;
151 } else {
152 return defaultInterface ;
153 }
154 }
155 }
156 }
157
158 return defaultInterface ;
159 }
160
161 static void ColouriseTeXDoc(
162 unsigned int startPos,
163 int length,
164 int,
165 WordList *keywordlists[],
166 Accessor &styler) {
167
168 styler.StartAt(startPos) ;
169 styler.StartSegment(startPos) ;
170
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) ;
175
176 char key[100] ;
177 int k ;
178 bool newifDone = false ;
179 bool inComment = false ;
180
181 int currentInterface = CheckTeXInterface(startPos,length,styler,defaultInterface) ;
182
183 if (currentInterface == 0) {
184 useKeywords = false ;
185 currentInterface = 1 ;
186 }
187
188 WordList &keywords = *keywordlists[currentInterface-1] ;
189
190 StyleContext sc(startPos, length, SCE_TEX_TEXT, styler);
191
192 bool going = sc.More() ; // needed because of a fuzzy end of file state
193
194 for (; going; sc.Forward()) {
195
196 if (! sc.More()) { going = false ; } // we need to go one behind the end of text
197
198 if (inComment) {
199 if (sc.atLineEnd) {
200 sc.SetState(SCE_TEX_TEXT) ;
201 newifDone = false ;
202 inComment = false ;
203 }
204 } else {
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>
210 }
211 sc.ForwardSetState(SCE_TEX_TEXT) ;
212 } else {
213 sc.GetCurrent(key, sizeof(key)-1) ;
214 k = strlen(key) ;
215 memmove(key,key+1,k) ; // shift left over escape token
216 key[k] = '\0' ;
217 k-- ;
218 if (! keywords || ! useKeywords) {
219 sc.SetState(SCE_TEX_COMMAND) ;
220 newifDone = false ;
221 } else if (k == 1) { //\<cstoken>
222 sc.SetState(SCE_TEX_COMMAND) ;
223 newifDone = false ;
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) ;
229 } else {
230 sc.ChangeState(SCE_TEX_TEXT) ;
231 sc.SetState(SCE_TEX_TEXT) ;
232 newifDone = false ;
233 }
234 }
235 }
236 if (isTeXzero(sc.ch)) {
237 sc.SetState(SCE_TEX_SYMBOL) ;
238 sc.ForwardSetState(SCE_TEX_DEFAULT) ;
239 inComment = ! processComment ;
240 newifDone = false ;
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) ;
246 newifDone = false ;
247 } else if (isTeXtwo(sc.ch)) {
248 sc.SetState(SCE_TEX_GROUP) ;
249 newifDone = false ;
250 } else if (isTeXthree(sc.ch)) {
251 sc.SetState(SCE_TEX_SYMBOL) ;
252 newifDone = false ;
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) ;
259 newifDone = false ;
260 inComment = false ;
261 } else {
262 sc.SetState(SCE_TEX_TEXT) ;
263 }
264 } else if (sc.state != SCE_TEX_COMMAND) {
265 sc.SetState(SCE_TEX_TEXT) ;
266 }
267 }
268 }
269 sc.ChangeState(SCE_TEX_TEXT) ;
270 sc.Complete();
271
272 }
273
274
275 // Hooks into the system:
276
277 static const char * const texWordListDesc[] = {
278 "TeX, eTeX, pdfTeX, Omega"
279 "ConTeXt Dutch",
280 "ConTeXt English",
281 "ConTeXt German",
282 "ConTeXt Czech",
283 "ConTeXt Italian",
284 "ConTeXt Romanian",
285 0,
286 } ;
287
288 LexerModule lmTeX(SCLEX_TEX, ColouriseTeXDoc, "tex", 0, texWordListDesc);