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 include/HFacer.py script
10 3. Run the src/lexGen.py script
13 val SCE_GC_COMMENTLINE=1
14 val SCE_GC_COMMENTBLOCK=2
17 val SCE_GC_ATTRIBUTE=5
34 #include "StyleContext.h"
36 #include "Scintilla.h"
39 #define debug Platform::DebugPrintf
41 static inline bool IsAWordChar(const int ch
) {
42 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_' || ch
=='\\');
45 static inline bool IsAWordStart(const int ch
) {
46 return (ch
< 0x80) && (isalnum(ch
) || ch
== '_' || ch
== '.');
49 inline bool isGCOperator(int ch
)
52 // '.' left out as it is used to make up numbers
53 if (ch
== '*' || ch
== '/' || ch
== '-' || ch
== '+' ||
54 ch
== '(' || ch
== ')' || ch
== '=' || ch
== '%' ||
55 ch
== '[' || ch
== ']' || ch
== '<' || ch
== '>' ||
56 ch
== ',' || ch
== ';' || ch
== ':')
61 #define isSpace(x) ((x)==' ' || (x)=='\t')
62 #define isNL(x) ((x)=='\n' || (x)=='\r')
63 #define isSpaceOrNL(x) (isSpace(x) || isNL(x))
65 #define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024)
67 static void colorFirstWord(WordList
*keywordlists
[], Accessor
&styler
,
68 StyleContext
*sc
, char *buff
, int length
, int)
71 while (sc
->More() && isSpaceOrNL(sc
->ch
))
74 styler
.ColourTo(sc
->currentPos
- 1, sc
->state
);
76 if (!IsAWordChar(sc
->ch
)) // comment, marker, etc..
79 while (sc
->More() && !isSpaceOrNL(sc
->ch
) && (c
< length
-1) && !isGCOperator(sc
->ch
))
80 { buff
[c
] = static_cast<char>(sc
->ch
);
85 while (*p
) // capitalize..
86 { if (islower(*p
)) *p
= static_cast<char>(toupper(*p
));
90 WordList
&kGlobal
= *keywordlists
[0]; // keyword lists set by the user
91 WordList
&kEvent
= *keywordlists
[1];
92 WordList
&kAttribute
= *keywordlists
[2];
93 WordList
&kControl
= *keywordlists
[3];
94 WordList
&kCommand
= *keywordlists
[4];
97 // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
98 // debug ("line = %d, level = %d", line, level);
100 if (kGlobal
.InList(buff
)) state
= SCE_GC_GLOBAL
;
101 else if (kAttribute
.InList(buff
)) state
= SCE_GC_ATTRIBUTE
;
102 else if (kControl
.InList(buff
)) state
= SCE_GC_CONTROL
;
103 else if (kCommand
.InList(buff
)) state
= SCE_GC_COMMAND
;
104 else if (kEvent
.InList(buff
)) state
= SCE_GC_EVENT
;
107 { sc
->ChangeState(state
);
108 styler
.ColourTo(sc
->currentPos
- 1, sc
->state
);
109 sc
->ChangeState(SCE_GC_DEFAULT
);
112 { sc
->ChangeState(SCE_GC_DEFAULT
);
113 styler
.ColourTo(sc
->currentPos
- 1, sc
->state
);
117 // Main colorizing function called by Scintilla
119 ColouriseGui4CliDoc(unsigned int startPos
, int length
, int initStyle
,
120 WordList
*keywordlists
[], Accessor
&styler
)
122 styler
.StartAt(startPos
);
124 int quotestart
= 0, oldstate
, currentline
= styler
.GetLine(startPos
);
125 styler
.StartSegment(startPos
);
127 char buff
[BUFFSIZE
+1]; // buffer for command name
129 StyleContext
sc(startPos
, length
, initStyle
, styler
);
130 buff
[0] = '\0'; // cbuff = 0;
132 if (sc
.state
!= SCE_GC_COMMENTBLOCK
) // colorize 1st word..
133 colorFirstWord(keywordlists
, styler
, &sc
, buff
, BUFFSIZE
, currentline
);
141 if (sc
.state
== SCE_GC_COMMENTBLOCK
|| sc
.state
== SCE_GC_STRING
)
143 if (sc
.chNext
== '/') // line comment
144 { sc
.SetState (SCE_GC_COMMENTLINE
);
146 styler
.ColourTo(sc
.currentPos
, sc
.state
);
148 else if (sc
.chNext
== '*') // block comment
149 { sc
.SetState(SCE_GC_COMMENTBLOCK
);
151 styler
.ColourTo(sc
.currentPos
, sc
.state
);
154 styler
.ColourTo(sc
.currentPos
, sc
.state
);
157 case '*': // end of comment block, or operator..
158 if (sc
.state
== SCE_GC_STRING
)
160 if (sc
.state
== SCE_GC_COMMENTBLOCK
&& sc
.chNext
== '/')
162 styler
.ColourTo(sc
.currentPos
, sc
.state
);
163 sc
.ChangeState (SCE_GC_DEFAULT
);
166 styler
.ColourTo(sc
.currentPos
, sc
.state
);
169 case '\'': case '\"': // strings..
170 if (sc
.state
== SCE_GC_COMMENTBLOCK
|| sc
.state
== SCE_GC_COMMENTLINE
)
172 if (sc
.state
== SCE_GC_STRING
)
173 { if (sc
.ch
== quotestart
) // match same quote char..
174 { styler
.ColourTo(sc
.currentPos
, sc
.state
);
175 sc
.ChangeState(SCE_GC_DEFAULT
);
179 { styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
180 sc
.ChangeState(SCE_GC_STRING
);
185 case ';': // end of commandline character
186 if (sc
.state
!= SCE_GC_COMMENTBLOCK
&& sc
.state
!= SCE_GC_COMMENTLINE
&&
187 sc
.state
!= SCE_GC_STRING
)
189 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
190 styler
.ColourTo(sc
.currentPos
, SCE_GC_OPERATOR
);
191 sc
.ChangeState(SCE_GC_DEFAULT
);
193 colorFirstWord(keywordlists
, styler
, &sc
, buff
, BUFFSIZE
, currentline
);
194 noforward
= 1; // don't move forward - already positioned at next char..
198 case '+': case '-': case '=': case '!': // operators..
199 case '<': case '>': case '&': case '|': case '$':
200 if (sc
.state
!= SCE_GC_COMMENTBLOCK
&& sc
.state
!= SCE_GC_COMMENTLINE
&&
201 sc
.state
!= SCE_GC_STRING
)
203 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
204 styler
.ColourTo(sc
.currentPos
, SCE_GC_OPERATOR
);
205 sc
.ChangeState(SCE_GC_DEFAULT
);
209 case '\\': // escape - same as operator, but also mark in strings..
210 if (sc
.state
!= SCE_GC_COMMENTBLOCK
&& sc
.state
!= SCE_GC_COMMENTLINE
)
213 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
214 sc
.Forward(); // mark also the next char..
215 styler
.ColourTo(sc
.currentPos
, SCE_GC_OPERATOR
);
216 sc
.ChangeState(oldstate
);
220 case '\n': case '\r':
222 if (sc
.state
== SCE_GC_COMMENTLINE
)
223 { styler
.ColourTo(sc
.currentPos
, sc
.state
);
224 sc
.ChangeState (SCE_GC_DEFAULT
);
226 else if (sc
.state
!= SCE_GC_COMMENTBLOCK
)
227 { colorFirstWord(keywordlists
, styler
, &sc
, buff
, BUFFSIZE
, currentline
);
228 noforward
= 1; // don't move forward - already positioned at next char..
232 // case ' ': case '\t':
236 if (!noforward
) sc
.Forward();
239 styler
.ColourTo(sc
.currentPos
, sc
.state
);
242 // Main folding function called by Scintilla - (based on props (.ini) files function)
243 static void FoldGui4Cli(unsigned int startPos
, int length
, int,
244 WordList
*[], Accessor
&styler
)
246 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
248 unsigned int endPos
= startPos
+ length
;
249 int visibleChars
= 0;
250 int lineCurrent
= styler
.GetLine(startPos
);
252 char chNext
= styler
[startPos
];
253 int styleNext
= styler
.StyleAt(startPos
);
254 bool headerPoint
= false;
256 for (unsigned int i
= startPos
; i
< endPos
; i
++)
259 chNext
= styler
[i
+1];
261 int style
= styleNext
;
262 styleNext
= styler
.StyleAt(i
+ 1);
263 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
265 if (style
== SCE_GC_EVENT
|| style
== SCE_GC_GLOBAL
)
266 { headerPoint
= true; // fold at events and globals
270 { int lev
= SC_FOLDLEVELBASE
+1;
273 lev
= SC_FOLDLEVELBASE
;
275 if (visibleChars
== 0 && foldCompact
)
276 lev
|= SC_FOLDLEVELWHITEFLAG
;
279 lev
|= SC_FOLDLEVELHEADERFLAG
;
281 if (lev
!= styler
.LevelAt(lineCurrent
)) // set level, if not already correct
282 { styler
.SetLevel(lineCurrent
, lev
);
285 lineCurrent
++; // re-initialize our flags
290 if (!(isspacechar(ch
))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK)))
294 int lev
= headerPoint
? SC_FOLDLEVELBASE
: SC_FOLDLEVELBASE
+1;
295 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
296 styler
.SetLevel(lineCurrent
, lev
| flagsNext
);
299 // I have no idea what these are for.. probably accessible by some message.
300 static const char * const gui4cliWordListDesc
[] = {
301 "Globals", "Events", "Attributes", "Control", "Commands",
305 // Declare language & pass our function pointers to Scintilla
306 LexerModule
lmGui4Cli(SCLEX_GUI4CLI
, ColouriseGui4CliDoc
, "gui4cli", FoldGui4Cli
, gui4cliWordListDesc
);