]>
git.saurik.com Git - wxWidgets.git/blob - src/stc/scintilla/src/LexNsis.cxx
1 // Scintilla source code edit control
5 // Copyright 2003, 2004 by Angelo Mandato <angelo [at] spaceblue [dot] com>
6 // Last Updated: 02/22/2004
7 // The License.txt file describes the conditions under which this software may be distributed.
19 #include "Scintilla.h"
23 // located in SciLexer.h
26 #define SCE_NSIS_DEFAULT 0
27 #define SCE_NSIS_COMMENT 1
28 #define SCE_NSIS_STRINGDQ 2
29 #define SCE_NSIS_STRINGLQ 3
30 #define SCE_NSIS_STRINGRQ 4
31 #define SCE_NSIS_FUNCTION 5
32 #define SCE_NSIS_VARIABLE 6
33 #define SCE_NSIS_LABEL 7
34 #define SCE_NSIS_USERDEFINED 8
35 #define SCE_NSIS_SECTIONDEF 9
36 #define SCE_NSIS_SUBSECTIONDEF 10
37 #define SCE_NSIS_IFDEFINEDEF 11
38 #define SCE_NSIS_MACRODEF 12
39 #define SCE_NSIS_STRINGVAR 13
40 #define SCE_NSIS_NUMBER 14
43 static bool isNsisNumber(char ch
)
45 return (ch
>= '0' && ch
<= '9');
48 static bool isNsisChar(char ch
)
50 return (ch
== '.' ) || (ch
== '_' ) || isNsisNumber(ch
) || (ch
>= 'A' && ch
<= 'Z') || (ch
>= 'a' && ch
<= 'z');
53 static bool isNsisLetter(char ch
)
55 return (ch
>= 'A' && ch
<= 'Z') || (ch
>= 'a' && ch
<= 'z');
58 static int NsisCmp( char *s1
, char *s2
, bool bIgnoreCase
)
61 return CompareCaseInsensitive( s1
, s2
);
63 return strcmp( s1
, s2
);
66 static int calculateFoldNsis(unsigned int start
, unsigned int end
, int foldlevel
, Accessor
&styler
)
68 // If the word is too long, it is not what we are looking for
69 if( end
- start
> 13 )
72 // Check the style at this point, if it is not valid, then return zero
73 if( styler
.StyleAt(end
) != SCE_NSIS_FUNCTION
&& styler
.StyleAt(end
) != SCE_NSIS_SECTIONDEF
&&
74 styler
.StyleAt(end
) != SCE_NSIS_SUBSECTIONDEF
&& styler
.StyleAt(end
) != SCE_NSIS_IFDEFINEDEF
&&
75 styler
.StyleAt(end
) != SCE_NSIS_MACRODEF
)
78 int newFoldlevel
= foldlevel
;
79 bool bIgnoreCase
= false;
80 if( styler
.GetPropertyInt("nsis.ignorecase") == 1 )
83 char s
[15]; // The key word we are looking for has atmost 13 characters
84 for (unsigned int i
= 0; i
< end
- start
+ 1 && i
< 14; i
++)
86 s
[i
] = static_cast<char>( styler
[ start
+ i
] );
92 if( NsisCmp(s
, "!ifndef", bIgnoreCase
) == 0 || NsisCmp(s
, "!ifdef", bIgnoreCase
) == 0 || NsisCmp(s
, "!macro", bIgnoreCase
) == 0 )
94 else if( NsisCmp(s
, "!endif", bIgnoreCase
) == 0 || NsisCmp(s
, "!macroend", bIgnoreCase
) == 0 )
99 if( NsisCmp(s
, "Function", bIgnoreCase
) == 0 || NsisCmp(s
, "Section", bIgnoreCase
) == 0 || NsisCmp(s
, "SubSection", bIgnoreCase
) == 0 )
101 else if( NsisCmp(s
, "FunctionEnd", bIgnoreCase
) == 0 || NsisCmp(s
, "SectionEnd", bIgnoreCase
) == 0 || NsisCmp(s
, "SubSectionEnd", bIgnoreCase
) == 0 )
108 static int classifyWordNsis(unsigned int start
, unsigned int end
, WordList
*keywordLists
[], Accessor
&styler
)
110 bool bIgnoreCase
= false;
111 if( styler
.GetPropertyInt("nsis.ignorecase") == 1 )
114 bool bUserVars
= false;
115 if( styler
.GetPropertyInt("nsis.uservars") == 1 )
120 WordList
&Functions
= *keywordLists
[0];
121 WordList
&Variables
= *keywordLists
[1];
122 WordList
&Lables
= *keywordLists
[2];
123 WordList
&UserDefined
= *keywordLists
[3];
125 for (unsigned int i
= 0; i
< end
- start
+ 1 && i
< 99; i
++)
128 s
[i
] = static_cast<char>( tolower(styler
[ start
+ i
] ) );
130 s
[i
] = static_cast<char>( styler
[ start
+ i
] );
134 // Check for special words...
135 if( NsisCmp(s
, "!macro", bIgnoreCase
) == 0 || NsisCmp(s
, "!macroend", bIgnoreCase
) == 0 ) // Covers !micro and !microend
136 return SCE_NSIS_MACRODEF
;
138 if( NsisCmp(s
, "!ifdef", bIgnoreCase
) == 0 || NsisCmp(s
, "!ifndef", bIgnoreCase
) == 0 || NsisCmp(s
, "!endif", bIgnoreCase
) == 0 )
139 return SCE_NSIS_IFDEFINEDEF
;
141 if( NsisCmp(s
, "Section", bIgnoreCase
) == 0 || NsisCmp(s
, "SectionEnd", bIgnoreCase
) == 0 ) // Covers Section and SectionEnd
142 return SCE_NSIS_SECTIONDEF
;
144 if( NsisCmp(s
, "SubSection", bIgnoreCase
) == 0 || NsisCmp(s
, "SubSectionEnd", bIgnoreCase
) == 0 ) // Covers SubSection and SubSectionEnd
145 return SCE_NSIS_SUBSECTIONDEF
;
147 if( NsisCmp(s
, "Function", bIgnoreCase
) == 0 || NsisCmp(s
, "FunctionEnd", bIgnoreCase
) == 0 ) // Covers SubSection and SubSectionEnd
148 return SCE_NSIS_FUNCTION
;
150 if ( Functions
.InList(s
) )
151 return SCE_NSIS_FUNCTION
;
153 if ( Variables
.InList(s
) )
154 return SCE_NSIS_VARIABLE
;
156 if ( Lables
.InList(s
) )
157 return SCE_NSIS_LABEL
;
159 if( UserDefined
.InList(s
) )
160 return SCE_NSIS_USERDEFINED
;
164 if( s
[1] == '{' && s
[strlen(s
)-1] == '}' )
165 return SCE_NSIS_VARIABLE
;
168 // See if the variable is a user defined variable
169 if( s
[0] == '$' && bUserVars
)
171 bool bHasSimpleNsisChars
= true;
172 for (unsigned int j
= 1; j
< end
- start
+ 1 && j
< 99; j
++)
174 if( !isNsisChar( s
[j
] ) )
176 bHasSimpleNsisChars
= false;
181 if( bHasSimpleNsisChars
)
182 return SCE_NSIS_VARIABLE
;
185 // To check for numbers
186 if( isNsisNumber( s
[0] ) )
188 bool bHasSimpleNsisNumber
= true;
189 for (unsigned int j
= 1; j
< end
- start
+ 1 && j
< 99; j
++)
191 if( s
[j
] == '\0' || s
[j
] == '\r' || s
[j
] == '\n' )
194 if( !isNsisNumber( s
[j
] ) )
196 bHasSimpleNsisNumber
= false;
201 if( bHasSimpleNsisNumber
)
202 return SCE_NSIS_NUMBER
;
205 return SCE_NSIS_DEFAULT
;
208 static void ColouriseNsisDoc(unsigned int startPos
, int length
, int, WordList
*keywordLists
[], Accessor
&styler
)
210 int state
= SCE_NSIS_DEFAULT
;
211 styler
.StartAt( startPos
);
212 styler
.GetLine( startPos
);
214 unsigned int nLengthDoc
= startPos
+ length
;
215 styler
.StartSegment( startPos
);
218 bool bVarInString
= false;
219 bool bClassicVarInString
= false;
222 for( i
= startPos
; i
< nLengthDoc
; i
++ )
224 cCurrChar
= styler
.SafeGetCharAt( i
);
225 char cNextChar
= styler
.SafeGetCharAt(i
+1);
229 case SCE_NSIS_DEFAULT
:
230 if( cCurrChar
== ';' || cCurrChar
== '#' ) // we have a comment line
232 styler
.ColourTo(i
-1, state
);
233 state
= SCE_NSIS_COMMENT
;
236 if( cCurrChar
== '"' )
238 styler
.ColourTo(i
-1, state
);
239 state
= SCE_NSIS_STRINGDQ
;
240 bVarInString
= false;
241 bClassicVarInString
= false;
244 if( cCurrChar
== '\'' )
246 styler
.ColourTo(i
-1, state
);
247 state
= SCE_NSIS_STRINGRQ
;
248 bVarInString
= false;
249 bClassicVarInString
= false;
252 if( cCurrChar
== '`' )
254 styler
.ColourTo(i
-1, state
);
255 state
= SCE_NSIS_STRINGLQ
;
256 bVarInString
= false;
257 bClassicVarInString
= false;
261 // NSIS KeyWord,Function, Variable, UserDefined:
262 if( cCurrChar
== '$' || isNsisChar(cCurrChar
) || cCurrChar
== '!' )
264 styler
.ColourTo(i
-1,state
);
265 state
= SCE_NSIS_FUNCTION
;
267 // If it is a number, we must check and set style here first...
268 if( isNsisNumber(cCurrChar
) && (cNextChar
== '\t' || cNextChar
== ' ' || cNextChar
== '\r' || cNextChar
== '\n' ) )
269 styler
.ColourTo( i
, SCE_NSIS_NUMBER
);
274 case SCE_NSIS_COMMENT
:
275 if( cNextChar
== '\n' || cNextChar
== '\r' )
277 styler
.ColourTo(i
,state
);
278 state
= SCE_NSIS_DEFAULT
;
281 case SCE_NSIS_STRINGDQ
:
282 if( cCurrChar
== '"' || cNextChar
== '\r' || cNextChar
== '\n' )
284 styler
.ColourTo(i
,SCE_NSIS_STRINGDQ
);
285 state
= SCE_NSIS_DEFAULT
;
288 case SCE_NSIS_STRINGLQ
:
289 if( cCurrChar
== '`' || cNextChar
== '\r' || cNextChar
== '\n' )
291 styler
.ColourTo(i
,SCE_NSIS_STRINGLQ
);
292 state
= SCE_NSIS_DEFAULT
;
295 case SCE_NSIS_STRINGRQ
:
296 if( cCurrChar
== '\'' || cNextChar
== '\r' || cNextChar
== '\n' )
298 styler
.ColourTo(i
,SCE_NSIS_STRINGRQ
);
299 state
= SCE_NSIS_DEFAULT
;
302 case SCE_NSIS_FUNCTION
:
305 if( cCurrChar
== '$' )
306 state
= SCE_NSIS_DEFAULT
;
307 else if( cCurrChar
== '\\' && (cNextChar
== 'n' || cNextChar
== 'r' || cNextChar
== 't' ) )
308 state
= SCE_NSIS_DEFAULT
;
309 else if( (isNsisChar(cCurrChar
) && !isNsisChar( cNextChar
) && cNextChar
!= '}') || cCurrChar
== '}' )
311 state
= classifyWordNsis( styler
.GetStartSegment(), i
, keywordLists
, styler
);
312 styler
.ColourTo( i
, state
);
313 state
= SCE_NSIS_DEFAULT
;
315 else if( !isNsisChar( cCurrChar
) && cCurrChar
!= '{' && cCurrChar
!= '}' )
317 if( classifyWordNsis( styler
.GetStartSegment(), i
-1, keywordLists
, styler
) == SCE_NSIS_NUMBER
)
318 styler
.ColourTo( i
-1, SCE_NSIS_NUMBER
);
320 state
= SCE_NSIS_DEFAULT
;
322 if( cCurrChar
== '"' )
324 state
= SCE_NSIS_STRINGDQ
;
325 bVarInString
= false;
326 bClassicVarInString
= false;
328 else if( cCurrChar
== '`' )
330 state
= SCE_NSIS_STRINGLQ
;
331 bVarInString
= false;
332 bClassicVarInString
= false;
334 else if( cCurrChar
== '\'' )
336 state
= SCE_NSIS_STRINGRQ
;
337 bVarInString
= false;
338 bClassicVarInString
= false;
340 else if( cCurrChar
== '#' || cCurrChar
== ';' )
342 state
= SCE_NSIS_COMMENT
;
348 if( state
== SCE_NSIS_COMMENT
)
350 styler
.ColourTo(i
,state
);
352 else if( state
== SCE_NSIS_STRINGDQ
|| state
== SCE_NSIS_STRINGLQ
|| state
== SCE_NSIS_STRINGRQ
)
354 bool bIngoreNextDollarSign
= false;
355 bool bUserVars
= false;
356 if( styler
.GetPropertyInt("nsis.uservars") == 1 )
359 if( bVarInString
&& cCurrChar
== '$' )
361 bVarInString
= false;
362 bIngoreNextDollarSign
= true;
364 else if( bVarInString
&& cCurrChar
== '\\' && (cNextChar
== 'n' || cNextChar
== 'r' || cNextChar
== 't' ) )
366 bVarInString
= false;
367 bIngoreNextDollarSign
= true;
370 // Covers "$INSTDIR and user vars like $MYVAR"
371 else if( bVarInString
&& !isNsisChar(cNextChar
) )
373 int nWordState
= classifyWordNsis( styler
.GetStartSegment(), i
, keywordLists
, styler
);
374 if( nWordState
== SCE_NSIS_VARIABLE
)
375 styler
.ColourTo( i
, SCE_NSIS_STRINGVAR
);
377 styler
.ColourTo( i
, SCE_NSIS_STRINGVAR
);
378 bVarInString
= false;
380 // Covers "${TEST}..."
381 else if( bClassicVarInString
&& cNextChar
== '}' )
383 styler
.ColourTo( i
+1, SCE_NSIS_STRINGVAR
);
384 bClassicVarInString
= false;
387 // Start of var in string
388 if( !bIngoreNextDollarSign
&& cCurrChar
== '$' && cNextChar
== '{' )
390 styler
.ColourTo( i
-1, state
);
391 bClassicVarInString
= true;
392 bVarInString
= false;
394 else if( !bIngoreNextDollarSign
&& cCurrChar
== '$' )
396 styler
.ColourTo( i
-1, state
);
398 bClassicVarInString
= false;
403 // Colourise remaining document
406 case SCE_NSIS_COMMENT
:
407 case SCE_NSIS_STRINGDQ
:
408 case SCE_NSIS_STRINGLQ
:
409 case SCE_NSIS_STRINGRQ
:
410 case SCE_NSIS_VARIABLE
:
411 case SCE_NSIS_STRINGVAR
:
412 styler
.ColourTo(nLengthDoc
-1,state
); break;
415 styler
.ColourTo(nLengthDoc
-1,SCE_NSIS_DEFAULT
); break;
419 static void FoldNsisDoc(unsigned int startPos
, int length
, int, WordList
*[], Accessor
&styler
)
421 // No folding enabled, no reason to continue...
422 if( styler
.GetPropertyInt("fold") == 0 )
425 int lineCurrent
= styler
.GetLine(startPos
);
426 unsigned int safeStartPos
= styler
.LineStart( lineCurrent
);
431 int levelCurrent
= SC_FOLDLEVELBASE
;
433 levelCurrent
= styler
.LevelAt(lineCurrent
-1) >> 16;
434 int levelNext
= levelCurrent
;
436 for (unsigned int i
= safeStartPos
; i
< startPos
+ length
; i
++)
438 char chCurr
= styler
.SafeGetCharAt(i
);
440 if( bArg1
) //&& chCurr != '\n' )
442 if( nWordStart
== -1 && (isNsisLetter(chCurr
) || chCurr
== '!') )
444 else if( !isNsisLetter(chCurr
) && nWordStart
> -1 )
446 int newLevel
= calculateFoldNsis( nWordStart
, i
-1, levelNext
, styler
);
447 if( newLevel
!= levelNext
)
448 levelNext
= newLevel
;
455 // If we are on a new line...
456 int levelUse
= levelCurrent
;
457 int lev
= levelUse
| levelNext
<< 16;
458 if (levelUse
< levelNext
)
459 lev
|= SC_FOLDLEVELHEADERFLAG
;
460 if (lev
!= styler
.LevelAt(lineCurrent
))
461 styler
.SetLevel(lineCurrent
, lev
);
464 levelCurrent
= levelNext
;
465 bArg1
= true; // New line, lets look at first argument again
470 int levelUse
= levelCurrent
;
471 int lev
= levelUse
| levelNext
<< 16;
472 if (levelUse
< levelNext
)
473 lev
|= SC_FOLDLEVELHEADERFLAG
;
474 if (lev
!= styler
.LevelAt(lineCurrent
))
475 styler
.SetLevel(lineCurrent
, lev
);
478 static const char * const nsisWordLists
[] = {
486 LexerModule
lmNsis(SCLEX_NSIS
, ColouriseNsisDoc
, "nsis", FoldNsisDoc
, nsisWordLists
);