]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexMetapost.cxx
6afc9d8265848a9d45ab096ff53cb4c230654f52
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).
26 #include "Scintilla.h"
28 #include "StyleContext.h"
31 using namespace Scintilla
;
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
46 // style.metapost.0=fore:#7F7F00
48 // style.metapost.1=fore:#007F7F
50 // style.metapost.2=fore:#880000
52 // style.metapost.3=fore:#7F7F00
54 // style.metapost.4=fore:#008800
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
) {
64 (styler
[i
] == '\n') || ((styler
[i
] == '\r') && (styler
.SafeGetCharAt(i
+ 1) != '\n')) ;
67 static inline bool isMETAPOSTcomment(int ch
) {
72 static inline bool isMETAPOSTone(int ch
) {
74 (ch
== '[') || (ch
== ']') || (ch
== '(') || (ch
== ')') ||
75 (ch
== ':') || (ch
== '=') || (ch
== '<') || (ch
== '>') ||
76 (ch
== '{') || (ch
== '}') || (ch
== '\'') || (ch
== '\"') ;
79 static inline bool isMETAPOSTtwo(int ch
) {
81 (ch
== ';') || (ch
== '$') || (ch
== '@') || (ch
== '#');
84 static inline bool isMETAPOSTthree(int ch
) {
86 (ch
== '.') || (ch
== '-') || (ch
== '+') || (ch
== '/') ||
87 (ch
== '*') || (ch
== ',') || (ch
== '|') || (ch
== '`') ||
88 (ch
== '!') || (ch
== '?') || (ch
== '^') || (ch
== '&') ||
92 static inline bool isMETAPOSTidentifier(int ch
) {
94 ((ch
>= 'a') && (ch
<= 'z')) || ((ch
>= 'A') && (ch
<= 'Z')) ||
98 static inline bool isMETAPOSTnumber(int ch
) {
100 (ch
>= '0') && (ch
<= '9') ;
103 static inline bool isMETAPOSTstring(int ch
) {
108 static inline bool isMETAPOSTcolon(int ch
) {
113 static inline bool isMETAPOSTequal(int ch
) {
118 static int CheckMETAPOSTInterface(
119 unsigned int startPos
,
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")) {
136 } else if (strstr(lineBuffer
, "interface=metapost") || strstr(lineBuffer
, "interface=mp")) {
138 } else if (strstr(lineBuffer
, "interface=metafun")) {
140 } else if (styler
.SafeGetCharAt(1) == 'D' && strstr(lineBuffer
, "%D \\module")) {
141 // better would be to limit the search to just one line
144 return defaultInterface
;
150 return defaultInterface
;
153 static void ColouriseMETAPOSTDoc(
154 unsigned int startPos
,
157 WordList
*keywordlists
[],
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
) ;
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
197 sc
.SetState(SCE_METAPOST_TEXT
) ;
203 sc
.SetState(SCE_METAPOST_TEXT
) ;
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
) ;
214 } else if (sc
.atLineEnd
) {
215 sc
.SetState(SCE_METAPOST_TEXT
) ;
219 inString
= false ; // not correct but we want to stimulate one-lines
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
) ;
229 if (strcmp(key
,"etex") == 0) {
230 sc
.ChangeState(SCE_METAPOST_GROUP
) ;
233 sc
.ChangeState(SCE_METAPOST_TEXT
) ;
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
) ;
241 sc
.ChangeState(SCE_METAPOST_TEXT
) ;
246 if (isMETAPOSTcomment(sc
.ch
)) {
248 sc
.SetState(SCE_METAPOST_SYMBOL
) ;
249 sc
.ForwardSetState(SCE_METAPOST_DEFAULT
) ;
250 inComment
= ! processComment
;
252 sc
.SetState(SCE_METAPOST_TEXT
) ;
254 } else if (isMETAPOSTstring(sc
.ch
)) {
256 sc
.SetState(SCE_METAPOST_SPECIAL
) ;
257 if (! isMETAPOSTstring(sc
.chNext
)) {
258 sc
.ForwardSetState(SCE_METAPOST_TEXT
) ;
262 sc
.SetState(SCE_METAPOST_TEXT
) ;
264 } else if (isMETAPOSTcolon(sc
.ch
)) {
266 if (! isMETAPOSTequal(sc
.chNext
)) {
267 sc
.SetState(SCE_METAPOST_COMMAND
) ;
270 sc
.SetState(SCE_METAPOST_SPECIAL
) ;
273 sc
.SetState(SCE_METAPOST_TEXT
) ;
275 } else if (isMETAPOSTone(sc
.ch
)) {
277 sc
.SetState(SCE_METAPOST_SPECIAL
) ;
279 sc
.SetState(SCE_METAPOST_TEXT
) ;
281 } else if (isMETAPOSTtwo(sc
.ch
)) {
283 sc
.SetState(SCE_METAPOST_GROUP
) ;
285 sc
.SetState(SCE_METAPOST_TEXT
) ;
287 } else if (isMETAPOSTthree(sc
.ch
)) {
289 sc
.SetState(SCE_METAPOST_SYMBOL
) ;
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
) ;
308 sc
.SetState(SCE_METAPOST_TEXT
) ;
318 // Hooks info the system:
320 static const char * const metapostWordListDesc
[] = {
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;}
336 static int ParseMetapostWord(unsigned int pos
, Accessor
&styler
, char *word
)
339 char ch
=styler
.SafeGetCharAt(pos
);
342 while(isMETAPOSTidentifier(ch
) && isalpha(ch
) && length
<100){
345 ch
=styler
.SafeGetCharAt(pos
+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
;
356 int lineCurrent
=styler
.GetLine(startPos
);
357 int levelPrev
=styler
.LevelAt(lineCurrent
) & SC_FOLDLEVELNUMBERMASK
;
358 int levelCurrent
=levelPrev
;
359 char chNext
=styler
[startPos
];
363 for (unsigned int i
=startPos
; i
< endPos
; i
++) {
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
);
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
);
385 levelPrev
= levelCurrent
;
389 if (!isspacechar(ch
))
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
);