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