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"
42 using namespace Scintilla
;
44 #define debug Platform::DebugPrintf
46 static inline bool IsAWordChar(const int ch
) {
47 return (ch
< 0x80) && (isalnum(ch
) || ch
== '.' || ch
== '_' || ch
=='\\');
50 inline bool isGCOperator(int ch
)
53 // '.' left out as it is used to make up numbers
54 if (ch
== '*' || ch
== '/' || ch
== '-' || ch
== '+' ||
55 ch
== '(' || ch
== ')' || ch
== '=' || ch
== '%' ||
56 ch
== '[' || ch
== ']' || ch
== '<' || ch
== '>' ||
57 ch
== ',' || ch
== ';' || ch
== ':')
62 #define isSpace(x) ((x)==' ' || (x)=='\t')
63 #define isNL(x) ((x)=='\n' || (x)=='\r')
64 #define isSpaceOrNL(x) (isSpace(x) || isNL(x))
66 #define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024)
68 static void colorFirstWord(WordList
*keywordlists
[], Accessor
&styler
,
69 StyleContext
*sc
, char *buff
, Sci_Position length
, Sci_Position
)
72 while (sc
->More() && isSpaceOrNL(sc
->ch
))
75 styler
.ColourTo(sc
->currentPos
- 1, sc
->state
);
77 if (!IsAWordChar(sc
->ch
)) // comment, marker, etc..
80 while (sc
->More() && !isSpaceOrNL(sc
->ch
) && (c
< length
-1) && !isGCOperator(sc
->ch
))
81 { buff
[c
] = static_cast<char>(sc
->ch
);
86 while (*p
) // capitalize..
87 { if (islower(*p
)) *p
= static_cast<char>(toupper(*p
));
91 WordList
&kGlobal
= *keywordlists
[0]; // keyword lists set by the user
92 WordList
&kEvent
= *keywordlists
[1];
93 WordList
&kAttribute
= *keywordlists
[2];
94 WordList
&kControl
= *keywordlists
[3];
95 WordList
&kCommand
= *keywordlists
[4];
98 // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
99 // debug ("line = %d, level = %d", line, level);
101 if (kGlobal
.InList(buff
)) state
= SCE_GC_GLOBAL
;
102 else if (kAttribute
.InList(buff
)) state
= SCE_GC_ATTRIBUTE
;
103 else if (kControl
.InList(buff
)) state
= SCE_GC_CONTROL
;
104 else if (kCommand
.InList(buff
)) state
= SCE_GC_COMMAND
;
105 else if (kEvent
.InList(buff
)) state
= SCE_GC_EVENT
;
108 { sc
->ChangeState(state
);
109 styler
.ColourTo(sc
->currentPos
- 1, sc
->state
);
110 sc
->ChangeState(SCE_GC_DEFAULT
);
113 { sc
->ChangeState(SCE_GC_DEFAULT
);
114 styler
.ColourTo(sc
->currentPos
- 1, sc
->state
);
118 // Main colorizing function called by Scintilla
120 ColouriseGui4CliDoc(Sci_PositionU startPos
, Sci_Position length
, int initStyle
,
121 WordList
*keywordlists
[], Accessor
&styler
)
123 styler
.StartAt(startPos
);
125 Sci_Position currentline
= styler
.GetLine(startPos
);
126 int quotestart
= 0, oldstate
;
127 styler
.StartSegment(startPos
);
129 char buff
[BUFFSIZE
+1]; // buffer for command name
131 StyleContext
sc(startPos
, length
, initStyle
, styler
);
132 buff
[0] = '\0'; // cbuff = 0;
134 if (sc
.state
!= SCE_GC_COMMENTBLOCK
) // colorize 1st word..
135 colorFirstWord(keywordlists
, styler
, &sc
, buff
, BUFFSIZE
, currentline
);
143 if (sc
.state
== SCE_GC_COMMENTBLOCK
|| sc
.state
== SCE_GC_STRING
)
145 if (sc
.chNext
== '/') // line comment
146 { sc
.SetState (SCE_GC_COMMENTLINE
);
148 styler
.ColourTo(sc
.currentPos
, sc
.state
);
150 else if (sc
.chNext
== '*') // block comment
151 { sc
.SetState(SCE_GC_COMMENTBLOCK
);
153 styler
.ColourTo(sc
.currentPos
, sc
.state
);
156 styler
.ColourTo(sc
.currentPos
, sc
.state
);
159 case '*': // end of comment block, or operator..
160 if (sc
.state
== SCE_GC_STRING
)
162 if (sc
.state
== SCE_GC_COMMENTBLOCK
&& sc
.chNext
== '/')
164 styler
.ColourTo(sc
.currentPos
, sc
.state
);
165 sc
.ChangeState (SCE_GC_DEFAULT
);
168 styler
.ColourTo(sc
.currentPos
, sc
.state
);
171 case '\'': case '\"': // strings..
172 if (sc
.state
== SCE_GC_COMMENTBLOCK
|| sc
.state
== SCE_GC_COMMENTLINE
)
174 if (sc
.state
== SCE_GC_STRING
)
175 { if (sc
.ch
== quotestart
) // match same quote char..
176 { styler
.ColourTo(sc
.currentPos
, sc
.state
);
177 sc
.ChangeState(SCE_GC_DEFAULT
);
181 { styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
182 sc
.ChangeState(SCE_GC_STRING
);
187 case ';': // end of commandline character
188 if (sc
.state
!= SCE_GC_COMMENTBLOCK
&& sc
.state
!= SCE_GC_COMMENTLINE
&&
189 sc
.state
!= SCE_GC_STRING
)
191 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
192 styler
.ColourTo(sc
.currentPos
, SCE_GC_OPERATOR
);
193 sc
.ChangeState(SCE_GC_DEFAULT
);
195 colorFirstWord(keywordlists
, styler
, &sc
, buff
, BUFFSIZE
, currentline
);
196 noforward
= 1; // don't move forward - already positioned at next char..
200 case '+': case '-': case '=': case '!': // operators..
201 case '<': case '>': case '&': case '|': case '$':
202 if (sc
.state
!= SCE_GC_COMMENTBLOCK
&& sc
.state
!= SCE_GC_COMMENTLINE
&&
203 sc
.state
!= SCE_GC_STRING
)
205 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
206 styler
.ColourTo(sc
.currentPos
, SCE_GC_OPERATOR
);
207 sc
.ChangeState(SCE_GC_DEFAULT
);
211 case '\\': // escape - same as operator, but also mark in strings..
212 if (sc
.state
!= SCE_GC_COMMENTBLOCK
&& sc
.state
!= SCE_GC_COMMENTLINE
)
215 styler
.ColourTo(sc
.currentPos
- 1, sc
.state
);
216 sc
.Forward(); // mark also the next char..
217 styler
.ColourTo(sc
.currentPos
, SCE_GC_OPERATOR
);
218 sc
.ChangeState(oldstate
);
222 case '\n': case '\r':
224 if (sc
.state
== SCE_GC_COMMENTLINE
)
225 { styler
.ColourTo(sc
.currentPos
, sc
.state
);
226 sc
.ChangeState (SCE_GC_DEFAULT
);
228 else if (sc
.state
!= SCE_GC_COMMENTBLOCK
)
229 { colorFirstWord(keywordlists
, styler
, &sc
, buff
, BUFFSIZE
, currentline
);
230 noforward
= 1; // don't move forward - already positioned at next char..
234 // case ' ': case '\t':
238 if (!noforward
) sc
.Forward();
244 // Main folding function called by Scintilla - (based on props (.ini) files function)
245 static void FoldGui4Cli(Sci_PositionU startPos
, Sci_Position length
, int,
246 WordList
*[], Accessor
&styler
)
248 bool foldCompact
= styler
.GetPropertyInt("fold.compact", 1) != 0;
250 Sci_PositionU endPos
= startPos
+ length
;
251 int visibleChars
= 0;
252 Sci_Position lineCurrent
= styler
.GetLine(startPos
);
254 char chNext
= styler
[startPos
];
255 int styleNext
= styler
.StyleAt(startPos
);
256 bool headerPoint
= false;
258 for (Sci_PositionU i
= startPos
; i
< endPos
; i
++)
261 chNext
= styler
[i
+1];
263 int style
= styleNext
;
264 styleNext
= styler
.StyleAt(i
+ 1);
265 bool atEOL
= (ch
== '\r' && chNext
!= '\n') || (ch
== '\n');
267 if (style
== SCE_GC_EVENT
|| style
== SCE_GC_GLOBAL
)
268 { headerPoint
= true; // fold at events and globals
272 { int lev
= SC_FOLDLEVELBASE
+1;
275 lev
= SC_FOLDLEVELBASE
;
277 if (visibleChars
== 0 && foldCompact
)
278 lev
|= SC_FOLDLEVELWHITEFLAG
;
281 lev
|= SC_FOLDLEVELHEADERFLAG
;
283 if (lev
!= styler
.LevelAt(lineCurrent
)) // set level, if not already correct
284 { styler
.SetLevel(lineCurrent
, lev
);
287 lineCurrent
++; // re-initialize our flags
292 if (!(isspacechar(ch
))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK)))
296 int lev
= headerPoint
? SC_FOLDLEVELBASE
: SC_FOLDLEVELBASE
+1;
297 int flagsNext
= styler
.LevelAt(lineCurrent
) & ~SC_FOLDLEVELNUMBERMASK
;
298 styler
.SetLevel(lineCurrent
, lev
| flagsNext
);
301 // I have no idea what these are for.. probably accessible by some message.
302 static const char * const gui4cliWordListDesc
[] = {
303 "Globals", "Events", "Attributes", "Control", "Commands",
307 // Declare language & pass our function pointers to Scintilla
308 LexerModule
lmGui4Cli(SCLEX_GUI4CLI
, ColouriseGui4CliDoc
, "gui4cli", FoldGui4Cli
, gui4cliWordListDesc
);