]> git.saurik.com Git - wxWidgets.git/blame - src/stc/scintilla/src/LexNsis.cxx
use wxWindow::NewControlId() instead of wxNewId() to avoid clashes with user-defined...
[wxWidgets.git] / src / stc / scintilla / src / LexNsis.cxx
CommitLineData
88a8b04e
RD
1// Scintilla source code edit control
2/** @file LexNsis.cxx
3 ** Lexer for NSIS
4 **/
1e9bafca
RD
5// Copyright 2003 - 2005 by Angelo Mandato <angelo [at] spaceblue [dot] com>
6// Last Updated: 03/13/2005
88a8b04e 7// The License.txt file describes the conditions under which this software may be distributed.
88a8b04e
RD
8#include <stdlib.h>
9#include <string.h>
10#include <ctype.h>
11#include <stdio.h>
12#include <stdarg.h>
13
14#include "Platform.h"
15
16#include "PropSet.h"
17#include "Accessor.h"
18#include "KeyWords.h"
19#include "Scintilla.h"
20#include "SciLexer.h"
21
22/*
591d01be
RD
23// located in SciLexer.h
24#define SCLEX_NSIS 43
88a8b04e
RD
25
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
591d01be 40#define SCE_NSIS_NUMBER 14
1e9bafca
RD
41// ADDED for Scintilla v1.63
42#define SCE_NSIS_SECTIONGROUP 15
43#define SCE_NSIS_PAGEEX 16
44#define SCE_NSIS_FUNCTIONDEF 17
45#define SCE_NSIS_COMMENTBOX 18
88a8b04e
RD
46*/
47
591d01be
RD
48static bool isNsisNumber(char ch)
49{
50 return (ch >= '0' && ch <= '9');
51}
52
53static bool isNsisChar(char ch)
54{
55 return (ch == '.' ) || (ch == '_' ) || isNsisNumber(ch) || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
56}
57
58static bool isNsisLetter(char ch)
59{
60 return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
61}
62
1e9bafca
RD
63static bool NsisNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler)
64{
65 int nNextLine = -1;
66 for( unsigned int i = start; i < end; i++ )
67 {
68 char cNext = styler.SafeGetCharAt( i );
69 if( cNext == '\n' )
70 {
71 nNextLine = i+1;
72 break;
73 }
74 }
75
76 if( nNextLine == -1 ) // We never foudn the next line...
77 return false;
78
79 for( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ )
80 {
81 char cNext = styler.SafeGetCharAt( firstChar );
82 if( cNext == ' ' )
83 continue;
84 if( cNext == '\t' )
85 continue;
86 if( cNext == '!' )
87 {
88 if( styler.Match(firstChar, "!else") )
89 return true;
90 }
91 break;
92 }
93
94 return false;
95}
96
5681ec3d 97static int NsisCmp( const char *s1, const char *s2, bool bIgnoreCase )
591d01be
RD
98{
99 if( bIgnoreCase )
100 return CompareCaseInsensitive( s1, s2);
101
102 return strcmp( s1, s2 );
103}
104
1e9bafca 105static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse, bool foldUtilityCmd )
591d01be 106{
1e9bafca
RD
107 int style = styler.StyleAt(end);
108
591d01be 109 // If the word is too long, it is not what we are looking for
1e9bafca 110 if( end - start > 20 )
591d01be
RD
111 return foldlevel;
112
1e9bafca
RD
113 if( foldUtilityCmd )
114 {
115 // Check the style at this point, if it is not valid, then return zero
116 if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF &&
117 style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_IFDEFINEDEF &&
118 style != SCE_NSIS_MACRODEF && style != SCE_NSIS_SECTIONGROUP &&
119 style != SCE_NSIS_PAGEEX )
120 return foldlevel;
121 }
122 else
123 {
124 if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF &&
125 style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_SECTIONGROUP &&
126 style != SCE_NSIS_PAGEEX )
127 return foldlevel;
128 }
591d01be
RD
129
130 int newFoldlevel = foldlevel;
131 bool bIgnoreCase = false;
132 if( styler.GetPropertyInt("nsis.ignorecase") == 1 )
133 bIgnoreCase = true;
134
1e9bafca
RD
135 char s[20]; // The key word we are looking for has atmost 13 characters
136 for (unsigned int i = 0; i < end - start + 1 && i < 19; i++)
591d01be
RD
137 {
138 s[i] = static_cast<char>( styler[ start + i ] );
139 s[i + 1] = '\0';
140 }
141
142 if( s[0] == '!' )
143 {
144 if( NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!macro", bIgnoreCase ) == 0 )
145 newFoldlevel++;
146 else if( NsisCmp(s, "!endif", bIgnoreCase) == 0 || NsisCmp(s, "!macroend", bIgnoreCase ) == 0 )
147 newFoldlevel--;
1e9bafca
RD
148 else if( bElse && NsisCmp(s, "!else", bIgnoreCase) == 0 )
149 newFoldlevel++;
591d01be
RD
150 }
151 else
152 {
1e9bafca 153 if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionGroup", bIgnoreCase ) == 0 || NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "SubSection", bIgnoreCase ) == 0 || NsisCmp(s, "PageEx", bIgnoreCase ) == 0 )
591d01be 154 newFoldlevel++;
1e9bafca 155 else if( NsisCmp(s, "SectionGroupEnd", bIgnoreCase ) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase ) == 0 )
591d01be
RD
156 newFoldlevel--;
157 }
1e9bafca 158
591d01be
RD
159 return newFoldlevel;
160}
161
162static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keywordLists[], Accessor &styler )
88a8b04e 163{
591d01be
RD
164 bool bIgnoreCase = false;
165 if( styler.GetPropertyInt("nsis.ignorecase") == 1 )
166 bIgnoreCase = true;
167
168 bool bUserVars = false;
169 if( styler.GetPropertyInt("nsis.uservars") == 1 )
170 bUserVars = true;
171
88a8b04e
RD
172 char s[100];
173
174 WordList &Functions = *keywordLists[0];
175 WordList &Variables = *keywordLists[1];
176 WordList &Lables = *keywordLists[2];
177 WordList &UserDefined = *keywordLists[3];
178
591d01be 179 for (unsigned int i = 0; i < end - start + 1 && i < 99; i++)
88a8b04e 180 {
591d01be
RD
181 if( bIgnoreCase )
182 s[i] = static_cast<char>( tolower(styler[ start + i ] ) );
183 else
184 s[i] = static_cast<char>( styler[ start + i ] );
88a8b04e
RD
185 s[i + 1] = '\0';
186 }
187
188 // Check for special words...
591d01be 189 if( NsisCmp(s, "!macro", bIgnoreCase ) == 0 || NsisCmp(s, "!macroend", bIgnoreCase) == 0 ) // Covers !micro and !microend
88a8b04e
RD
190 return SCE_NSIS_MACRODEF;
191
591d01be 192 if( NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 || NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!endif", bIgnoreCase) == 0 )
88a8b04e
RD
193 return SCE_NSIS_IFDEFINEDEF;
194
1e9bafca
RD
195 if( NsisCmp(s, "!else", bIgnoreCase ) == 0 ) // || NsisCmp(s, "!ifndef", bIgnoreCase) == 0 || NsisCmp(s, "!endif", bIgnoreCase) == 0 )
196 return SCE_NSIS_IFDEFINEDEF;
197
198 if( NsisCmp(s, "SectionGroup", bIgnoreCase) == 0 || NsisCmp(s, "SectionGroupEnd", bIgnoreCase) == 0 ) // Covers SectionGroup and SectionGroupEnd
199 return SCE_NSIS_SECTIONGROUP;
200
591d01be 201 if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase) == 0 ) // Covers Section and SectionEnd
88a8b04e
RD
202 return SCE_NSIS_SECTIONDEF;
203
591d01be 204 if( NsisCmp(s, "SubSection", bIgnoreCase) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd
88a8b04e
RD
205 return SCE_NSIS_SUBSECTIONDEF;
206
1e9bafca
RD
207 if( NsisCmp(s, "PageEx", bIgnoreCase) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase) == 0 ) // Covers PageEx and PageExEnd
208 return SCE_NSIS_PAGEEX;
209
210 if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 ) // Covers Function and FunctionEnd
211 return SCE_NSIS_FUNCTIONDEF;
88a8b04e
RD
212
213 if ( Functions.InList(s) )
214 return SCE_NSIS_FUNCTION;
215
216 if ( Variables.InList(s) )
217 return SCE_NSIS_VARIABLE;
218
219 if ( Lables.InList(s) )
220 return SCE_NSIS_LABEL;
221
222 if( UserDefined.InList(s) )
223 return SCE_NSIS_USERDEFINED;
224
591d01be 225 if( strlen(s) > 3 )
88a8b04e
RD
226 {
227 if( s[1] == '{' && s[strlen(s)-1] == '}' )
228 return SCE_NSIS_VARIABLE;
229 }
230
591d01be
RD
231 // See if the variable is a user defined variable
232 if( s[0] == '$' && bUserVars )
233 {
234 bool bHasSimpleNsisChars = true;
235 for (unsigned int j = 1; j < end - start + 1 && j < 99; j++)
236 {
237 if( !isNsisChar( s[j] ) )
238 {
239 bHasSimpleNsisChars = false;
240 break;
241 }
242 }
243
244 if( bHasSimpleNsisChars )
245 return SCE_NSIS_VARIABLE;
246 }
247
248 // To check for numbers
249 if( isNsisNumber( s[0] ) )
250 {
251 bool bHasSimpleNsisNumber = true;
252 for (unsigned int j = 1; j < end - start + 1 && j < 99; j++)
253 {
591d01be
RD
254 if( !isNsisNumber( s[j] ) )
255 {
256 bHasSimpleNsisNumber = false;
257 break;
258 }
259 }
260
261 if( bHasSimpleNsisNumber )
262 return SCE_NSIS_NUMBER;
263 }
264
88a8b04e
RD
265 return SCE_NSIS_DEFAULT;
266}
267
268static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
269{
270 int state = SCE_NSIS_DEFAULT;
1e9bafca
RD
271 if( startPos > 0 )
272 state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox
273
88a8b04e
RD
274 styler.StartAt( startPos );
275 styler.GetLine( startPos );
276
277 unsigned int nLengthDoc = startPos + length;
278 styler.StartSegment( startPos );
279
280 char cCurrChar;
591d01be
RD
281 bool bVarInString = false;
282 bool bClassicVarInString = false;
88a8b04e
RD
283
284 unsigned int i;
285 for( i = startPos; i < nLengthDoc; i++ )
286 {
287 cCurrChar = styler.SafeGetCharAt( i );
591d01be 288 char cNextChar = styler.SafeGetCharAt(i+1);
88a8b04e
RD
289
290 switch(state)
291 {
292 case SCE_NSIS_DEFAULT:
88a8b04e
RD
293 if( cCurrChar == ';' || cCurrChar == '#' ) // we have a comment line
294 {
295 styler.ColourTo(i-1, state );
296 state = SCE_NSIS_COMMENT;
297 break;
298 }
299 if( cCurrChar == '"' )
300 {
301 styler.ColourTo(i-1, state );
302 state = SCE_NSIS_STRINGDQ;
303 bVarInString = false;
591d01be 304 bClassicVarInString = false;
88a8b04e
RD
305 break;
306 }
307 if( cCurrChar == '\'' )
308 {
309 styler.ColourTo(i-1, state );
310 state = SCE_NSIS_STRINGRQ;
311 bVarInString = false;
591d01be 312 bClassicVarInString = false;
88a8b04e
RD
313 break;
314 }
315 if( cCurrChar == '`' )
316 {
317 styler.ColourTo(i-1, state );
318 state = SCE_NSIS_STRINGLQ;
319 bVarInString = false;
591d01be 320 bClassicVarInString = false;
88a8b04e
RD
321 break;
322 }
323
324 // NSIS KeyWord,Function, Variable, UserDefined:
591d01be 325 if( cCurrChar == '$' || isNsisChar(cCurrChar) || cCurrChar == '!' )
88a8b04e
RD
326 {
327 styler.ColourTo(i-1,state);
328 state = SCE_NSIS_FUNCTION;
591d01be
RD
329
330 // If it is a number, we must check and set style here first...
331 if( isNsisNumber(cCurrChar) && (cNextChar == '\t' || cNextChar == ' ' || cNextChar == '\r' || cNextChar == '\n' ) )
332 styler.ColourTo( i, SCE_NSIS_NUMBER);
333
88a8b04e
RD
334 break;
335 }
1e9bafca
RD
336
337 if( cCurrChar == '/' && cNextChar == '*' )
338 {
339 styler.ColourTo(i-1,state);
340 state = SCE_NSIS_COMMENTBOX;
341 break;
342 }
343
88a8b04e
RD
344 break;
345 case SCE_NSIS_COMMENT:
591d01be 346 if( cNextChar == '\n' || cNextChar == '\r' )
88a8b04e 347 {
1e9bafca
RD
348 // Special case:
349 if( cCurrChar == '\\' )
350 {
351 styler.ColourTo(i-2,state);
352 styler.ColourTo(i,SCE_NSIS_DEFAULT);
353 }
354 else
355 {
356 styler.ColourTo(i,state);
357 state = SCE_NSIS_DEFAULT;
358 }
88a8b04e
RD
359 }
360 break;
361 case SCE_NSIS_STRINGDQ:
1e9bafca
RD
362 case SCE_NSIS_STRINGLQ:
363 case SCE_NSIS_STRINGRQ:
364
365 if( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' )
366 break; // Ignore the next character, even if it is a quote of some sort
367
368 if( cCurrChar == '"' && state == SCE_NSIS_STRINGDQ )
88a8b04e 369 {
1e9bafca 370 styler.ColourTo(i,state);
88a8b04e 371 state = SCE_NSIS_DEFAULT;
1e9bafca 372 break;
88a8b04e 373 }
1e9bafca
RD
374
375 if( cCurrChar == '`' && state == SCE_NSIS_STRINGLQ )
376 {
377 styler.ColourTo(i,state);
88a8b04e 378 state = SCE_NSIS_DEFAULT;
1e9bafca 379 break;
88a8b04e 380 }
1e9bafca
RD
381
382 if( cCurrChar == '\'' && state == SCE_NSIS_STRINGRQ )
88a8b04e 383 {
1e9bafca 384 styler.ColourTo(i,state);
88a8b04e 385 state = SCE_NSIS_DEFAULT;
1e9bafca 386 break;
88a8b04e 387 }
1e9bafca
RD
388
389 if( cNextChar == '\r' || cNextChar == '\n' )
390 {
391 int nCurLine = styler.GetLine(i+1);
392 int nBack = i;
393 // We need to check if the previous line has a \ in it...
394 bool bNextLine = false;
395
396 while( nBack > 0 )
397 {
398 if( styler.GetLine(nBack) != nCurLine )
399 break;
400
401 char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here
402
403 if( cTemp == '\\' )
404 {
405 bNextLine = true;
406 break;
407 }
408 if( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' )
409 break;
410
411 nBack--;
412 }
413
414 if( bNextLine )
415 {
416 styler.ColourTo(i+1,state);
417 }
418 if( bNextLine == false )
419 {
420 styler.ColourTo(i,state);
421 state = SCE_NSIS_DEFAULT;
422 }
423 }
88a8b04e 424 break;
1e9bafca 425
88a8b04e
RD
426 case SCE_NSIS_FUNCTION:
427
428 // NSIS KeyWord:
591d01be
RD
429 if( cCurrChar == '$' )
430 state = SCE_NSIS_DEFAULT;
431 else if( cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) )
432 state = SCE_NSIS_DEFAULT;
433 else if( (isNsisChar(cCurrChar) && !isNsisChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' )
88a8b04e 434 {
1e9bafca 435 state = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler );
88a8b04e 436 styler.ColourTo( i, state);
591d01be 437 state = SCE_NSIS_DEFAULT;
88a8b04e 438 }
591d01be 439 else if( !isNsisChar( cCurrChar ) && cCurrChar != '{' && cCurrChar != '}' )
88a8b04e 440 {
591d01be
RD
441 if( classifyWordNsis( styler.GetStartSegment(), i-1, keywordLists, styler) == SCE_NSIS_NUMBER )
442 styler.ColourTo( i-1, SCE_NSIS_NUMBER );
443
88a8b04e
RD
444 state = SCE_NSIS_DEFAULT;
445
591d01be 446 if( cCurrChar == '"' )
88a8b04e
RD
447 {
448 state = SCE_NSIS_STRINGDQ;
449 bVarInString = false;
591d01be 450 bClassicVarInString = false;
88a8b04e 451 }
591d01be 452 else if( cCurrChar == '`' )
88a8b04e
RD
453 {
454 state = SCE_NSIS_STRINGLQ;
455 bVarInString = false;
591d01be 456 bClassicVarInString = false;
88a8b04e 457 }
591d01be 458 else if( cCurrChar == '\'' )
88a8b04e
RD
459 {
460 state = SCE_NSIS_STRINGRQ;
461 bVarInString = false;
591d01be 462 bClassicVarInString = false;
88a8b04e 463 }
591d01be
RD
464 else if( cCurrChar == '#' || cCurrChar == ';' )
465 {
88a8b04e 466 state = SCE_NSIS_COMMENT;
591d01be 467 }
88a8b04e
RD
468 }
469 break;
1e9bafca
RD
470 case SCE_NSIS_COMMENTBOX:
471
472 if( styler.SafeGetCharAt(i-1) == '*' && cCurrChar == '/' )
473 {
474 styler.ColourTo(i,state);
475 state = SCE_NSIS_DEFAULT;
476 }
477 break;
88a8b04e
RD
478 }
479
1e9bafca 480 if( state == SCE_NSIS_COMMENT || state == SCE_NSIS_COMMENTBOX )
88a8b04e
RD
481 {
482 styler.ColourTo(i,state);
483 }
484 else if( state == SCE_NSIS_STRINGDQ || state == SCE_NSIS_STRINGLQ || state == SCE_NSIS_STRINGRQ )
485 {
591d01be
RD
486 bool bIngoreNextDollarSign = false;
487 bool bUserVars = false;
488 if( styler.GetPropertyInt("nsis.uservars") == 1 )
489 bUserVars = true;
490
491 if( bVarInString && cCurrChar == '$' )
492 {
493 bVarInString = false;
494 bIngoreNextDollarSign = true;
495 }
1e9bafca 496 else if( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) )
591d01be 497 {
1e9bafca 498 styler.ColourTo( i+1, SCE_NSIS_STRINGVAR);
591d01be 499 bVarInString = false;
1e9bafca 500 bIngoreNextDollarSign = false;
591d01be
RD
501 }
502
503 // Covers "$INSTDIR and user vars like $MYVAR"
504 else if( bVarInString && !isNsisChar(cNextChar) )
505 {
506 int nWordState = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler);
88a8b04e 507 if( nWordState == SCE_NSIS_VARIABLE )
88a8b04e 508 styler.ColourTo( i, SCE_NSIS_STRINGVAR);
591d01be
RD
509 else if( bUserVars )
510 styler.ColourTo( i, SCE_NSIS_STRINGVAR);
511 bVarInString = false;
512 }
513 // Covers "${TEST}..."
514 else if( bClassicVarInString && cNextChar == '}' )
515 {
516 styler.ColourTo( i+1, SCE_NSIS_STRINGVAR);
517 bClassicVarInString = false;
518 }
519
520 // Start of var in string
521 if( !bIngoreNextDollarSign && cCurrChar == '$' && cNextChar == '{' )
88a8b04e
RD
522 {
523 styler.ColourTo( i-1, state);
591d01be
RD
524 bClassicVarInString = true;
525 bVarInString = false;
88a8b04e 526 }
591d01be
RD
527 else if( !bIngoreNextDollarSign && cCurrChar == '$' )
528 {
529 styler.ColourTo( i-1, state);
530 bVarInString = true;
531 bClassicVarInString = false;
532 }
88a8b04e
RD
533 }
534 }
88a8b04e 535
591d01be 536 // Colourise remaining document
1e9bafca 537 styler.ColourTo(nLengthDoc-1,state);
591d01be 538}
88a8b04e
RD
539
540static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
541{
542 // No folding enabled, no reason to continue...
543 if( styler.GetPropertyInt("fold") == 0 )
544 return;
545
1e9bafca
RD
546 bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1;
547 bool foldUtilityCmd = styler.GetPropertyInt("nsis.foldutilcmd", 1) == 1;
548 bool blockComment = false;
549
591d01be
RD
550 int lineCurrent = styler.GetLine(startPos);
551 unsigned int safeStartPos = styler.LineStart( lineCurrent );
552
553 bool bArg1 = true;
554 int nWordStart = -1;
555
556 int levelCurrent = SC_FOLDLEVELBASE;
88a8b04e
RD
557 if (lineCurrent > 0)
558 levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
559 int levelNext = levelCurrent;
1e9bafca
RD
560 int style = styler.StyleAt(safeStartPos);
561 if( style == SCE_NSIS_COMMENTBOX )
562 {
563 if( styler.SafeGetCharAt(safeStartPos) == '/' && styler.SafeGetCharAt(safeStartPos+1) == '*' )
564 levelNext++;
565 blockComment = true;
566 }
88a8b04e 567
591d01be 568 for (unsigned int i = safeStartPos; i < startPos + length; i++)
88a8b04e 569 {
591d01be 570 char chCurr = styler.SafeGetCharAt(i);
1e9bafca
RD
571 style = styler.StyleAt(i);
572 if( blockComment && style != SCE_NSIS_COMMENTBOX )
573 {
574 levelNext--;
575 blockComment = false;
576 }
577 else if( !blockComment && style == SCE_NSIS_COMMENTBOX )
578 {
579 levelNext++;
580 blockComment = true;
581 }
591d01be 582
1e9bafca 583 if( bArg1 && !blockComment)
591d01be
RD
584 {
585 if( nWordStart == -1 && (isNsisLetter(chCurr) || chCurr == '!') )
1e9bafca 586 {
591d01be 587 nWordStart = i;
1e9bafca
RD
588 }
589 else if( isNsisLetter(chCurr) == false && nWordStart > -1 )
591d01be 590 {
1e9bafca
RD
591 int newLevel = calculateFoldNsis( nWordStart, i-1, levelNext, styler, foldAtElse, foldUtilityCmd );
592
593 if( newLevel == levelNext )
594 {
595 if( foldAtElse && foldUtilityCmd )
596 {
597 if( NsisNextLineHasElse(i, startPos + length, styler) )
598 levelNext--;
599 }
600 }
601 else
591d01be
RD
602 levelNext = newLevel;
603 bArg1 = false;
604 }
605 }
606
607 if( chCurr == '\n' )
608 {
1e9bafca
RD
609 if( bArg1 && foldAtElse && foldUtilityCmd && !blockComment )
610 {
611 if( NsisNextLineHasElse(i, startPos + length, styler) )
612 levelNext--;
613 }
614
591d01be
RD
615 // If we are on a new line...
616 int levelUse = levelCurrent;
88a8b04e 617 int lev = levelUse | levelNext << 16;
1e9bafca 618 if (levelUse < levelNext )
88a8b04e
RD
619 lev |= SC_FOLDLEVELHEADERFLAG;
620 if (lev != styler.LevelAt(lineCurrent))
88a8b04e 621 styler.SetLevel(lineCurrent, lev);
591d01be 622
88a8b04e
RD
623 lineCurrent++;
624 levelCurrent = levelNext;
591d01be
RD
625 bArg1 = true; // New line, lets look at first argument again
626 nWordStart = -1;
627 }
628 }
88a8b04e
RD
629
630 int levelUse = levelCurrent;
631 int lev = levelUse | levelNext << 16;
632 if (levelUse < levelNext)
633 lev |= SC_FOLDLEVELHEADERFLAG;
634 if (lev != styler.LevelAt(lineCurrent))
88a8b04e 635 styler.SetLevel(lineCurrent, lev);
88a8b04e
RD
636}
637
638static const char * const nsisWordLists[] = {
639 "Functions",
640 "Variables",
641 "Lables",
642 "UserDefined",
643 0, };
644
645
646LexerModule lmNsis(SCLEX_NSIS, ColouriseNsisDoc, "nsis", FoldNsisDoc, nsisWordLists);
1e9bafca 647