1 // Scintilla source code edit control
2 // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
4 This is the Lexer for Gui4Cli, included in SciLexer.dll
5 - by d. Keletsekis, 2/10/2003
7 To add to SciLexer.dll:
8 1. Add the values below to INCLUDE\Scintilla.iface
9 2. Run the scripts/HFacer.py script
10 3. Run the scripts/LexGen.py script
13 val SCE_GC_COMMENTLINE=1
14 val SCE_GC_COMMENTBLOCK=2
17 val SCE_GC_ATTRIBUTE=5
32 #include "Scintilla.h"
36 #include "LexAccessor.h"
38 #include "StyleContext.h"
39 #include "CharacterSet.h"
40 #include "LexerModule.h"
43 using namespace Scintilla
;
46 #define debug Platform::DebugPrintf
48 static inline bool IsAWordChar(const int ch
) {
49 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_' || ch
=='\\');
52 inline bool isGCOperator(int ch
)
55 // '.' left out as it is used to make up numbers
56 if (ch
== '*' || ch
== '/' || ch
== '-' || ch
== '+' ||
57 ch
== '(' || ch
== ')' || ch
== '=' || ch
== '%' ||
58 ch
== '[' || ch
== ']' || ch
== '<' || ch
== '>' ||
59 ch
== ',' || ch
== ';' || ch
== ':')
64 #define isSpace(x) ((x)==' ' || (x)=='\t')
65 #define isNL(x) ((x)=='\n' || (x)=='\r')
66 #define isSpaceOrNL(x) (isSpace(x) || isNL(x))
68 #define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024)
70 static void colorFirstWord(WordList
*keywordlists
[], Accessor
&styler
,
71 StyleContext
*sc
, char *buff
, int length
, int)
74 while (sc
->More() && isSpaceOrNL(sc
->ch
))
77 styler
.ColourTo(sc
->currentPos
- 1, sc
->state
);
79 if (!IsAWordChar(sc
->ch
)) // comment, marker, etc..
82 while (sc
->More() && !isSpaceOrNL(sc
->ch
) && (c
< length
-1) && !isGCOperator(sc
->ch
))
83 { buff
[c
] = static_cast<char>(sc
->ch
);
88 while (*p
) // capitalize..
89 { if (islower(*p
)) *p
= static_cast<char>(toupper(*p
));
93 WordList
&kGlobal
= *keywordlists
[0]; // keyword lists set by the user
94 WordList
&kEvent
= *keywordlists
[1];
95 WordList
&kAttribute
= *keywordlists
[2];
96 WordList
&kControl
= *keywordlists
[3];
97 WordList
&kCommand
= *keywordlists
[4];
100 // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
101 // debug ("line = %d, level = %d", line, level);
103 if (kGlobal
.InList(buff
)) state
= SCE_GC_GLOBAL
;
104 else if (kAttribute
.InList(buff
)) state
= SCE_GC_ATTRIBUTE
;
105 else if (kControl
.InList(buff
)) state
= SCE_GC_CONTROL
;
106 else if (kCommand
.InList(buff
)) state
= SCE_GC_COMMAND
;
107 else if (kEvent
.InList(buff
)) state
= SCE_GC_EVENT
;
110 { sc
->ChangeState(state
);
111 styler
.ColourTo(sc
->currentPos
- 1, sc
->state
);
112 sc
->ChangeState(SCE_GC_DEFAULT
);
115 { sc
->ChangeState(SCE_GC_DEFAULT
);
116 styler
.ColourTo(sc
->currentPos
- 1, sc
->state
);
120 // Main colorizing function called by Scintilla
122 ColouriseGui4CliDoc(unsigned int startPos
, int length
, int initStyle
,
123 WordList
*keywordlists
[], Accessor
&styler
)
125 styler
.StartAt(startPos
);
127 int quotestart
= 0, oldstate
, currentline
= styler
.GetLine(startPos
);
128 styler
.StartSegment(startPos
);
130 char buff
[BUFFSIZE
+1]; // buffer for command name
132 StyleContext
sc(startPos
, length
, initStyle
, styler
);
133 buff
[0] = '\0'; // cbuff = 0;
135 if (sc
.state
!= SCE_GC_COMMENTBLOCK
) // colorize 1st word..
136 colorFirstWord(keywordlists
, styler
, &sc
, buff
, BUFFSIZE
, currentline
);
144 if (sc
.state
== SCE_GC_COMMENTBLOCK
|| sc
.state
== SCE_GC_STRING
)
146 if (sc
.chNext
== '/') // line comment
147 { sc
.SetState (SCE_GC_COMMENTLINE
);
149 styler
.ColourTo(sc
.currentPos
, sc
.state
);
151 else if (sc
.chNext
== '*') // block comment
152 { sc
.SetState(SCE_GC_COMMENTBLOCK
);
154 styler
.ColourTo(sc
.currentPos
, sc
.state
);
157 styler
.ColourTo(sc
.currentPos
, sc
.state
);
160 case '*': // end of comment block, or operator..
161 if (sc
.state
== SCE_GC_STRING
)
163 if (sc
.state
== SCE_GC_COMMENTBLOCK
&& sc
.chNext
== '/')
165 styler
.ColourTo(sc
.currentPos
, sc
.state
);
166 sc
.ChangeState (SCE_GC_DEFAULT
);
169 styler
.ColourTo(sc
.currentPos
, sc
.state
);
172 case '\'': case '\"': // strings..
173 if (sc
.state
== SCE_GC_COMMENTBLOCK
|| sc
.state
== SCE_GC_COMMENTLINE
)
175 if (sc
.state
== SCE_GC_STRING
)
176 { if (sc
.ch
== quotestart
) // match same quote char..
177 { styler
.ColourTo(sc
.currentPos
, sc
.state
);
178 sc
.ChangeState(SCE_GC_DEFAULT
);
182 { styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
183 sc
.ChangeState(SCE_GC_STRING
);
188 case ';': // end of commandline character
189 if (sc
.state
!= SCE_GC_COMMENTBLOCK
&& sc
.state
!= SCE_GC_COMMENTLINE
&&
190 sc
.state
!= SCE_GC_STRING
)
192 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
193 styler
.ColourTo(sc
.currentPos
, SCE_GC_OPERATOR
);
194 sc
.ChangeState(SCE_GC_DEFAULT
);
196 colorFirstWord(keywordlists
, styler
, &sc
, buff
, BUFFSIZE
, currentline
);
197 noforward
= 1; // don't move forward - already positioned at next char..
201 case '+': case '-': case '=': case '!': // operators..
202 case '<': case '>': case '&': case '|': case '$':
203 if (sc
.state
!= SCE_GC_COMMENTBLOCK
&& sc
.state
!= SCE_GC_COMMENTLINE
&&
204 sc
.state
!= SCE_GC_STRING
)
206 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
207 styler
.ColourTo(sc
.currentPos
, SCE_GC_OPERATOR
);
208 sc
.ChangeState(SCE_GC_DEFAULT
);
212 case '\\': // escape - same as operator, but also mark in strings..
213 if (sc
.state
!= SCE_GC_COMMENTBLOCK
&& sc
.state
!= SCE_GC_COMMENTLINE
)
216 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
217 sc
.Forward(); // mark also the next char..
218 styler
.ColourTo(sc
.currentPos
, SCE_GC_OPERATOR
);
219 sc
.ChangeState(oldstate
);
223 case '\n': case '\r':
225 if (sc
.state
== SCE_GC_COMMENTLINE
)
226 { styler
.ColourTo(sc
.currentPos
, sc
.state
);
227 sc
.ChangeState (SCE_GC_DEFAULT
);
229 else if (sc
.state
!= SCE_GC_COMMENTBLOCK
)
230 { colorFirstWord(keywordlists
, styler
, &sc
, buff
, BUFFSIZE
, currentline
);
231 noforward
= 1; // don't move forward - already positioned at next char..
235 // case ' ': case '\t':
239 if (!noforward
) sc
.Forward();
245 // Main folding function called by Scintilla - (based on props (.ini) files function)
246 static void FoldGui4Cli(unsigned int startPos
, int length
, int,
247 WordList
*[], Accessor
&styler
)
249 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
251 unsigned int endPos
= startPos
+ length
;
252 int visibleChars
= 0;
253 int lineCurrent
= styler
.GetLine(startPos
);
255 char chNext
= styler
[startPos
];
256 int styleNext
= styler
.StyleAt(startPos
);
257 bool headerPoint
= false;
259 for (unsigned int i
= startPos
; i
< endPos
; i
++)
262 chNext
= styler
[i
+1];
264 int style
= styleNext
;
265 styleNext
= styler
.StyleAt(i
+ 1);
266 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
268 if (style
== SCE_GC_EVENT
|| style
== SCE_GC_GLOBAL
)
269 { headerPoint
= true; // fold at events and globals
273 { int lev
= SC_FOLDLEVELBASE
+1;
276 lev
= SC_FOLDLEVELBASE
;
278 if (visibleChars
== 0 && foldCompact
)
279 lev
|= SC_FOLDLEVELWHITEFLAG
;
282 lev
|= SC_FOLDLEVELHEADERFLAG
;
284 if (lev
!= styler
.LevelAt(lineCurrent
)) // set level, if not already correct
285 { styler
.SetLevel(lineCurrent
, lev
);
288 lineCurrent
++; // re-initialize our flags
293 if (!(isspacechar(ch
))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK)))
297 int lev
= headerPoint
? SC_FOLDLEVELBASE
: SC_FOLDLEVELBASE
+1;
298 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
299 styler
.SetLevel(lineCurrent
, lev
| flagsNext
);
302 // I have no idea what these are for.. probably accessible by some message.
303 static const char * const gui4cliWordListDesc
[] = {
304 "Globals", "Events", "Attributes", "Control", "Commands",
308 // Declare language & pass our function pointers to Scintilla
309 LexerModule
lmGui4Cli(SCLEX_GUI4CLI
, ColouriseGui4CliDoc
, "gui4cli", FoldGui4Cli
, gui4cliWordListDesc
);