1 // Scintilla source code edit control
2 /** @file LexScriptol.cxx
14 #include "Scintilla.h"
18 #include "LexAccessor.h"
20 #include "StyleContext.h"
21 #include "CharacterSet.h"
22 #include "LexerModule.h"
25 using namespace Scintilla
;
28 static void ClassifyWordSol(unsigned int start
, unsigned int end
, WordList
&keywords
, Accessor
&styler
, char *prevWord
)
31 bool wordIsNumber
= isdigit(styler
[start
]) != 0;
32 for (unsigned int i
= 0; i
< end
- start
+ 1 && i
< 30; i
++)
34 s
[i
] = styler
[start
+ i
];
37 char chAttr
= SCE_SCRIPTOL_IDENTIFIER
;
38 if (0 == strcmp(prevWord
, "class")) chAttr
= SCE_SCRIPTOL_CLASSNAME
;
39 else if (wordIsNumber
) chAttr
= SCE_SCRIPTOL_NUMBER
;
40 else if (keywords
.InList(s
)) chAttr
= SCE_SCRIPTOL_KEYWORD
;
41 else for (unsigned int i
= 0; i
< end
- start
+ 1; i
++) // test dotted idents
43 if (styler
[start
+ i
] == '.')
45 styler
.ColourTo(start
+ i
- 1, chAttr
);
46 styler
.ColourTo(start
+ i
, SCE_SCRIPTOL_OPERATOR
);
49 styler
.ColourTo(end
, chAttr
);
53 static bool IsSolComment(Accessor
&styler
, int pos
, int len
)
58 if(c
== '`') return true;
64 if(c
== '/') return true;
65 if(c
== '*') return true;
72 static bool IsSolStringStart(char ch
)
74 if (ch
== '\'' || ch
== '"') return true;
78 static bool IsSolWordStart(char ch
)
80 return (iswordchar(ch
) && !IsSolStringStart(ch
));
84 static int GetSolStringState(Accessor
&styler
, int i
, int *nextIndex
)
86 char ch
= styler
.SafeGetCharAt(i
);
87 char chNext
= styler
.SafeGetCharAt(i
+ 1);
89 if (ch
!= '\"' && ch
!= '\'')
92 return SCE_SCRIPTOL_DEFAULT
;
94 // ch is either single or double quotes in string
95 // code below seem non-sense but is here for future extensions
96 if (ch
== chNext
&& ch
== styler
.SafeGetCharAt(i
+ 2))
99 if(ch
== '\"') return SCE_SCRIPTOL_TRIPLE
;
100 if(ch
== '\'') return SCE_SCRIPTOL_TRIPLE
;
101 return SCE_SCRIPTOL_STRING
;
106 if (ch
== '"') return SCE_SCRIPTOL_STRING
;
107 else return SCE_SCRIPTOL_STRING
;
112 static void ColouriseSolDoc(unsigned int startPos
, int length
, int initStyle
,
113 WordList
*keywordlists
[], Accessor
&styler
)
116 int lengthDoc
= startPos
+ length
;
117 char stringType
= '\"';
121 int lineCurrent
= styler
.GetLine(startPos
);
124 startPos
= styler
.LineStart(lineCurrent
-1);
125 if (startPos
== 0) initStyle
= SCE_SCRIPTOL_DEFAULT
;
126 else initStyle
= styler
.StyleAt(startPos
-1);
130 styler
.StartAt(startPos
, 127);
132 WordList
&keywords
= *keywordlists
[0];
134 int whingeLevel
= styler
.GetPropertyInt("tab.timmy.whinge.level");
137 if (length
== 0) return;
139 int state
= initStyle
& 31;
144 char chNext
= styler
[startPos
];
145 styler
.StartSegment(startPos
);
146 bool atStartLine
= true;
148 for (int i
= startPos
; i
< lengthDoc
; i
++)
153 char chBad
= static_cast<char>(64);
154 char chGood
= static_cast<char>(0);
155 char chFlags
= chGood
;
157 if (whingeLevel
== 1)
159 chFlags
= (spaceFlags
& wsInconsistent
) ? chBad
: chGood
;
161 else if (whingeLevel
== 2)
163 chFlags
= (spaceFlags
& wsSpaceTab
) ? chBad
: chGood
;
165 else if (whingeLevel
== 3)
167 chFlags
= (spaceFlags
& wsSpace
) ? chBad
: chGood
;
169 else if (whingeLevel
== 4)
171 chFlags
= (spaceFlags
& wsTab
) ? chBad
: chGood
;
173 styler
.SetFlags(chFlags
, static_cast<char>(state
));
178 chNext
= styler
.SafeGetCharAt(i
+ 1);
180 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n') || (i
== lengthDoc
))
182 if ((state
== SCE_SCRIPTOL_DEFAULT
) ||
183 (state
== SCE_SCRIPTOL_TRIPLE
) ||
184 (state
== SCE_SCRIPTOL_COMMENTBLOCK
))
186 styler
.ColourTo(i
, state
);
191 if (styler
.IsLeadByte(ch
))
193 chNext
= styler
.SafeGetCharAt(i
+ 2);
200 if (state
== SCE_SCRIPTOL_STRINGEOL
)
202 if (ch
!= '\r' && ch
!= '\n')
204 styler
.ColourTo(i
- 1, state
);
205 state
= SCE_SCRIPTOL_DEFAULT
;
209 if (state
== SCE_SCRIPTOL_DEFAULT
)
211 if (IsSolWordStart(ch
))
213 styler
.ColourTo(i
- 1, state
);
214 state
= SCE_SCRIPTOL_KEYWORD
;
218 styler
.ColourTo(i
- 1, state
);
219 state
= SCE_SCRIPTOL_COMMENTLINE
;
223 styler
.ColourTo(i
- 1, state
);
224 if(chNext
== '/') state
= SCE_SCRIPTOL_CSTYLE
;
225 if(chNext
== '*') state
= SCE_SCRIPTOL_COMMENTBLOCK
;
228 else if (IsSolStringStart(ch
))
230 styler
.ColourTo(i
- 1, state
);
231 state
= GetSolStringState(styler
, i
, &nextIndex
);
232 if(state
== SCE_SCRIPTOL_STRING
)
236 if (nextIndex
!= i
+ 1)
241 chNext
= styler
.SafeGetCharAt(i
+ 1);
244 else if (isoperator(ch
))
246 styler
.ColourTo(i
- 1, state
);
247 styler
.ColourTo(i
, SCE_SCRIPTOL_OPERATOR
);
250 else if (state
== SCE_SCRIPTOL_KEYWORD
)
254 ClassifyWordSol(styler
.GetStartSegment(), i
- 1, keywords
, styler
, prevWord
);
255 state
= SCE_SCRIPTOL_DEFAULT
;
258 state
= chNext
== '`' ? SCE_SCRIPTOL_PERSISTENT
: SCE_SCRIPTOL_COMMENTLINE
;
260 else if (IsSolStringStart(ch
))
262 styler
.ColourTo(i
- 1, state
);
263 state
= GetSolStringState(styler
, i
, &nextIndex
);
264 if (nextIndex
!= i
+ 1)
269 chNext
= styler
.SafeGetCharAt(i
+ 1);
272 else if (isoperator(ch
))
274 styler
.ColourTo(i
, SCE_SCRIPTOL_OPERATOR
);
280 if (state
== SCE_SCRIPTOL_COMMENTLINE
||
281 state
== SCE_SCRIPTOL_PERSISTENT
||
282 state
== SCE_SCRIPTOL_CSTYLE
)
284 if (ch
== '\r' || ch
== '\n')
286 styler
.ColourTo(i
- 1, state
);
287 state
= SCE_SCRIPTOL_DEFAULT
;
290 else if(state
== SCE_SCRIPTOL_COMMENTBLOCK
)
292 if(chPrev
== '*' && ch
== '/')
294 styler
.ColourTo(i
, state
);
295 state
= SCE_SCRIPTOL_DEFAULT
;
298 else if ((state
== SCE_SCRIPTOL_STRING
) ||
299 (state
== SCE_SCRIPTOL_CHARACTER
))
301 if ((ch
== '\r' || ch
== '\n') && (chPrev
!= '\\'))
303 styler
.ColourTo(i
- 1, state
);
304 state
= SCE_SCRIPTOL_STRINGEOL
;
308 if (chNext
== '\"' || chNext
== '\'' || chNext
== '\\')
312 chNext
= styler
.SafeGetCharAt(i
+ 1);
315 else if ((ch
== '\"') || (ch
== '\''))
317 // must match the entered quote type
320 styler
.ColourTo(i
, state
);
321 state
= SCE_SCRIPTOL_DEFAULT
;
325 else if (state
== SCE_SCRIPTOL_TRIPLE
)
327 if ((ch
== '\'' && chPrev
== '\'' && chPrev2
== '\'') ||
328 (ch
== '\"' && chPrev
== '\"' && chPrev2
== '\"'))
330 styler
.ColourTo(i
, state
);
331 state
= SCE_SCRIPTOL_DEFAULT
;
339 if (state
== SCE_SCRIPTOL_KEYWORD
)
341 ClassifyWordSol(styler
.GetStartSegment(),
342 lengthDoc
-1, keywords
, styler
, prevWord
);
346 styler
.ColourTo(lengthDoc
-1, state
);
350 static void FoldSolDoc(unsigned int startPos
, int length
, int initStyle
,
351 WordList
*[], Accessor
&styler
)
353 int lengthDoc
= startPos
+ length
;
355 int lineCurrent
= styler
.GetLine(startPos
);
361 startPos
= styler
.LineStart(lineCurrent
);
363 initStyle
= SCE_SCRIPTOL_DEFAULT
;
365 initStyle
= styler
.StyleAt(startPos
-1);
368 int state
= initStyle
& 31;
370 int indentCurrent
= styler
.IndentAmount(lineCurrent
, &spaceFlags
, IsSolComment
);
371 if (state
== SCE_SCRIPTOL_TRIPLE
)
372 indentCurrent
|= SC_FOLDLEVELWHITEFLAG
;
373 char chNext
= styler
[startPos
];
374 for (int i
= startPos
; i
< lengthDoc
; i
++)
377 chNext
= styler
.SafeGetCharAt(i
+ 1);
378 int style
= styler
.StyleAt(i
) & 31;
380 if ((ch
== '\r' && chNext
!= '\n') || (ch
== '\n') || (i
== lengthDoc
))
382 int lev
= indentCurrent
;
383 int indentNext
= styler
.IndentAmount(lineCurrent
+ 1, &spaceFlags
, IsSolComment
);
384 if (style
== SCE_SCRIPTOL_TRIPLE
)
385 indentNext
|= SC_FOLDLEVELWHITEFLAG
;
386 if (!(indentCurrent
& SC_FOLDLEVELWHITEFLAG
))
388 // Only non whitespace lines can be headers
389 if ((indentCurrent
& SC_FOLDLEVELNUMBERMASK
) < (indentNext
& SC_FOLDLEVELNUMBERMASK
))
391 lev
|= SC_FOLDLEVELHEADERFLAG
;
393 else if (indentNext
& SC_FOLDLEVELWHITEFLAG
)
395 // Line after is blank so check the next - maybe should continue further?
397 int indentNext2
= styler
.IndentAmount(lineCurrent
+ 2, &spaceFlags2
, IsSolComment
);
398 if ((indentCurrent
& SC_FOLDLEVELNUMBERMASK
) < (indentNext2
& SC_FOLDLEVELNUMBERMASK
))
400 lev
|= SC_FOLDLEVELHEADERFLAG
;
404 indentCurrent
= indentNext
;
405 styler
.SetLevel(lineCurrent
, lev
);
411 LexerModule
lmScriptol(SCLEX_SCRIPTOL
, ColouriseSolDoc
, "scriptol", FoldSolDoc
);