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