OSDN Git Service

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