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