Add an UI to enable/disable specific overlay handlers.
[TortoiseGit.git] / ext / scintilla / src / LexMetapost.cxx
blobba391258189c11efd7bc4a697f5a3d22b2024c9d
1 // Scintilla source code edit control
3 // File: LexMetapost.cxx - general context conformant metapost coloring scheme
4 // Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com
5 // Version: September 28, 2003
6 // Modified by instanton: July 10, 2007
7 // Folding based on keywordlists[]
9 // Copyright: 1998-2003 by Neil Hodgson <neilh@scintilla.org>
10 // The License.txt file describes the conditions under which this software may be distributed.
12 // This lexer is derived from the one written for the texwork environment (1999++) which in
13 // turn is inspired on texedit (1991++) which finds its roots in wdt (1986).
15 #include <stdlib.h>
16 #include <string.h>
17 #include <ctype.h>
18 #include <stdio.h>
19 #include <stdarg.h>
21 #include "Platform.h"
23 #include "PropSet.h"
24 #include "Accessor.h"
25 #include "KeyWords.h"
26 #include "Scintilla.h"
27 #include "SciLexer.h"
28 #include "StyleContext.h"
30 #ifdef SCI_NAMESPACE
31 using namespace Scintilla;
32 #endif
34 // val SCE_METAPOST_DEFAULT = 0
35 // val SCE_METAPOST_SPECIAL = 1
36 // val SCE_METAPOST_GROUP = 2
37 // val SCE_METAPOST_SYMBOL = 3
38 // val SCE_METAPOST_COMMAND = 4
39 // val SCE_METAPOST_TEXT = 5
41 // Definitions in SciTEGlobal.properties:
43 // Metapost Highlighting
45 // # Default
46 // style.metapost.0=fore:#7F7F00
47 // # Special
48 // style.metapost.1=fore:#007F7F
49 // # Group
50 // style.metapost.2=fore:#880000
51 // # Symbol
52 // style.metapost.3=fore:#7F7F00
53 // # Command
54 // style.metapost.4=fore:#008800
55 // # Text
56 // style.metapost.5=fore:#000000
58 // lexer.tex.comment.process=0
60 // Auxiliary functions:
62 static inline bool endOfLine(Accessor &styler, unsigned int i) {
63 return
64 (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')) ;
67 static inline bool isMETAPOSTcomment(int ch) {
68 return
69 (ch == '%') ;
72 static inline bool isMETAPOSTone(int ch) {
73 return
74 (ch == '[') || (ch == ']') || (ch == '(') || (ch == ')') ||
75 (ch == ':') || (ch == '=') || (ch == '<') || (ch == '>') ||
76 (ch == '{') || (ch == '}') || (ch == '\'') || (ch == '\"') ;
79 static inline bool isMETAPOSTtwo(int ch) {
80 return
81 (ch == ';') || (ch == '$') || (ch == '@') || (ch == '#');
84 static inline bool isMETAPOSTthree(int ch) {
85 return
86 (ch == '.') || (ch == '-') || (ch == '+') || (ch == '/') ||
87 (ch == '*') || (ch == ',') || (ch == '|') || (ch == '`') ||
88 (ch == '!') || (ch == '?') || (ch == '^') || (ch == '&') ||
89 (ch == '%') ;
92 static inline bool isMETAPOSTidentifier(int ch) {
93 return
94 ((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) ||
95 (ch == '_') ;
98 static inline bool isMETAPOSTnumber(int ch) {
99 return
100 (ch >= '0') && (ch <= '9') ;
103 static inline bool isMETAPOSTstring(int ch) {
104 return
105 (ch == '\"') ;
108 static inline bool isMETAPOSTcolon(int ch) {
109 return
110 (ch == ':') ;
113 static inline bool isMETAPOSTequal(int ch) {
114 return
115 (ch == '=') ;
118 static int CheckMETAPOSTInterface(
119 unsigned int startPos,
120 int length,
121 Accessor &styler,
122 int defaultInterface) {
124 char lineBuffer[1024] ;
125 unsigned int linePos = 0 ;
127 // some day we can make something lexer.metapost.mapping=(none,0)(metapost,1)(mp,1)(metafun,2)...
129 if (styler.SafeGetCharAt(0) == '%') {
130 for (unsigned int i = 0; i < startPos + length; i++) {
131 lineBuffer[linePos++] = styler.SafeGetCharAt(i) ;
132 if (endOfLine(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
133 lineBuffer[linePos] = '\0';
134 if (strstr(lineBuffer, "interface=none")) {
135 return 0 ;
136 } else if (strstr(lineBuffer, "interface=metapost") || strstr(lineBuffer, "interface=mp")) {
137 return 1 ;
138 } else if (strstr(lineBuffer, "interface=metafun")) {
139 return 2 ;
140 } else if (styler.SafeGetCharAt(1) == 'D' && strstr(lineBuffer, "%D \\module")) {
141 // better would be to limit the search to just one line
142 return 2 ;
143 } else {
144 return defaultInterface ;
150 return defaultInterface ;
153 static void ColouriseMETAPOSTDoc(
154 unsigned int startPos,
155 int length,
156 int,
157 WordList *keywordlists[],
158 Accessor &styler) {
160 styler.StartAt(startPos) ;
161 styler.StartSegment(startPos) ;
163 bool processComment = styler.GetPropertyInt("lexer.metapost.comment.process", 0) == 1 ;
164 int defaultInterface = styler.GetPropertyInt("lexer.metapost.interface.default", 1) ;
166 int currentInterface = CheckMETAPOSTInterface(startPos,length,styler,defaultInterface) ;
168 // 0 no keyword highlighting
169 // 1 metapost keyword hightlighting
170 // 2+ metafun keyword hightlighting
172 int extraInterface = 0 ;
174 if (currentInterface != 0) {
175 extraInterface = currentInterface ;
178 WordList &keywords = *keywordlists[0] ;
179 WordList &keywords2 = *keywordlists[extraInterface-1] ;
181 StyleContext sc(startPos, length, SCE_METAPOST_TEXT, styler) ;
183 char key[100] ;
185 bool inTeX = false ;
186 bool inComment = false ;
187 bool inString = false ;
188 bool inClause = false ;
190 bool going = sc.More() ; // needed because of a fuzzy end of file state
192 for (; going; sc.Forward()) {
194 if (! sc.More()) { going = false ; } // we need to go one behind the end of text
196 if (inClause) {
197 sc.SetState(SCE_METAPOST_TEXT) ;
198 inClause = false ;
201 if (inComment) {
202 if (sc.atLineEnd) {
203 sc.SetState(SCE_METAPOST_TEXT) ;
204 inTeX = false ;
205 inComment = false ;
206 inClause = false ;
207 inString = false ; // not correct but we want to stimulate one-lines
209 } else if (inString) {
210 if (isMETAPOSTstring(sc.ch)) {
211 sc.SetState(SCE_METAPOST_SPECIAL) ;
212 sc.ForwardSetState(SCE_METAPOST_TEXT) ;
213 inString = false ;
214 } else if (sc.atLineEnd) {
215 sc.SetState(SCE_METAPOST_TEXT) ;
216 inTeX = false ;
217 inComment = false ;
218 inClause = false ;
219 inString = false ; // not correct but we want to stimulate one-lines
221 } else {
222 if ((! isMETAPOSTidentifier(sc.ch)) && (sc.LengthCurrent() > 0)) {
223 if (sc.state == SCE_METAPOST_COMMAND) {
224 sc.GetCurrent(key, sizeof(key)) ;
225 if ((strcmp(key,"btex") == 0) || (strcmp(key,"verbatimtex") == 0)) {
226 sc.ChangeState(SCE_METAPOST_GROUP) ;
227 inTeX = true ;
228 } else if (inTeX) {
229 if (strcmp(key,"etex") == 0) {
230 sc.ChangeState(SCE_METAPOST_GROUP) ;
231 inTeX = false ;
232 } else {
233 sc.ChangeState(SCE_METAPOST_TEXT) ;
235 } else {
236 if (keywords && keywords.InList(key)) {
237 sc.ChangeState(SCE_METAPOST_COMMAND) ;
238 } else if (keywords2 && keywords2.InList(key)) {
239 sc.ChangeState(SCE_METAPOST_EXTRA) ;
240 } else {
241 sc.ChangeState(SCE_METAPOST_TEXT) ;
246 if (isMETAPOSTcomment(sc.ch)) {
247 if (! inTeX) {
248 sc.SetState(SCE_METAPOST_SYMBOL) ;
249 sc.ForwardSetState(SCE_METAPOST_DEFAULT) ;
250 inComment = ! processComment ;
251 } else {
252 sc.SetState(SCE_METAPOST_TEXT) ;
254 } else if (isMETAPOSTstring(sc.ch)) {
255 if (! inTeX) {
256 sc.SetState(SCE_METAPOST_SPECIAL) ;
257 if (! isMETAPOSTstring(sc.chNext)) {
258 sc.ForwardSetState(SCE_METAPOST_TEXT) ;
260 inString = true ;
261 } else {
262 sc.SetState(SCE_METAPOST_TEXT) ;
264 } else if (isMETAPOSTcolon(sc.ch)) {
265 if (! inTeX) {
266 if (! isMETAPOSTequal(sc.chNext)) {
267 sc.SetState(SCE_METAPOST_COMMAND) ;
268 inClause = true ;
269 } else {
270 sc.SetState(SCE_METAPOST_SPECIAL) ;
272 } else {
273 sc.SetState(SCE_METAPOST_TEXT) ;
275 } else if (isMETAPOSTone(sc.ch)) {
276 if (! inTeX) {
277 sc.SetState(SCE_METAPOST_SPECIAL) ;
278 } else {
279 sc.SetState(SCE_METAPOST_TEXT) ;
281 } else if (isMETAPOSTtwo(sc.ch)) {
282 if (! inTeX) {
283 sc.SetState(SCE_METAPOST_GROUP) ;
284 } else {
285 sc.SetState(SCE_METAPOST_TEXT) ;
287 } else if (isMETAPOSTthree(sc.ch)) {
288 if (! inTeX) {
289 sc.SetState(SCE_METAPOST_SYMBOL) ;
290 } else {
291 sc.SetState(SCE_METAPOST_TEXT) ;
293 } else if (isMETAPOSTidentifier(sc.ch)) {
294 if (sc.state != SCE_METAPOST_COMMAND) {
295 sc.SetState(SCE_METAPOST_TEXT) ;
296 sc.ChangeState(SCE_METAPOST_COMMAND) ;
298 } else if (isMETAPOSTnumber(sc.ch)) {
299 // rather redundant since for the moment we don't handle numbers
300 sc.SetState(SCE_METAPOST_TEXT) ;
301 } else if (sc.atLineEnd) {
302 sc.SetState(SCE_METAPOST_TEXT) ;
303 inTeX = false ;
304 inComment = false ;
305 inClause = false ;
306 inString = false ;
307 } else {
308 sc.SetState(SCE_METAPOST_TEXT) ;
314 sc.Complete();
318 // Hooks info the system:
320 static const char * const metapostWordListDesc[] = {
321 "MetaPost",
322 "MetaFun",
326 static int classifyFoldPointMetapost(const char* s,WordList *keywordlists[]) {
327 WordList& keywordsStart=*keywordlists[3];
328 WordList& keywordsStop1=*keywordlists[4];
330 if (keywordsStart.InList(s)) {return 1;}
331 else if (keywordsStop1.InList(s)) {return -1;}
332 return 0;
336 static int ParseMetapostWord(unsigned int pos, Accessor &styler, char *word)
338 int length=0;
339 char ch=styler.SafeGetCharAt(pos);
340 *word=0;
342 while(isMETAPOSTidentifier(ch) && isalpha(ch) && length<100){
343 word[length]=ch;
344 length++;
345 ch=styler.SafeGetCharAt(pos+length);
347 word[length]=0;
348 return length;
351 static void FoldMetapostDoc(unsigned int startPos, int length, int, WordList *keywordlists[], Accessor &styler)
353 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
354 unsigned int endPos = startPos+length;
355 int visibleChars=0;
356 int lineCurrent=styler.GetLine(startPos);
357 int levelPrev=styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
358 int levelCurrent=levelPrev;
359 char chNext=styler[startPos];
361 char buffer[100]="";
363 for (unsigned int i=startPos; i < endPos; i++) {
364 char ch=chNext;
365 chNext=styler.SafeGetCharAt(i+1);
366 char chPrev=styler.SafeGetCharAt(i-1);
367 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
369 if(i==0 || chPrev == '\r' || chPrev=='\n'|| chPrev==' '|| chPrev=='(' || chPrev=='$')
371 ParseMetapostWord(i, styler, buffer);
372 levelCurrent += classifyFoldPointMetapost(buffer,keywordlists);
375 if (atEOL) {
376 int lev = levelPrev;
377 if (visibleChars == 0 && foldCompact)
378 lev |= SC_FOLDLEVELWHITEFLAG;
379 if ((levelCurrent > levelPrev) && (visibleChars > 0))
380 lev |= SC_FOLDLEVELHEADERFLAG;
381 if (lev != styler.LevelAt(lineCurrent)) {
382 styler.SetLevel(lineCurrent, lev);
384 lineCurrent++;
385 levelPrev = levelCurrent;
386 visibleChars = 0;
389 if (!isspacechar(ch))
390 visibleChars++;
392 // Fill in the real level of the next line, keeping the current flags as they will be filled in later
393 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
394 styler.SetLevel(lineCurrent, levelPrev | flagsNext);
399 LexerModule lmMETAPOST(SCLEX_METAPOST, ColouriseMETAPOSTDoc, "metapost", FoldMetapostDoc, metapostWordListDesc);