]> git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/lexers/LexGui4Cli.cxx
wxRTC text box layout fixes
[wxWidgets.git] / src / stc / scintilla / lexers / 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 <stdio.h>
27 #include <stdarg.h>
28 #include <assert.h>
29 #include <ctype.h>
30
31 #include "ILexer.h"
32 #include "Scintilla.h"
33 #include "SciLexer.h"
34
35 #include "WordList.h"
36 #include "LexAccessor.h"
37 #include "Accessor.h"
38 #include "StyleContext.h"
39 #include "CharacterSet.h"
40 #include "LexerModule.h"
41
42 #ifdef SCI_NAMESPACE
43 using namespace Scintilla;
44 #endif
45
46 #define debug Platform::DebugPrintf
47
48 static inline bool IsAWordChar(const int ch) {
49 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch =='\\');
50 }
51
52 static inline bool IsAWordStart(const int ch) {
53 return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
54 }
55
56 inline bool isGCOperator(int ch)
57 { if (isalnum(ch))
58 return false;
59 // '.' left out as it is used to make up numbers
60 if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
61 ch == '(' || ch == ')' || ch == '=' || ch == '%' ||
62 ch == '[' || ch == ']' || ch == '<' || ch == '>' ||
63 ch == ',' || ch == ';' || ch == ':')
64 return true;
65 return false;
66 }
67
68 #define isSpace(x) ((x)==' ' || (x)=='\t')
69 #define isNL(x) ((x)=='\n' || (x)=='\r')
70 #define isSpaceOrNL(x) (isSpace(x) || isNL(x))
71 #define BUFFSIZE 500
72 #define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024)
73
74 static void colorFirstWord(WordList *keywordlists[], Accessor &styler,
75 StyleContext *sc, char *buff, int length, int)
76 {
77 int c = 0;
78 while (sc->More() && isSpaceOrNL(sc->ch))
79 { sc->Forward();
80 }
81 styler.ColourTo(sc->currentPos - 1, sc->state);
82
83 if (!IsAWordChar(sc->ch)) // comment, marker, etc..
84 return;
85
86 while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch))
87 { buff[c] = static_cast<char>(sc->ch);
88 ++c; sc->Forward();
89 }
90 buff[c] = '\0';
91 char *p = buff;
92 while (*p) // capitalize..
93 { if (islower(*p)) *p = static_cast<char>(toupper(*p));
94 ++p;
95 }
96
97 WordList &kGlobal = *keywordlists[0]; // keyword lists set by the user
98 WordList &kEvent = *keywordlists[1];
99 WordList &kAttribute = *keywordlists[2];
100 WordList &kControl = *keywordlists[3];
101 WordList &kCommand = *keywordlists[4];
102
103 int state = 0;
104 // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
105 // debug ("line = %d, level = %d", line, level);
106
107 if (kGlobal.InList(buff)) state = SCE_GC_GLOBAL;
108 else if (kAttribute.InList(buff)) state = SCE_GC_ATTRIBUTE;
109 else if (kControl.InList(buff)) state = SCE_GC_CONTROL;
110 else if (kCommand.InList(buff)) state = SCE_GC_COMMAND;
111 else if (kEvent.InList(buff)) state = SCE_GC_EVENT;
112
113 if (state)
114 { sc->ChangeState(state);
115 styler.ColourTo(sc->currentPos - 1, sc->state);
116 sc->ChangeState(SCE_GC_DEFAULT);
117 }
118 else
119 { sc->ChangeState(SCE_GC_DEFAULT);
120 styler.ColourTo(sc->currentPos - 1, sc->state);
121 }
122 }
123
124 // Main colorizing function called by Scintilla
125 static void
126 ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle,
127 WordList *keywordlists[], Accessor &styler)
128 {
129 styler.StartAt(startPos);
130
131 int quotestart = 0, oldstate, currentline = styler.GetLine(startPos);
132 styler.StartSegment(startPos);
133 bool noforward;
134 char buff[BUFFSIZE+1]; // buffer for command name
135
136 StyleContext sc(startPos, length, initStyle, styler);
137 buff[0] = '\0'; // cbuff = 0;
138
139 if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word..
140 colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
141
142 while (sc.More())
143 { noforward = 0;
144
145 switch (sc.ch)
146 {
147 case '/':
148 if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING)
149 break;
150 if (sc.chNext == '/') // line comment
151 { sc.SetState (SCE_GC_COMMENTLINE);
152 sc.Forward();
153 styler.ColourTo(sc.currentPos, sc.state);
154 }
155 else if (sc.chNext == '*') // block comment
156 { sc.SetState(SCE_GC_COMMENTBLOCK);
157 sc.Forward();
158 styler.ColourTo(sc.currentPos, sc.state);
159 }
160 else
161 styler.ColourTo(sc.currentPos, sc.state);
162 break;
163
164 case '*': // end of comment block, or operator..
165 if (sc.state == SCE_GC_STRING)
166 break;
167 if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/')
168 { sc.Forward();
169 styler.ColourTo(sc.currentPos, sc.state);
170 sc.ChangeState (SCE_GC_DEFAULT);
171 }
172 else
173 styler.ColourTo(sc.currentPos, sc.state);
174 break;
175
176 case '\'': case '\"': // strings..
177 if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE)
178 break;
179 if (sc.state == SCE_GC_STRING)
180 { if (sc.ch == quotestart) // match same quote char..
181 { styler.ColourTo(sc.currentPos, sc.state);
182 sc.ChangeState(SCE_GC_DEFAULT);
183 quotestart = 0;
184 } }
185 else
186 { styler.ColourTo(sc.currentPos - 1, sc.state);
187 sc.ChangeState(SCE_GC_STRING);
188 quotestart = sc.ch;
189 }
190 break;
191
192 case ';': // end of commandline character
193 if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
194 sc.state != SCE_GC_STRING)
195 {
196 styler.ColourTo(sc.currentPos - 1, sc.state);
197 styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
198 sc.ChangeState(SCE_GC_DEFAULT);
199 sc.Forward();
200 colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
201 noforward = 1; // don't move forward - already positioned at next char..
202 }
203 break;
204
205 case '+': case '-': case '=': case '!': // operators..
206 case '<': case '>': case '&': case '|': case '$':
207 if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
208 sc.state != SCE_GC_STRING)
209 {
210 styler.ColourTo(sc.currentPos - 1, sc.state);
211 styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
212 sc.ChangeState(SCE_GC_DEFAULT);
213 }
214 break;
215
216 case '\\': // escape - same as operator, but also mark in strings..
217 if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE)
218 {
219 oldstate = sc.state;
220 styler.ColourTo(sc.currentPos - 1, sc.state);
221 sc.Forward(); // mark also the next char..
222 styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
223 sc.ChangeState(oldstate);
224 }
225 break;
226
227 case '\n': case '\r':
228 ++currentline;
229 if (sc.state == SCE_GC_COMMENTLINE)
230 { styler.ColourTo(sc.currentPos, sc.state);
231 sc.ChangeState (SCE_GC_DEFAULT);
232 }
233 else if (sc.state != SCE_GC_COMMENTBLOCK)
234 { colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
235 noforward = 1; // don't move forward - already positioned at next char..
236 }
237 break;
238
239 // case ' ': case '\t':
240 // default :
241 }
242
243 if (!noforward) sc.Forward();
244
245 }
246 sc.Complete();
247 }
248
249 // Main folding function called by Scintilla - (based on props (.ini) files function)
250 static void FoldGui4Cli(unsigned int startPos, int length, int,
251 WordList *[], Accessor &styler)
252 {
253 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
254
255 unsigned int endPos = startPos + length;
256 int visibleChars = 0;
257 int lineCurrent = styler.GetLine(startPos);
258
259 char chNext = styler[startPos];
260 int styleNext = styler.StyleAt(startPos);
261 bool headerPoint = false;
262
263 for (unsigned int i = startPos; i < endPos; i++)
264 {
265 char ch = chNext;
266 chNext = styler[i+1];
267
268 int style = styleNext;
269 styleNext = styler.StyleAt(i + 1);
270 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
271
272 if (style == SCE_GC_EVENT || style == SCE_GC_GLOBAL)
273 { headerPoint = true; // fold at events and globals
274 }
275
276 if (atEOL)
277 { int lev = SC_FOLDLEVELBASE+1;
278
279 if (headerPoint)
280 lev = SC_FOLDLEVELBASE;
281
282 if (visibleChars == 0 && foldCompact)
283 lev |= SC_FOLDLEVELWHITEFLAG;
284
285 if (headerPoint)
286 lev |= SC_FOLDLEVELHEADERFLAG;
287
288 if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct
289 { styler.SetLevel(lineCurrent, lev);
290 }
291
292 lineCurrent++; // re-initialize our flags
293 visibleChars = 0;
294 headerPoint = false;
295 }
296
297 if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK)))
298 visibleChars++;
299 }
300
301 int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1;
302 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
303 styler.SetLevel(lineCurrent, lev | flagsNext);
304 }
305
306 // I have no idea what these are for.. probably accessible by some message.
307 static const char * const gui4cliWordListDesc[] = {
308 "Globals", "Events", "Attributes", "Control", "Commands",
309 0
310 };
311
312 // Declare language & pass our function pointers to Scintilla
313 LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc);
314
315 #undef debug
316