1 // Scintilla source code edit control
2 //Author: instanton (email: soft_share<at>126<dot>com)
3 // The License.txt file describes the conditions under which this software may be distributed.
12 #include "Scintilla.h"
16 #include "LexAccessor.h"
18 #include "StyleContext.h"
19 #include "CharacterSet.h"
20 #include "LexerModule.h"
23 using namespace Scintilla
;
26 static void ColouriseAsyDoc(unsigned int startPos
, int length
, int initStyle
,
27 WordList
*keywordlists
[], Accessor
&styler
) {
29 WordList
&keywords
= *keywordlists
[0];
30 WordList
&keywords2
= *keywordlists
[1];
32 CharacterSet
setWordStart(CharacterSet::setAlpha
, "_", 0x80, true);
33 CharacterSet
setWord(CharacterSet::setAlphaNum
, "._", 0x80, true);
37 StyleContext
sc(startPos
, length
, initStyle
, styler
);
39 for (; sc
.More(); sc
.Forward()) {
42 if (sc
.state
== SCE_ASY_STRING
) {
43 sc
.SetState(SCE_ASY_STRING
);
49 if (sc
.chNext
== '\n' || sc
.chNext
== '\r') {
51 if (sc
.ch
== '\r' && sc
.chNext
== '\n') {
54 // continuationLine = true;
59 // Determine if the current state should terminate.
61 case SCE_ASY_OPERATOR
:
62 sc
.SetState(SCE_ASY_DEFAULT
);
65 if (!setWord
.Contains(sc
.ch
)) {
66 sc
.SetState(SCE_ASY_DEFAULT
);
69 case SCE_ASY_IDENTIFIER
:
70 if (!setWord
.Contains(sc
.ch
) || (sc
.ch
== '.')) {
72 sc
.GetCurrentLowered(s
, sizeof(s
));
73 if (keywords
.InList(s
)) {
74 sc
.ChangeState(SCE_ASY_WORD
);
75 } else if (keywords2
.InList(s
)) {
76 sc
.ChangeState(SCE_ASY_WORD2
);
78 sc
.SetState(SCE_ASY_DEFAULT
);
82 if (sc
.Match('*', '/')) {
84 sc
.ForwardSetState(SCE_ASY_DEFAULT
);
87 case SCE_ASY_COMMENTLINE
:
89 sc
.SetState(SCE_ASY_DEFAULT
);
94 sc
.ChangeState(SCE_ASY_STRINGEOL
);
95 } else if (sc
.ch
== '\\') {
96 if (sc
.chNext
== '\"' || sc
.chNext
== '\'' || sc
.chNext
== '\\') {
99 } else if (sc
.ch
== '\"') {
100 sc
.ForwardSetState(SCE_ASY_DEFAULT
);
103 case SCE_ASY_CHARACTER
:
105 sc
.ChangeState(SCE_ASY_STRINGEOL
);
106 } else if (sc
.ch
== '\\') {
107 if (sc
.chNext
== '\"' || sc
.chNext
== '\'' || sc
.chNext
== '\\') {
110 } else if (sc
.ch
== '\'') {
111 sc
.ForwardSetState(SCE_ASY_DEFAULT
);
116 // Determine if a new state should be entered.
117 if (sc
.state
== SCE_ASY_DEFAULT
) {
118 if (setWordStart
.Contains(sc
.ch
) || (sc
.ch
== '@')) {
119 sc
.SetState(SCE_ASY_IDENTIFIER
);
120 } else if (sc
.Match('/', '*')) {
121 sc
.SetState(SCE_ASY_COMMENT
);
123 } else if (sc
.Match('/', '/')) {
124 sc
.SetState(SCE_ASY_COMMENTLINE
);
125 } else if (sc
.ch
== '\"') {
126 sc
.SetState(SCE_ASY_STRING
);
127 } else if (sc
.ch
== '\'') {
128 sc
.SetState(SCE_ASY_CHARACTER
);
129 } else if (sc
.ch
== '#' && visibleChars
== 0) {
132 } while ((sc
.ch
== ' ' || sc
.ch
== '\t') && sc
.More());
134 sc
.SetState(SCE_ASY_DEFAULT
);
136 } else if (isoperator(static_cast<char>(sc
.ch
))) {
137 sc
.SetState(SCE_ASY_OPERATOR
);
145 static bool IsAsyCommentStyle(int style
) {
146 return style
== SCE_ASY_COMMENT
;
150 static inline bool isASYidentifier(int ch
) {
152 ((ch
>= 'a') && (ch
<= 'z')) || ((ch
>= 'A') && (ch
<= 'Z')) ;
155 static int ParseASYWord(unsigned int pos
, Accessor
&styler
, char *word
)
158 char ch
=styler
.SafeGetCharAt(pos
);
161 while(isASYidentifier(ch
) && length
<100){
164 ch
=styler
.SafeGetCharAt(pos
+length
);
170 static bool IsASYDrawingLine(int line
, Accessor
&styler
) {
171 int pos
= styler
.LineStart(line
);
172 int eol_pos
= styler
.LineStart(line
+ 1) - 1;
177 while (startpos
<eol_pos
){
178 char ch
= styler
[startpos
];
179 ParseASYWord(startpos
,styler
,buffer
);
180 bool drawcommands
= strncmp(buffer
,"draw",4)==0||
181 strncmp(buffer
,"pair",4)==0||strncmp(buffer
,"label",5)==0;
182 if (!drawcommands
&& ch
!=' ') return false;
183 else if (drawcommands
) return true;
189 static void FoldAsyDoc(unsigned int startPos
, int length
, int initStyle
,
190 WordList
*[], Accessor
&styler
) {
191 bool foldComment
= styler
.GetPropertyInt("fold.comment") != 0;
192 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
193 bool foldAtElse
= styler
.GetPropertyInt("fold.at.else", 0) != 0;
194 unsigned int endPos
= startPos
+ length
;
195 int visibleChars
= 0;
196 int lineCurrent
= styler
.GetLine(startPos
);
197 int levelCurrent
= SC_FOLDLEVELBASE
;
199 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
200 int levelMinCurrent
= levelCurrent
;
201 int levelNext
= levelCurrent
;
202 char chNext
= styler
[startPos
];
203 int styleNext
= styler
.StyleAt(startPos
);
204 int style
= initStyle
;
205 for (unsigned int i
= startPos
; i
< endPos
; i
++) {
207 chNext
= styler
.SafeGetCharAt(i
+ 1);
208 int stylePrev
= style
;
210 styleNext
= styler
.StyleAt(i
+ 1);
211 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
212 if (foldComment
&& IsAsyCommentStyle(style
)) {
213 if (!IsAsyCommentStyle(stylePrev
) && (stylePrev
!= SCE_ASY_COMMENTLINEDOC
)) {
215 } else if (!IsAsyCommentStyle(styleNext
) && (styleNext
!= SCE_ASY_COMMENTLINEDOC
) && !atEOL
) {
219 if (style
== SCE_ASY_OPERATOR
) {
221 if (levelMinCurrent
> levelNext
) {
222 levelMinCurrent
= levelNext
;
225 } else if (ch
== '}') {
230 if (atEOL
&& IsASYDrawingLine(lineCurrent
, styler
)){
231 if (lineCurrent
==0 && IsASYDrawingLine(lineCurrent
+ 1, styler
))
233 else if (lineCurrent
!=0 && !IsASYDrawingLine(lineCurrent
- 1, styler
)
234 && IsASYDrawingLine(lineCurrent
+ 1, styler
)
237 else if (lineCurrent
!=0 && IsASYDrawingLine(lineCurrent
- 1, styler
) &&
238 !IsASYDrawingLine(lineCurrent
+1, styler
))
243 int levelUse
= levelCurrent
;
245 levelUse
= levelMinCurrent
;
247 int lev
= levelUse
| levelNext
<< 16;
248 if (visibleChars
== 0 && foldCompact
)
249 lev
|= SC_FOLDLEVELWHITEFLAG
;
250 if (levelUse
< levelNext
)
251 lev
|= SC_FOLDLEVELHEADERFLAG
;
252 if (lev
!= styler
.LevelAt(lineCurrent
)) {
253 styler
.SetLevel(lineCurrent
, lev
);
256 levelCurrent
= levelNext
;
257 levelMinCurrent
= levelCurrent
;
265 static const char * const asyWordLists
[] = {
266 "Primary keywords and identifiers",
267 "Secondary keywords and identifiers",
271 LexerModule
lmASY(SCLEX_ASYMPTOTE
, ColouriseAsyDoc
, "asy", FoldAsyDoc
, asyWordLists
);