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