]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexGui4Cli.cxx
WinCE doesn't have GetThreadLocale
[wxWidgets.git] / src / stc / scintilla / src / LexGui4Cli.cxx
1 // Scintilla source code edit control
2 // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
3 /*
4 This is the Lexer for Gui4Cli, included in SciLexer.dll
5 - by d. Keletsekis, 2/10/2003
6
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
11
12 val SCE_GC_DEFAULT=0
13 val SCE_GC_COMMENTLINE=1
14 val SCE_GC_COMMENTBLOCK=2
15 val SCE_GC_GLOBAL=3
16 val SCE_GC_EVENT=4
17 val SCE_GC_ATTRIBUTE=5
18 val SCE_GC_CONTROL=6
19 val SCE_GC_COMMAND=7
20 val SCE_GC_STRING=8
21 val SCE_GC_OPERATOR=9
22 */
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <stdio.h>
28 #include <stdarg.h>
29
30 #include "Platform.h"
31
32 #include "PropSet.h"
33 #include "Accessor.h"
34 #include "StyleContext.h"
35 #include "KeyWords.h"
36 #include "Scintilla.h"
37 #include "SciLexer.h"
38
39 #define debug Platform::DebugPrintf
40
41 static inline bool IsAWordChar(const int ch) {
42 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch =='\\');
43 }
44
45 static inline bool IsAWordStart(const int ch) {
46 return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
47 }
48
49 inline bool isGCOperator(int ch)
50 { if (isalnum(ch))
51 return false;
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 == ':')
57 return true;
58 return false;
59 }
60
61 #define isSpace(x) ((x)==' ' || (x)=='\t')
62 #define isNL(x) ((x)=='\n' || (x)=='\r')
63 #define isSpaceOrNL(x) (isSpace(x) || isNL(x))
64 #define BUFFSIZE 500
65 #define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024)
66
67 static void colorFirstWord(WordList *keywordlists[], Accessor &styler,
68 StyleContext *sc, char *buff, int length, int)
69 {
70 int c = 0;
71 while (sc->More() && isSpaceOrNL(sc->ch))
72 { sc->Forward();
73 }
74 styler.ColourTo(sc->currentPos - 1, sc->state);
75
76 if (!IsAWordChar(sc->ch)) // comment, marker, etc..
77 return;
78
79 while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch))
80 { buff[c] = static_cast<char>(sc->ch);
81 ++c; sc->Forward();
82 }
83 buff[c] = '\0';
84 char *p = buff;
85 while (*p) // capitalize..
86 { if (islower(*p)) *p = static_cast<char>(toupper(*p));
87 ++p;
88 }
89
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];
95
96 int state = 0;
97 // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
98 // debug ("line = %d, level = %d", line, level);
99
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;
105
106 if (state)
107 { sc->ChangeState(state);
108 styler.ColourTo(sc->currentPos - 1, sc->state);
109 sc->ChangeState(SCE_GC_DEFAULT);
110 }
111 else
112 { sc->ChangeState(SCE_GC_DEFAULT);
113 styler.ColourTo(sc->currentPos - 1, sc->state);
114 }
115 }
116
117 // Main colorizing function called by Scintilla
118 static void
119 ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle,
120 WordList *keywordlists[], Accessor &styler)
121 {
122 styler.StartAt(startPos);
123
124 int quotestart = 0, oldstate, currentline = styler.GetLine(startPos);
125 styler.StartSegment(startPos);
126 bool noforward;
127 char buff[BUFFSIZE+1]; // buffer for command name
128
129 StyleContext sc(startPos, length, initStyle, styler);
130 buff[0] = '\0'; // cbuff = 0;
131
132 if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word..
133 colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
134
135 while (sc.More())
136 { noforward = 0;
137
138 switch (sc.ch)
139 {
140 case '/':
141 if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING)
142 break;
143 if (sc.chNext == '/') // line comment
144 { sc.SetState (SCE_GC_COMMENTLINE);
145 sc.Forward();
146 styler.ColourTo(sc.currentPos, sc.state);
147 }
148 else if (sc.chNext == '*') // block comment
149 { sc.SetState(SCE_GC_COMMENTBLOCK);
150 sc.Forward();
151 styler.ColourTo(sc.currentPos, sc.state);
152 }
153 else
154 styler.ColourTo(sc.currentPos, sc.state);
155 break;
156
157 case '*': // end of comment block, or operator..
158 if (sc.state == SCE_GC_STRING)
159 break;
160 if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/')
161 { sc.Forward();
162 styler.ColourTo(sc.currentPos, sc.state);
163 sc.ChangeState (SCE_GC_DEFAULT);
164 }
165 else
166 styler.ColourTo(sc.currentPos, sc.state);
167 break;
168
169 case '\'': case '\"': // strings..
170 if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE)
171 break;
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);
176 quotestart = 0;
177 } }
178 else
179 { styler.ColourTo(sc.currentPos - 1, sc.state);
180 sc.ChangeState(SCE_GC_STRING);
181 quotestart = sc.ch;
182 }
183 break;
184
185 case ';': // end of commandline character
186 if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
187 sc.state != SCE_GC_STRING)
188 {
189 styler.ColourTo(sc.currentPos - 1, sc.state);
190 styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
191 sc.ChangeState(SCE_GC_DEFAULT);
192 sc.Forward();
193 colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
194 noforward = 1; // don't move forward - already positioned at next char..
195 }
196 break;
197
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)
202 {
203 styler.ColourTo(sc.currentPos - 1, sc.state);
204 styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
205 sc.ChangeState(SCE_GC_DEFAULT);
206 }
207 break;
208
209 case '\\': // escape - same as operator, but also mark in strings..
210 if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE)
211 {
212 oldstate = sc.state;
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);
217 }
218 break;
219
220 case '\n': case '\r':
221 ++currentline;
222 if (sc.state == SCE_GC_COMMENTLINE)
223 { styler.ColourTo(sc.currentPos, sc.state);
224 sc.ChangeState (SCE_GC_DEFAULT);
225 }
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..
229 }
230 break;
231
232 // case ' ': case '\t':
233 // default :
234 }
235
236 if (!noforward) sc.Forward();
237
238 }
239 styler.ColourTo(sc.currentPos, sc.state);
240 }
241
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)
245 {
246 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
247
248 unsigned int endPos = startPos + length;
249 int visibleChars = 0;
250 int lineCurrent = styler.GetLine(startPos);
251
252 char chNext = styler[startPos];
253 int styleNext = styler.StyleAt(startPos);
254 bool headerPoint = false;
255
256 for (unsigned int i = startPos; i < endPos; i++)
257 {
258 char ch = chNext;
259 chNext = styler[i+1];
260
261 int style = styleNext;
262 styleNext = styler.StyleAt(i + 1);
263 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
264
265 if (style == SCE_GC_EVENT || style == SCE_GC_GLOBAL)
266 { headerPoint = true; // fold at events and globals
267 }
268
269 if (atEOL)
270 { int lev = SC_FOLDLEVELBASE+1;
271
272 if (headerPoint)
273 lev = SC_FOLDLEVELBASE;
274
275 if (visibleChars == 0 && foldCompact)
276 lev |= SC_FOLDLEVELWHITEFLAG;
277
278 if (headerPoint)
279 lev |= SC_FOLDLEVELHEADERFLAG;
280
281 if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct
282 { styler.SetLevel(lineCurrent, lev);
283 }
284
285 lineCurrent++; // re-initialize our flags
286 visibleChars = 0;
287 headerPoint = false;
288 }
289
290 if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK)))
291 visibleChars++;
292 }
293
294 int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1;
295 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
296 styler.SetLevel(lineCurrent, lev | flagsNext);
297 }
298
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",
302 0
303 };
304
305 // Declare language & pass our function pointers to Scintilla
306 LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc);
307
308 #undef debug
309