1 // Scintilla source code edit control
\r
2 // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
\r
4 This is the Lexer for Gui4Cli, included in SciLexer.dll
\r
5 - by d. Keletsekis, 2/10/2003
\r
7 To add to SciLexer.dll:
\r
8 1. Add the values below to INCLUDE\Scintilla.iface
\r
9 2. Run the include/HFacer.py script
\r
10 3. Run the src/lexGen.py script
\r
12 val SCE_GC_DEFAULT=0
\r
13 val SCE_GC_COMMENTLINE=1
\r
14 val SCE_GC_COMMENTBLOCK=2
\r
17 val SCE_GC_ATTRIBUTE=5
\r
18 val SCE_GC_CONTROL=6
\r
19 val SCE_GC_COMMAND=7
\r
21 val SCE_GC_OPERATOR=9
\r
30 #include "Platform.h"
\r
32 #include "PropSet.h"
\r
33 #include "Accessor.h"
\r
34 #include "StyleContext.h"
\r
35 #include "KeyWords.h"
\r
36 #include "Scintilla.h"
\r
37 #include "SciLexer.h"
\r
39 #ifdef SCI_NAMESPACE
\r
40 using namespace Scintilla;
\r
43 #define debug Platform::DebugPrintf
\r
45 static inline bool IsAWordChar(const int ch) {
\r
46 return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch =='\\');
\r
49 static inline bool IsAWordStart(const int ch) {
\r
50 return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
\r
53 inline bool isGCOperator(int ch)
\r
56 // '.' left out as it is used to make up numbers
\r
57 if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
\r
58 ch == '(' || ch == ')' || ch == '=' || ch == '%' ||
\r
59 ch == '[' || ch == ']' || ch == '<' || ch == '>' ||
\r
60 ch == ',' || ch == ';' || ch == ':')
\r
65 #define isSpace(x) ((x)==' ' || (x)=='\t')
\r
66 #define isNL(x) ((x)=='\n' || (x)=='\r')
\r
67 #define isSpaceOrNL(x) (isSpace(x) || isNL(x))
\r
68 #define BUFFSIZE 500
\r
69 #define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024)
\r
71 static void colorFirstWord(WordList *keywordlists[], Accessor &styler,
\r
72 StyleContext *sc, char *buff, int length, int)
\r
75 while (sc->More() && isSpaceOrNL(sc->ch))
\r
78 styler.ColourTo(sc->currentPos - 1, sc->state);
\r
80 if (!IsAWordChar(sc->ch)) // comment, marker, etc..
\r
83 while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch))
\r
84 { buff[c] = static_cast<char>(sc->ch);
\r
89 while (*p) // capitalize..
\r
90 { if (islower(*p)) *p = static_cast<char>(toupper(*p));
\r
94 WordList &kGlobal = *keywordlists[0]; // keyword lists set by the user
\r
95 WordList &kEvent = *keywordlists[1];
\r
96 WordList &kAttribute = *keywordlists[2];
\r
97 WordList &kControl = *keywordlists[3];
\r
98 WordList &kCommand = *keywordlists[4];
\r
101 // int level = styler.LevelAt(line) & SC_FOLDLEVELNUMBERMASK;
\r
102 // debug ("line = %d, level = %d", line, level);
\r
104 if (kGlobal.InList(buff)) state = SCE_GC_GLOBAL;
\r
105 else if (kAttribute.InList(buff)) state = SCE_GC_ATTRIBUTE;
\r
106 else if (kControl.InList(buff)) state = SCE_GC_CONTROL;
\r
107 else if (kCommand.InList(buff)) state = SCE_GC_COMMAND;
\r
108 else if (kEvent.InList(buff)) state = SCE_GC_EVENT;
\r
111 { sc->ChangeState(state);
\r
112 styler.ColourTo(sc->currentPos - 1, sc->state);
\r
113 sc->ChangeState(SCE_GC_DEFAULT);
\r
116 { sc->ChangeState(SCE_GC_DEFAULT);
\r
117 styler.ColourTo(sc->currentPos - 1, sc->state);
\r
121 // Main colorizing function called by Scintilla
\r
123 ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle,
\r
124 WordList *keywordlists[], Accessor &styler)
\r
126 styler.StartAt(startPos);
\r
128 int quotestart = 0, oldstate, currentline = styler.GetLine(startPos);
\r
129 styler.StartSegment(startPos);
\r
131 char buff[BUFFSIZE+1]; // buffer for command name
\r
133 StyleContext sc(startPos, length, initStyle, styler);
\r
134 buff[0] = '\0'; // cbuff = 0;
\r
136 if (sc.state != SCE_GC_COMMENTBLOCK) // colorize 1st word..
\r
137 colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
\r
145 if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING)
\r
147 if (sc.chNext == '/') // line comment
\r
148 { sc.SetState (SCE_GC_COMMENTLINE);
\r
150 styler.ColourTo(sc.currentPos, sc.state);
\r
152 else if (sc.chNext == '*') // block comment
\r
153 { sc.SetState(SCE_GC_COMMENTBLOCK);
\r
155 styler.ColourTo(sc.currentPos, sc.state);
\r
158 styler.ColourTo(sc.currentPos, sc.state);
\r
161 case '*': // end of comment block, or operator..
\r
162 if (sc.state == SCE_GC_STRING)
\r
164 if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/')
\r
166 styler.ColourTo(sc.currentPos, sc.state);
\r
167 sc.ChangeState (SCE_GC_DEFAULT);
\r
170 styler.ColourTo(sc.currentPos, sc.state);
\r
173 case '\'': case '\"': // strings..
\r
174 if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE)
\r
176 if (sc.state == SCE_GC_STRING)
\r
177 { if (sc.ch == quotestart) // match same quote char..
\r
178 { styler.ColourTo(sc.currentPos, sc.state);
\r
179 sc.ChangeState(SCE_GC_DEFAULT);
\r
183 { styler.ColourTo(sc.currentPos - 1, sc.state);
\r
184 sc.ChangeState(SCE_GC_STRING);
\r
185 quotestart = sc.ch;
\r
189 case ';': // end of commandline character
\r
190 if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
\r
191 sc.state != SCE_GC_STRING)
\r
193 styler.ColourTo(sc.currentPos - 1, sc.state);
\r
194 styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
\r
195 sc.ChangeState(SCE_GC_DEFAULT);
\r
197 colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
\r
198 noforward = 1; // don't move forward - already positioned at next char..
\r
202 case '+': case '-': case '=': case '!': // operators..
\r
203 case '<': case '>': case '&': case '|': case '$':
\r
204 if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE &&
\r
205 sc.state != SCE_GC_STRING)
\r
207 styler.ColourTo(sc.currentPos - 1, sc.state);
\r
208 styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
\r
209 sc.ChangeState(SCE_GC_DEFAULT);
\r
213 case '\\': // escape - same as operator, but also mark in strings..
\r
214 if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE)
\r
216 oldstate = sc.state;
\r
217 styler.ColourTo(sc.currentPos - 1, sc.state);
\r
218 sc.Forward(); // mark also the next char..
\r
219 styler.ColourTo(sc.currentPos, SCE_GC_OPERATOR);
\r
220 sc.ChangeState(oldstate);
\r
224 case '\n': case '\r':
\r
226 if (sc.state == SCE_GC_COMMENTLINE)
\r
227 { styler.ColourTo(sc.currentPos, sc.state);
\r
228 sc.ChangeState (SCE_GC_DEFAULT);
\r
230 else if (sc.state != SCE_GC_COMMENTBLOCK)
\r
231 { colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
\r
232 noforward = 1; // don't move forward - already positioned at next char..
\r
236 // case ' ': case '\t':
\r
240 if (!noforward) sc.Forward();
\r
246 // Main folding function called by Scintilla - (based on props (.ini) files function)
\r
247 static void FoldGui4Cli(unsigned int startPos, int length, int,
\r
248 WordList *[], Accessor &styler)
\r
250 bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
\r
252 unsigned int endPos = startPos + length;
\r
253 int visibleChars = 0;
\r
254 int lineCurrent = styler.GetLine(startPos);
\r
256 char chNext = styler[startPos];
\r
257 int styleNext = styler.StyleAt(startPos);
\r
258 bool headerPoint = false;
\r
260 for (unsigned int i = startPos; i < endPos; i++)
\r
263 chNext = styler[i+1];
\r
265 int style = styleNext;
\r
266 styleNext = styler.StyleAt(i + 1);
\r
267 bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
\r
269 if (style == SCE_GC_EVENT || style == SCE_GC_GLOBAL)
\r
270 { headerPoint = true; // fold at events and globals
\r
274 { int lev = SC_FOLDLEVELBASE+1;
\r
277 lev = SC_FOLDLEVELBASE;
\r
279 if (visibleChars == 0 && foldCompact)
\r
280 lev |= SC_FOLDLEVELWHITEFLAG;
\r
283 lev |= SC_FOLDLEVELHEADERFLAG;
\r
285 if (lev != styler.LevelAt(lineCurrent)) // set level, if not already correct
\r
286 { styler.SetLevel(lineCurrent, lev);
\r
289 lineCurrent++; // re-initialize our flags
\r
291 headerPoint = false;
\r
294 if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK)))
\r
298 int lev = headerPoint ? SC_FOLDLEVELBASE : SC_FOLDLEVELBASE+1;
\r
299 int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
\r
300 styler.SetLevel(lineCurrent, lev | flagsNext);
\r
303 // I have no idea what these are for.. probably accessible by some message.
\r
304 static const char * const gui4cliWordListDesc[] = {
\r
305 "Globals", "Events", "Attributes", "Control", "Commands",
\r
309 // Declare language & pass our function pointers to Scintilla
\r
310 LexerModule lmGui4Cli(SCLEX_GUI4CLI, ColouriseGui4CliDoc, "gui4cli", FoldGui4Cli, gui4cliWordListDesc);
\r