Scintilla 4.0.3
[TortoiseGit.git] / ext / scintilla / lexers / LexGui4Cli.cxx
blob547d8ca65d868d5bf892e86c05d791ca207391ec
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
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
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
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <assert.h>
29 #include <ctype.h>
31 #include "ILexer.h"
32 #include "Scintilla.h"
33 #include "SciLexer.h"
35 #include "WordList.h"
36 #include "LexAccessor.h"
37 #include "Accessor.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)
51 { if (isalnum(ch))
52 return false;
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 == ':')
58 return true;
59 return false;
62 #define isSpace(x) ((x)==' ' || (x)=='\t')
63 #define isNL(x) ((x)=='\n' || (x)=='\r')
64 #define isSpaceOrNL(x) (isSpace(x) || isNL(x))
65 #define BUFFSIZE 500
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)
71 Sci_Position c = 0;
72 while (sc->More() && isSpaceOrNL(sc->ch))
73 { sc->Forward();
75 styler.ColourTo(sc->currentPos - 1, sc->state);
77 if (!IsAWordChar(sc->ch)) // comment, marker, etc..
78 return;
80 while (sc->More() && !isSpaceOrNL(sc->ch) && (c < length-1) && !isGCOperator(sc->ch))
81 { buff[c] = static_cast<char>(sc->ch);
82 ++c; sc->Forward();
84 buff[c] = '\0';
85 char *p = buff;
86 while (*p) // capitalize..
87 { if (islower(*p)) *p = static_cast<char>(toupper(*p));
88 ++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];
97 int state = 0;
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;
107 if (state)
108 { sc->ChangeState(state);
109 styler.ColourTo(sc->currentPos - 1, sc->state);
110 sc->ChangeState(SCE_GC_DEFAULT);
112 else
113 { sc->ChangeState(SCE_GC_DEFAULT);
114 styler.ColourTo(sc->currentPos - 1, sc->state);
118 // Main colorizing function called by Scintilla
119 static void
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);
128 bool noforward;
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);
137 while (sc.More())
138 { noforward = 0;
140 switch (sc.ch)
142 case '/':
143 if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_STRING)
144 break;
145 if (sc.chNext == '/') // line comment
146 { sc.SetState (SCE_GC_COMMENTLINE);
147 sc.Forward();
148 styler.ColourTo(sc.currentPos, sc.state);
150 else if (sc.chNext == '*') // block comment
151 { sc.SetState(SCE_GC_COMMENTBLOCK);
152 sc.Forward();
153 styler.ColourTo(sc.currentPos, sc.state);
155 else
156 styler.ColourTo(sc.currentPos, sc.state);
157 break;
159 case '*': // end of comment block, or operator..
160 if (sc.state == SCE_GC_STRING)
161 break;
162 if (sc.state == SCE_GC_COMMENTBLOCK && sc.chNext == '/')
163 { sc.Forward();
164 styler.ColourTo(sc.currentPos, sc.state);
165 sc.ChangeState (SCE_GC_DEFAULT);
167 else
168 styler.ColourTo(sc.currentPos, sc.state);
169 break;
171 case '\'': case '\"': // strings..
172 if (sc.state == SCE_GC_COMMENTBLOCK || sc.state == SCE_GC_COMMENTLINE)
173 break;
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);
178 quotestart = 0;
180 else
181 { styler.ColourTo(sc.currentPos - 1, sc.state);
182 sc.ChangeState(SCE_GC_STRING);
183 quotestart = sc.ch;
185 break;
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);
194 sc.Forward();
195 colorFirstWord(keywordlists, styler, &sc, buff, BUFFSIZE, currentline);
196 noforward = 1; // don't move forward - already positioned at next char..
198 break;
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);
209 break;
211 case '\\': // escape - same as operator, but also mark in strings..
212 if (sc.state != SCE_GC_COMMENTBLOCK && sc.state != SCE_GC_COMMENTLINE)
214 oldstate = sc.state;
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);
220 break;
222 case '\n': case '\r':
223 ++currentline;
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..
232 break;
234 // case ' ': case '\t':
235 // default :
238 if (!noforward) sc.Forward();
241 sc.Complete();
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++)
260 char ch = chNext;
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
271 if (atEOL)
272 { int lev = SC_FOLDLEVELBASE+1;
274 if (headerPoint)
275 lev = SC_FOLDLEVELBASE;
277 if (visibleChars == 0 && foldCompact)
278 lev |= SC_FOLDLEVELWHITEFLAG;
280 if (headerPoint)
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
288 visibleChars = 0;
289 headerPoint = false;
292 if (!(isspacechar(ch))) // || (style == SCE_GC_COMMENTLINE) || (style != SCE_GC_COMMENTBLOCK)))
293 visibleChars++;
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);
310 #undef debug