| 1 | // Scintilla source code edit control | 
| 2 | // @file LexAU3.cxx | 
| 3 | // Lexer for AutoIt3 https://www.autoitscript.com/site/ | 
| 4 | // by Jos van der Zande, jvdzande@yahoo.com | 
| 5 | // | 
| 6 | // Changes: | 
| 7 | // March 28, 2004 - Added the standard Folding code | 
| 8 | // April 21, 2004 - Added Preprosessor Table + Syntax Highlighting | 
| 9 | //                  Fixed Number highlighting | 
| 10 | //                  Changed default isoperator to IsAOperator to have a better match to AutoIt3 | 
| 11 | //                  Fixed "#comments_start" -> "#comments-start" | 
| 12 | //                  Fixed "#comments_end" -> "#comments-end" | 
| 13 | //                  Fixed Sendkeys in Strings when not terminated with } | 
| 14 | //                  Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down} | 
| 15 | // April 26, 2004 - Fixed # pre-processor statement inside of comment block would invalidly change the color. | 
| 16 | //                  Added logic for #include <xyz.au3> to treat the <> as string | 
| 17 | //                  Added underscore to IsAOperator. | 
| 18 | // May 17, 2004   - Changed the folding logic from indent to keyword folding. | 
| 19 | //                  Added Folding logic for blocks of single-commentlines or commentblock. | 
| 20 | //                        triggered by: fold.comment=1 | 
| 21 | //                  Added Folding logic for preprocessor blocks triggered by fold.preprocessor=1 | 
| 22 | //                  Added Special for #region - #endregion syntax highlight and folding. | 
| 23 | // May 30, 2004   - Fixed issue with continuation lines on If statements. | 
| 24 | // June 5, 2004   - Added comma to Operators for better readability. | 
| 25 | //                  Added fold.compact support set with fold.compact=1 | 
| 26 | //                  Changed folding inside of #cs-#ce. Default is no keyword folding inside comment blocks when fold.comment=1 | 
| 27 | //                        it will now only happen when fold.comment=2. | 
| 28 | // Sep 5, 2004    - Added logic to handle colourizing words on the last line. | 
| 29 | //                        Typed Characters now show as "default" till they match any table. | 
| 30 | // Oct 10, 2004   - Added logic to show Comments in "Special" directives. | 
| 31 | // Nov  1, 2004   - Added better testing for Numbers supporting x and e notation. | 
| 32 | // Nov 28, 2004   - Added logic to handle continuation lines for syntax highlighting. | 
| 33 | // Jan 10, 2005   - Added Abbreviations Keyword used for expansion | 
| 34 | // Mar 24, 2005   - Updated Abbreviations Keywords to fix when followed by Operator. | 
| 35 | // Apr 18, 2005   - Updated #CE/#Comment-End logic to take a linecomment ";" into account | 
| 36 | //                - Added folding support for With...EndWith | 
| 37 | //                - Added support for a DOT in variable names | 
| 38 | //                - Fixed Underscore in CommentBlock | 
| 39 | // May 23, 2005   - Fixed the SentKey lexing in case of a missing } | 
| 40 | // Aug 11, 2005   - Fixed possible bug with s_save length > 100. | 
| 41 | // Aug 23, 2005   - Added Switch/endswitch support to the folding logic. | 
| 42 | // Sep 27, 2005   - Fixed the SentKey lexing logic in case of multiple sentkeys. | 
| 43 | // Mar 12, 2006   - Fixed issue with <> coloring as String in stead of Operator in rare occasions. | 
| 44 | // Apr  8, 2006   - Added support for AutoIt3 Standard UDF library (SCE_AU3_UDF) | 
| 45 | // Mar  9, 2007   - Fixed bug with + following a String getting the wrong Color. | 
| 46 | // Jun 20, 2007   - Fixed Commentblock issue when LF's are used as EOL. | 
| 47 | // Jul 26, 2007   - Fixed #endregion undetected bug. | 
| 48 | // | 
| 49 | // Copyright for Scintilla: 1998-2001 by Neil Hodgson <neilh@scintilla.org> | 
| 50 | // The License.txt file describes the conditions under which this software may be distributed. | 
| 51 | // Scintilla source code edit control | 
| 52 |  | 
| 53 | #include <stdlib.h> | 
| 54 | #include <string.h> | 
| 55 | #include <stdio.h> | 
| 56 | #include <stdarg.h> | 
| 57 | #include <assert.h> | 
| 58 | #include <ctype.h> | 
| 59 |  | 
| 60 | #include <string> | 
| 61 | #include <string_view> | 
| 62 |  | 
| 63 | #include "ILexer.h" | 
| 64 | #include "Scintilla.h" | 
| 65 | #include "SciLexer.h" | 
| 66 |  | 
| 67 | #include "WordList.h" | 
| 68 | #include "LexAccessor.h" | 
| 69 | #include "Accessor.h" | 
| 70 | #include "StyleContext.h" | 
| 71 | #include "CharacterSet.h" | 
| 72 | #include "LexerModule.h" | 
| 73 |  | 
| 74 | using namespace Lexilla; | 
| 75 |  | 
| 76 | static inline bool IsTypeCharacter(const int ch) | 
| 77 | { | 
| 78 |     return ch == '$'; | 
| 79 | } | 
| 80 | static inline bool IsAWordChar(const int ch) | 
| 81 | { | 
| 82 |     return (ch < 0x80) && (isalnum(ch) || ch == '_'); | 
| 83 | } | 
| 84 |  | 
| 85 | static inline bool IsAWordStart(const int ch) | 
| 86 | { | 
| 87 |     return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.'); | 
| 88 | } | 
| 89 |  | 
| 90 | static inline bool IsAOperator(char ch) { | 
| 91 | 	if (IsASCII(ch) && isalnum(ch)) | 
| 92 | 		return false; | 
| 93 | 	if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || | 
| 94 | 	    ch == '&' || ch == '^' || ch == '=' || ch == '<' || ch == '>' || | 
| 95 | 	    ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == ',' ) | 
| 96 | 		return true; | 
| 97 | 	return false; | 
| 98 | } | 
| 99 |  | 
| 100 | /////////////////////////////////////////////////////////////////////////////// | 
| 101 | // GetSendKey() filters the portion before and after a/multiple space(s) | 
| 102 | // and return the first portion to be looked-up in the table | 
| 103 | // also check if the second portion is valid... (up,down.on.off,toggle or a number) | 
| 104 | /////////////////////////////////////////////////////////////////////////////// | 
| 105 |  | 
| 106 | static int GetSendKey(const char *szLine, char *szKey) | 
| 107 | { | 
| 108 | 	int		nFlag	= 0; | 
| 109 | 	int		nStartFound	= 0; | 
| 110 | 	int		nKeyPos	= 0; | 
| 111 | 	int		nSpecPos= 0; | 
| 112 | 	int		nSpecNum= 1; | 
| 113 | 	int		nPos	= 0; | 
| 114 | 	char	cTemp; | 
| 115 | 	char	szSpecial[100]; | 
| 116 |  | 
| 117 | 	// split the portion of the sendkey in the part before and after the spaces | 
| 118 | 	while ( ( (cTemp = szLine[nPos]) != '\0')) | 
| 119 | 	{ | 
| 120 | 		// skip leading Ctrl/Shift/Alt state | 
| 121 | 		if (cTemp == '{') { | 
| 122 | 			nStartFound = 1; | 
| 123 | 		} | 
| 124 | 		// | 
| 125 | 		if (nStartFound == 1) { | 
| 126 | 			if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space | 
| 127 | 			{ | 
| 128 | 				nFlag = 1; | 
| 129 | 				// Add } to the end of the first bit for table lookup later. | 
| 130 | 				szKey[nKeyPos++] = '}'; | 
| 131 | 			} | 
| 132 | 			else if (cTemp == ' ') | 
| 133 | 			{ | 
| 134 | 				// skip other spaces | 
| 135 | 			} | 
| 136 | 			else if (nFlag == 0) | 
| 137 | 			{ | 
| 138 | 				// save first portion into var till space or } is hit | 
| 139 | 				szKey[nKeyPos++] = cTemp; | 
| 140 | 			} | 
| 141 | 			else if ((nFlag == 1) && (cTemp != '}')) | 
| 142 | 			{ | 
| 143 | 				// Save second portion into var... | 
| 144 | 				szSpecial[nSpecPos++] = cTemp; | 
| 145 | 				// check if Second portion is all numbers for repeat fuction | 
| 146 | 				if (isdigit(cTemp) == false) {nSpecNum = 0;} | 
| 147 | 			} | 
| 148 | 		} | 
| 149 | 		nPos++;									// skip to next char | 
| 150 |  | 
| 151 | 	} // End While | 
| 152 |  | 
| 153 |  | 
| 154 | 	// Check if the second portion is either a number or one of these keywords | 
| 155 | 	szKey[nKeyPos] = '\0'; | 
| 156 | 	szSpecial[nSpecPos] = '\0'; | 
| 157 | 	if (strcmp(szSpecial,"down" )== 0    || strcmp(szSpecial,"up" )== 0  || | 
| 158 | 		strcmp(szSpecial,"on" )== 0      || strcmp(szSpecial,"off" )== 0 || | 
| 159 | 		strcmp(szSpecial,"toggle" )== 0  || nSpecNum == 1 ) | 
| 160 | 	{ | 
| 161 | 		nFlag = 0; | 
| 162 | 	} | 
| 163 | 	else | 
| 164 | 	{ | 
| 165 | 		nFlag = 1; | 
| 166 | 	} | 
| 167 | 	return nFlag;  // 1 is bad, 0 is good | 
| 168 |  | 
| 169 | } // GetSendKey() | 
| 170 |  | 
| 171 | // | 
| 172 | // Routine to check the last "none comment" character on a line to see if its a continuation | 
| 173 | // | 
| 174 | static bool IsContinuationLine(Sci_PositionU szLine, Accessor &styler) | 
| 175 | { | 
| 176 | 	Sci_Position nsPos = styler.LineStart(szLine); | 
| 177 | 	Sci_Position nePos = styler.LineStart(szLine+1) - 2; | 
| 178 | 	//int stylech = styler.StyleAt(nsPos); | 
| 179 | 	while (nsPos < nePos) | 
| 180 | 	{ | 
| 181 | 		//stylech = styler.StyleAt(nePos); | 
| 182 | 		int stylech = styler.StyleAt(nsPos); | 
| 183 | 		if (!(stylech == SCE_AU3_COMMENT)) { | 
| 184 | 			char ch = styler.SafeGetCharAt(nePos); | 
| 185 | 			if (!isspacechar(ch)) { | 
| 186 | 				if (ch == '_') | 
| 187 | 					return true; | 
| 188 | 				else | 
| 189 | 					return false; | 
| 190 | 			} | 
| 191 | 		} | 
| 192 | 		nePos--; // skip to next char | 
| 193 | 	} // End While | 
| 194 | 	return false; | 
| 195 | } // IsContinuationLine() | 
| 196 |  | 
| 197 | // | 
| 198 | // syntax highlighting logic | 
| 199 | static void ColouriseAU3Doc(Sci_PositionU startPos, | 
| 200 | 							Sci_Position length, int initStyle, | 
| 201 | 							WordList *keywordlists[], | 
| 202 | 							Accessor &styler) { | 
| 203 |  | 
| 204 |     WordList &keywords = *keywordlists[0]; | 
| 205 |     WordList &keywords2 = *keywordlists[1]; | 
| 206 |     WordList &keywords3 = *keywordlists[2]; | 
| 207 |     WordList &keywords4 = *keywordlists[3]; | 
| 208 |     WordList &keywords5 = *keywordlists[4]; | 
| 209 |     WordList &keywords6 = *keywordlists[5]; | 
| 210 |     WordList &keywords7 = *keywordlists[6]; | 
| 211 |     WordList &keywords8 = *keywordlists[7]; | 
| 212 | 	// find the first previous line without continuation character at the end | 
| 213 | 	Sci_Position lineCurrent = styler.GetLine(startPos); | 
| 214 | 	Sci_Position s_startPos = startPos; | 
| 215 | 	// When not inside a Block comment: find First line without _ | 
| 216 | 	if (!(initStyle==SCE_AU3_COMMENTBLOCK)) { | 
| 217 | 		while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || | 
| 218 | 			   (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { | 
| 219 | 			lineCurrent--; | 
| 220 | 			startPos = styler.LineStart(lineCurrent); // get start position | 
| 221 | 			initStyle =  0;                           // reset the start style to 0 | 
| 222 | 		} | 
| 223 | 	} | 
| 224 | 	// Set the new length to include it from the start and set the start position | 
| 225 | 	length = length + s_startPos - startPos;      // correct the total length to process | 
| 226 |     styler.StartAt(startPos); | 
| 227 |  | 
| 228 |     StyleContext sc(startPos, length, initStyle, styler); | 
| 229 | 	char si;     // string indicator "=1 '=2 | 
| 230 | 	char ni;     // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3 | 
| 231 | 	char ci;     // comment indicator 0=not linecomment(;) | 
| 232 | 	char s_save[100] = "" ; | 
| 233 | 	si=0; | 
| 234 | 	ni=0; | 
| 235 | 	ci=0; | 
| 236 | 	//$$$ | 
| 237 |     for (; sc.More(); sc.Forward()) { | 
| 238 | 		char s[100]; | 
| 239 | 		sc.GetCurrentLowered(s, sizeof(s)); | 
| 240 | 		// ********************************************** | 
| 241 | 		// save the total current word for eof processing | 
| 242 | 		if (IsAWordChar(sc.ch) || sc.ch == '}') | 
| 243 | 		{ | 
| 244 | 			strcpy(s_save,s); | 
| 245 | 			int tp = static_cast<int>(strlen(s_save)); | 
| 246 | 			if (tp < 99) { | 
| 247 | 				s_save[tp] = static_cast<char>(tolower(sc.ch)); | 
| 248 | 				s_save[tp+1] = '\0'; | 
| 249 | 			} | 
| 250 | 		} | 
| 251 | 		// ********************************************** | 
| 252 | 		// | 
| 253 | 		switch (sc.state) | 
| 254 |         { | 
| 255 |             case SCE_AU3_COMMENTBLOCK: | 
| 256 |             { | 
| 257 | 				//Reset at line end | 
| 258 | 				if (sc.atLineEnd) { | 
| 259 | 					ci=0; | 
| 260 | 					if (strcmp(s, "#ce" )== 0 || strcmp(s, "#comments-end" )== 0) { | 
| 261 | 						if (sc.atLineEnd) | 
| 262 | 							sc.SetState(SCE_AU3_DEFAULT); | 
| 263 | 						else | 
| 264 | 							sc.SetState(SCE_AU3_COMMENTBLOCK); | 
| 265 | 					} | 
| 266 | 					break; | 
| 267 | 				} | 
| 268 | 				//skip rest of line when a ; is encountered | 
| 269 | 				if (sc.chPrev == ';') { | 
| 270 | 					ci=2; | 
| 271 | 					sc.SetState(SCE_AU3_COMMENTBLOCK); | 
| 272 | 				} | 
| 273 | 				// skip rest of the line | 
| 274 | 				if (ci==2) | 
| 275 | 					break; | 
| 276 | 				// check when first character is detected on the line | 
| 277 | 				if (ci==0) { | 
| 278 | 					if (IsAWordStart(static_cast<char>(sc.ch)) || IsAOperator(static_cast<char>(sc.ch))) { | 
| 279 | 						ci=1; | 
| 280 | 						sc.SetState(SCE_AU3_COMMENTBLOCK); | 
| 281 | 					} | 
| 282 | 					break; | 
| 283 | 				} | 
| 284 | 				if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments" ) == 0))) { | 
| 285 | 					if ((strcmp(s, "#ce" )== 0 || strcmp(s, "#comments-end" )== 0)) | 
| 286 | 							sc.SetState(SCE_AU3_COMMENT);  // set to comment line for the rest of the line | 
| 287 | 					else | 
| 288 | 						ci=2;  // line doesn't begin with #CE so skip the rest of the line | 
| 289 | 				} | 
| 290 | 				break; | 
| 291 | 			} | 
| 292 |             case SCE_AU3_COMMENT: | 
| 293 |             { | 
| 294 |                 if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} | 
| 295 |                 break; | 
| 296 |             } | 
| 297 |             case SCE_AU3_OPERATOR: | 
| 298 |             { | 
| 299 |                 // check if its a COMobject | 
| 300 | 				if (sc.chPrev == '.' && IsAWordChar(sc.ch)) { | 
| 301 | 					sc.SetState(SCE_AU3_COMOBJ); | 
| 302 | 				} | 
| 303 | 				else { | 
| 304 | 					sc.SetState(SCE_AU3_DEFAULT); | 
| 305 | 				} | 
| 306 |                 break; | 
| 307 |             } | 
| 308 |             case SCE_AU3_SPECIAL: | 
| 309 |             { | 
| 310 |                 if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} | 
| 311 | 				if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} | 
| 312 |                 break; | 
| 313 |             } | 
| 314 |             case SCE_AU3_KEYWORD: | 
| 315 |             { | 
| 316 |                 if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && (strcmp(s, "#comments" ) == 0 || strcmp(s, "#include" ) == 0)))) | 
| 317 |                 { | 
| 318 |                     if (!IsTypeCharacter(sc.ch)) | 
| 319 |                     { | 
| 320 | 						if (strcmp(s, "#cs" )== 0 || strcmp(s, "#comments-start" )== 0 ) | 
| 321 | 						{ | 
| 322 | 							sc.ChangeState(SCE_AU3_COMMENTBLOCK); | 
| 323 | 							sc.SetState(SCE_AU3_COMMENTBLOCK); | 
| 324 | 							break; | 
| 325 | 						} | 
| 326 | 						else if (keywords.InList(s)) { | 
| 327 | 							sc.ChangeState(SCE_AU3_KEYWORD); | 
| 328 | 							sc.SetState(SCE_AU3_DEFAULT); | 
| 329 | 						} | 
| 330 | 						else if (keywords2.InList(s)) { | 
| 331 | 							sc.ChangeState(SCE_AU3_FUNCTION); | 
| 332 | 							sc.SetState(SCE_AU3_DEFAULT); | 
| 333 | 						} | 
| 334 | 						else if (keywords3.InList(s)) { | 
| 335 | 							sc.ChangeState(SCE_AU3_MACRO); | 
| 336 | 							sc.SetState(SCE_AU3_DEFAULT); | 
| 337 | 						} | 
| 338 | 						else if (keywords5.InList(s)) { | 
| 339 | 							sc.ChangeState(SCE_AU3_PREPROCESSOR); | 
| 340 | 							sc.SetState(SCE_AU3_DEFAULT); | 
| 341 | 							if (strcmp(s, "#include" )== 0) | 
| 342 | 							{ | 
| 343 | 								si = 3;   // use to determine string start for #inlude <> | 
| 344 | 							} | 
| 345 | 						} | 
| 346 | 						else if (keywords6.InList(s)) { | 
| 347 | 							sc.ChangeState(SCE_AU3_SPECIAL); | 
| 348 | 							sc.SetState(SCE_AU3_SPECIAL); | 
| 349 | 						} | 
| 350 | 						else if ((keywords7.InList(s)) && (!IsAOperator(static_cast<char>(sc.ch)))) { | 
| 351 | 							sc.ChangeState(SCE_AU3_EXPAND); | 
| 352 | 							sc.SetState(SCE_AU3_DEFAULT); | 
| 353 | 						} | 
| 354 | 						else if (keywords8.InList(s)) { | 
| 355 | 							sc.ChangeState(SCE_AU3_UDF); | 
| 356 | 							sc.SetState(SCE_AU3_DEFAULT); | 
| 357 | 						} | 
| 358 | 						else if (strcmp(s, "_" ) == 0) { | 
| 359 | 							sc.ChangeState(SCE_AU3_OPERATOR); | 
| 360 | 							sc.SetState(SCE_AU3_DEFAULT); | 
| 361 | 						} | 
| 362 | 						else if (!IsAWordChar(sc.ch)) { | 
| 363 | 							sc.ChangeState(SCE_AU3_DEFAULT); | 
| 364 | 							sc.SetState(SCE_AU3_DEFAULT); | 
| 365 | 						} | 
| 366 | 					} | 
| 367 | 				} | 
| 368 |                 if (sc.atLineEnd) { | 
| 369 | 					sc.SetState(SCE_AU3_DEFAULT);} | 
| 370 |                 break; | 
| 371 |             } | 
| 372 | 			case SCE_AU3_NUMBER: | 
| 373 |             { | 
| 374 | 				// Numeric indicator error=9 normal=0 normal+dec=1 hex=2 E-not=3 | 
| 375 | 				// | 
| 376 | 				// test for Hex notation | 
| 377 | 				if (strcmp(s, "0" ) == 0 && (sc.ch == 'x' || sc.ch == 'X') && ni == 0) | 
| 378 | 				{ | 
| 379 | 					ni = 2; | 
| 380 | 					break; | 
| 381 | 				} | 
| 382 | 				// test for E notation | 
| 383 | 				if (IsADigit(sc.chPrev) && (sc.ch == 'e' || sc.ch == 'E') && ni <= 1) | 
| 384 | 				{ | 
| 385 | 					ni = 3; | 
| 386 | 					break; | 
| 387 | 				} | 
| 388 | 				//  Allow Hex characters inside hex numeric strings | 
| 389 | 				if ((ni == 2) && | 
| 390 | 					(sc.ch == 'a' || sc.ch == 'b' || sc.ch == 'c' || sc.ch == 'd' || sc.ch == 'e' || sc.ch == 'f' || | 
| 391 | 					 sc.ch == 'A' || sc.ch == 'B' || sc.ch == 'C' || sc.ch == 'D' || sc.ch == 'E' || sc.ch == 'F' )) | 
| 392 | 				{ | 
| 393 | 					break; | 
| 394 | 				} | 
| 395 | 				// test for 1 dec point only | 
| 396 | 				if (sc.ch == '.') | 
| 397 | 				{ | 
| 398 | 					if (ni==0) | 
| 399 | 					{ | 
| 400 | 						ni=1; | 
| 401 | 					} | 
| 402 | 					else | 
| 403 | 					{ | 
| 404 | 						ni=9; | 
| 405 | 					} | 
| 406 | 					break; | 
| 407 | 				} | 
| 408 | 				// end of numeric string ? | 
| 409 | 				if (!(IsADigit(sc.ch))) | 
| 410 | 				{ | 
| 411 | 					if (ni==9) | 
| 412 | 					{ | 
| 413 | 						sc.ChangeState(SCE_AU3_DEFAULT); | 
| 414 | 					} | 
| 415 | 					sc.SetState(SCE_AU3_DEFAULT); | 
| 416 | 				} | 
| 417 | 				break; | 
| 418 | 			} | 
| 419 | 			case SCE_AU3_VARIABLE: | 
| 420 | 			{ | 
| 421 | 				// Check if its a COMObject | 
| 422 | 				if (sc.ch == '.' && !IsADigit(sc.chNext)) { | 
| 423 | 					sc.SetState(SCE_AU3_OPERATOR); | 
| 424 | 				} | 
| 425 | 				else if (!IsAWordChar(sc.ch)) { | 
| 426 | 					sc.SetState(SCE_AU3_DEFAULT); | 
| 427 | 				} | 
| 428 | 				break; | 
| 429 |             } | 
| 430 | 			case SCE_AU3_COMOBJ: | 
| 431 | 			{ | 
| 432 | 				if (!(IsAWordChar(sc.ch))) { | 
| 433 | 					sc.SetState(SCE_AU3_DEFAULT); | 
| 434 | 				} | 
| 435 | 				break; | 
| 436 |             } | 
| 437 |             case SCE_AU3_STRING: | 
| 438 |             { | 
| 439 | 				// check for " to end a double qouted string or | 
| 440 | 				// check for ' to end a single qouted string | 
| 441 | 	            if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>')) | 
| 442 | 				{ | 
| 443 | 					sc.ForwardSetState(SCE_AU3_DEFAULT); | 
| 444 | 					si=0; | 
| 445 | 					break; | 
| 446 | 				} | 
| 447 |                 if (sc.atLineEnd) | 
| 448 | 				{ | 
| 449 | 					si=0; | 
| 450 | 					// at line end and not found a continuation char then reset to default | 
| 451 | 					Sci_Position lineCurrent = styler.GetLine(sc.currentPos); | 
| 452 | 					if (!IsContinuationLine(lineCurrent,styler)) | 
| 453 | 					{ | 
| 454 | 						sc.SetState(SCE_AU3_DEFAULT); | 
| 455 | 						break; | 
| 456 | 					} | 
| 457 | 				} | 
| 458 | 				// find Sendkeys in a STRING | 
| 459 | 				if (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ) { | 
| 460 | 					sc.SetState(SCE_AU3_SENT);} | 
| 461 | 				break; | 
| 462 |             } | 
| 463 |  | 
| 464 |             case SCE_AU3_SENT: | 
| 465 |             { | 
| 466 | 				// Send key string ended | 
| 467 | 				if (sc.chPrev == '}' && sc.ch != '}') | 
| 468 | 				{ | 
| 469 | 					// set color to SENDKEY when valid sendkey .. else set back to regular string | 
| 470 | 					char sk[100]; | 
| 471 | 					// split {111 222} and return {111} and check if 222 is valid. | 
| 472 | 					// if return code = 1 then invalid 222 so must be string | 
| 473 | 					if (GetSendKey(s,sk)) | 
| 474 | 					{ | 
| 475 | 						sc.ChangeState(SCE_AU3_STRING); | 
| 476 | 					} | 
| 477 | 					// if single char between {?} then its ok as sendkey for a single character | 
| 478 | 					else if (strlen(sk) == 3) | 
| 479 | 					{ | 
| 480 | 						sc.ChangeState(SCE_AU3_SENT); | 
| 481 | 					} | 
| 482 | 					// if sendkey {111} is in table then ok as sendkey | 
| 483 | 					else if (keywords4.InList(sk)) | 
| 484 | 					{ | 
| 485 | 						sc.ChangeState(SCE_AU3_SENT); | 
| 486 | 					} | 
| 487 | 					else | 
| 488 | 					{ | 
| 489 | 						sc.ChangeState(SCE_AU3_STRING); | 
| 490 | 					} | 
| 491 | 					sc.SetState(SCE_AU3_STRING); | 
| 492 | 				} | 
| 493 | 				else | 
| 494 | 				{ | 
| 495 | 					// check if the start is a valid SendKey start | 
| 496 | 					Sci_Position		nPos	= 0; | 
| 497 | 					int		nState	= 1; | 
| 498 | 					char	cTemp; | 
| 499 | 					while (!(nState == 2) && ((cTemp = s[nPos]) != '\0')) | 
| 500 | 					{ | 
| 501 | 						if (cTemp == '{' && nState == 1) | 
| 502 | 						{ | 
| 503 | 							nState = 2; | 
| 504 | 						} | 
| 505 | 						if (nState == 1 && !(cTemp == '+' || cTemp == '!' || cTemp == '^' || cTemp == '#' )) | 
| 506 | 						{ | 
| 507 | 							nState = 0; | 
| 508 | 						} | 
| 509 | 						nPos++; | 
| 510 | 					} | 
| 511 | 					//Verify characters infront of { ... if not assume  regular string | 
| 512 | 					if (nState == 1 && (!(sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ))) { | 
| 513 | 						sc.ChangeState(SCE_AU3_STRING); | 
| 514 | 						sc.SetState(SCE_AU3_STRING); | 
| 515 | 					} | 
| 516 | 					// If invalid character found then assume its a regular string | 
| 517 | 					if (nState == 0) { | 
| 518 | 						sc.ChangeState(SCE_AU3_STRING); | 
| 519 | 						sc.SetState(SCE_AU3_STRING); | 
| 520 | 					} | 
| 521 | 				} | 
| 522 | 				// check if next portion is again a sendkey | 
| 523 | 				if (sc.atLineEnd) | 
| 524 | 				{ | 
| 525 | 					sc.ChangeState(SCE_AU3_STRING); | 
| 526 | 					sc.SetState(SCE_AU3_DEFAULT); | 
| 527 | 					si = 0;  // reset string indicator | 
| 528 | 				} | 
| 529 | 				//* check in next characters following a sentkey are again a sent key | 
| 530 | 				// Need this test incase of 2 sentkeys like {F1}{ENTER} but not detect {{} | 
| 531 | 				if (sc.state == SCE_AU3_STRING && (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' )) { | 
| 532 | 					sc.SetState(SCE_AU3_SENT);} | 
| 533 | 				// check to see if the string ended... | 
| 534 | 				// Sendkey string isn't complete but the string ended.... | 
| 535 | 				if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'')) | 
| 536 | 				{ | 
| 537 | 					sc.ChangeState(SCE_AU3_STRING); | 
| 538 | 					sc.ForwardSetState(SCE_AU3_DEFAULT); | 
| 539 | 				} | 
| 540 | 				break; | 
| 541 |             } | 
| 542 |         }  //switch (sc.state) | 
| 543 |  | 
| 544 |         // Determine if a new state should be entered: | 
| 545 |  | 
| 546 | 		if (sc.state == SCE_AU3_DEFAULT) | 
| 547 |         { | 
| 548 |             if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);} | 
| 549 |             else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);} | 
| 550 |             else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);} | 
| 551 |             else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);} | 
| 552 |             else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);} | 
| 553 |             //else if (sc.ch == '_') {sc.SetState(SCE_AU3_KEYWORD);} | 
| 554 |             else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);}  // string after #include | 
| 555 |             else if (sc.ch == '\"') { | 
| 556 | 				sc.SetState(SCE_AU3_STRING); | 
| 557 | 				si = 1;	} | 
| 558 |             else if (sc.ch == '\'') { | 
| 559 | 				sc.SetState(SCE_AU3_STRING); | 
| 560 | 				si = 2;	} | 
| 561 |             else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) | 
| 562 | 			{ | 
| 563 | 				sc.SetState(SCE_AU3_NUMBER); | 
| 564 | 				ni = 0; | 
| 565 | 			} | 
| 566 |             else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);} | 
| 567 |             else if (IsAOperator(static_cast<char>(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);} | 
| 568 | 			else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);} | 
| 569 |         } | 
| 570 |     }      //for (; sc.More(); sc.Forward()) | 
| 571 |  | 
| 572 | 	//************************************* | 
| 573 | 	// Colourize the last word correctly | 
| 574 | 	//************************************* | 
| 575 | 	if (sc.state == SCE_AU3_KEYWORD) | 
| 576 | 		{ | 
| 577 | 		if (strcmp(s_save, "#cs" )== 0 || strcmp(s_save, "#comments-start" )== 0 ) | 
| 578 | 		{ | 
| 579 | 			sc.ChangeState(SCE_AU3_COMMENTBLOCK); | 
| 580 | 			sc.SetState(SCE_AU3_COMMENTBLOCK); | 
| 581 | 		} | 
| 582 | 		else if (keywords.InList(s_save)) { | 
| 583 | 			sc.ChangeState(SCE_AU3_KEYWORD); | 
| 584 | 			sc.SetState(SCE_AU3_KEYWORD); | 
| 585 | 		} | 
| 586 | 		else if (keywords2.InList(s_save)) { | 
| 587 | 			sc.ChangeState(SCE_AU3_FUNCTION); | 
| 588 | 			sc.SetState(SCE_AU3_FUNCTION); | 
| 589 | 		} | 
| 590 | 		else if (keywords3.InList(s_save)) { | 
| 591 | 			sc.ChangeState(SCE_AU3_MACRO); | 
| 592 | 			sc.SetState(SCE_AU3_MACRO); | 
| 593 | 		} | 
| 594 | 		else if (keywords5.InList(s_save)) { | 
| 595 | 			sc.ChangeState(SCE_AU3_PREPROCESSOR); | 
| 596 | 			sc.SetState(SCE_AU3_PREPROCESSOR); | 
| 597 | 		} | 
| 598 | 		else if (keywords6.InList(s_save)) { | 
| 599 | 			sc.ChangeState(SCE_AU3_SPECIAL); | 
| 600 | 			sc.SetState(SCE_AU3_SPECIAL); | 
| 601 | 		} | 
| 602 | 		else if (keywords7.InList(s_save) && sc.atLineEnd) { | 
| 603 | 			sc.ChangeState(SCE_AU3_EXPAND); | 
| 604 | 			sc.SetState(SCE_AU3_EXPAND); | 
| 605 | 		} | 
| 606 | 		else if (keywords8.InList(s_save)) { | 
| 607 | 			sc.ChangeState(SCE_AU3_UDF); | 
| 608 | 			sc.SetState(SCE_AU3_UDF); | 
| 609 | 		} | 
| 610 | 		else { | 
| 611 | 			sc.ChangeState(SCE_AU3_DEFAULT); | 
| 612 | 			sc.SetState(SCE_AU3_DEFAULT); | 
| 613 | 		} | 
| 614 | 	} | 
| 615 | 	if (sc.state == SCE_AU3_SENT) | 
| 616 |     { | 
| 617 | 		// Send key string ended | 
| 618 | 		if (sc.chPrev == '}' && sc.ch != '}') | 
| 619 | 		{ | 
| 620 | 			// set color to SENDKEY when valid sendkey .. else set back to regular string | 
| 621 | 			char sk[100]; | 
| 622 | 			// split {111 222} and return {111} and check if 222 is valid. | 
| 623 | 			// if return code = 1 then invalid 222 so must be string | 
| 624 | 			if (GetSendKey(s_save,sk)) | 
| 625 | 			{ | 
| 626 | 				sc.ChangeState(SCE_AU3_STRING); | 
| 627 | 			} | 
| 628 | 			// if single char between {?} then its ok as sendkey for a single character | 
| 629 | 			else if (strlen(sk) == 3) | 
| 630 | 			{ | 
| 631 | 				sc.ChangeState(SCE_AU3_SENT); | 
| 632 | 			} | 
| 633 | 			// if sendkey {111} is in table then ok as sendkey | 
| 634 | 			else if (keywords4.InList(sk)) | 
| 635 | 			{ | 
| 636 | 				sc.ChangeState(SCE_AU3_SENT); | 
| 637 | 			} | 
| 638 | 			else | 
| 639 | 			{ | 
| 640 | 				sc.ChangeState(SCE_AU3_STRING); | 
| 641 | 			} | 
| 642 | 			sc.SetState(SCE_AU3_STRING); | 
| 643 | 		} | 
| 644 | 		// check if next portion is again a sendkey | 
| 645 | 		if (sc.atLineEnd) | 
| 646 | 		{ | 
| 647 | 			sc.ChangeState(SCE_AU3_STRING); | 
| 648 | 			sc.SetState(SCE_AU3_DEFAULT); | 
| 649 | 		} | 
| 650 |     } | 
| 651 | 	//************************************* | 
| 652 | 	sc.Complete(); | 
| 653 | } | 
| 654 |  | 
| 655 | // | 
| 656 | static bool (int style) { | 
| 657 | 	return style == SCE_AU3_COMMENT || style == SCE_AU3_COMMENTBLOCK; | 
| 658 | } | 
| 659 |  | 
| 660 | // | 
| 661 | // Routine to find first none space on the current line and return its Style | 
| 662 | // needed for comment lines not starting on pos 1 | 
| 663 | static int GetStyleFirstWord(Sci_PositionU szLine, Accessor &styler) | 
| 664 | { | 
| 665 | 	Sci_Position nsPos = styler.LineStart(szLine); | 
| 666 | 	Sci_Position nePos = styler.LineStart(szLine+1) - 1; | 
| 667 | 	while (isspacechar(styler.SafeGetCharAt(nsPos)) && nsPos < nePos) | 
| 668 | 	{ | 
| 669 | 		nsPos++; // skip to next char | 
| 670 |  | 
| 671 | 	} // End While | 
| 672 | 	return styler.StyleAt(nsPos); | 
| 673 |  | 
| 674 | } // GetStyleFirstWord() | 
| 675 |  | 
| 676 |  | 
| 677 | // | 
| 678 | static void FoldAU3Doc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) | 
| 679 | { | 
| 680 | 	Sci_Position endPos = startPos + length; | 
| 681 | 	// get settings from the config files for folding comments and preprocessor lines | 
| 682 | 	bool  = styler.GetPropertyInt("fold.comment" ) != 0; | 
| 683 | 	bool  = styler.GetPropertyInt("fold.comment" ) == 2; | 
| 684 | 	bool foldCompact = styler.GetPropertyInt("fold.compact" , 1) != 0; | 
| 685 | 	bool foldpreprocessor = styler.GetPropertyInt("fold.preprocessor" ) != 0; | 
| 686 | 	// Backtrack to previous line in case need to fix its fold status | 
| 687 | 	Sci_Position lineCurrent = styler.GetLine(startPos); | 
| 688 | 	if (startPos > 0) { | 
| 689 | 		if (lineCurrent > 0) { | 
| 690 | 			lineCurrent--; | 
| 691 | 			startPos = styler.LineStart(lineCurrent); | 
| 692 | 		} | 
| 693 | 	} | 
| 694 | 	// vars for style of previous/current/next lines | 
| 695 | 	int style = GetStyleFirstWord(lineCurrent,styler); | 
| 696 | 	int stylePrev = 0; | 
| 697 | 	// find the first previous line without continuation character at the end | 
| 698 | 	while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || | 
| 699 | 	       (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { | 
| 700 | 		lineCurrent--; | 
| 701 | 		startPos = styler.LineStart(lineCurrent); | 
| 702 | 	} | 
| 703 | 	if (lineCurrent > 0) { | 
| 704 | 		stylePrev = GetStyleFirstWord(lineCurrent-1,styler); | 
| 705 | 	} | 
| 706 | 	// vars for getting first word to check for keywords | 
| 707 | 	bool FirstWordStart = false; | 
| 708 | 	bool FirstWordEnd = false; | 
| 709 | 	char szKeyword[11]="" ; | 
| 710 | 	int	 szKeywordlen = 0; | 
| 711 | 	char szThen[5]="" ; | 
| 712 | 	int	 szThenlen = 0; | 
| 713 | 	bool ThenFoundLast = false; | 
| 714 | 	// var for indentlevel | 
| 715 | 	int levelCurrent = SC_FOLDLEVELBASE; | 
| 716 | 	if (lineCurrent > 0) | 
| 717 | 		levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; | 
| 718 | 	int levelNext = levelCurrent; | 
| 719 | 	// | 
| 720 | 	int	visibleChars = 0; | 
| 721 | 	char chNext = styler.SafeGetCharAt(startPos); | 
| 722 | 	char chPrev = ' '; | 
| 723 | 	// | 
| 724 | 	for (Sci_Position i = startPos; i < endPos; i++) { | 
| 725 | 		char ch = chNext; | 
| 726 | 		chNext = styler.SafeGetCharAt(i + 1); | 
| 727 | 		if (IsAWordChar(ch)) { | 
| 728 | 			visibleChars++; | 
| 729 | 		} | 
| 730 | 		// get the syle for the current character neede to check in comment | 
| 731 | 		int stylech = styler.StyleAt(i); | 
| 732 | 		// get first word for the line for indent check max 9 characters | 
| 733 | 		if (FirstWordStart && (!(FirstWordEnd))) { | 
| 734 | 			if (!IsAWordChar(ch)) { | 
| 735 | 				FirstWordEnd = true; | 
| 736 | 				szKeyword[szKeywordlen] = '\0'; | 
| 737 | 			} | 
| 738 | 			else { | 
| 739 | 				if (szKeywordlen < 10) { | 
| 740 | 				szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch)); | 
| 741 | 				} | 
| 742 | 			} | 
| 743 | 		} | 
| 744 | 		// start the capture of the first word | 
| 745 | 		if (!(FirstWordStart)) { | 
| 746 | 			if (IsAWordChar(ch) || IsAWordStart(ch) || ch == ';') { | 
| 747 | 				FirstWordStart = true; | 
| 748 | 				szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch)); | 
| 749 | 			} | 
| 750 | 		} | 
| 751 | 		// only process this logic when not in comment section | 
| 752 | 		if (!(stylech == SCE_AU3_COMMENT)) { | 
| 753 | 			if (ThenFoundLast) { | 
| 754 | 				if (IsAWordChar(ch)) { | 
| 755 | 					ThenFoundLast = false; | 
| 756 | 				} | 
| 757 | 			} | 
| 758 | 			// find out if the word "then" is the last on a "if" line | 
| 759 | 			if (FirstWordEnd && strcmp(szKeyword,"if" ) == 0) { | 
| 760 | 				if (szThenlen == 4) { | 
| 761 | 					szThen[0] = szThen[1]; | 
| 762 | 					szThen[1] = szThen[2]; | 
| 763 | 					szThen[2] = szThen[3]; | 
| 764 | 					szThen[3] = static_cast<char>(tolower(ch)); | 
| 765 | 					if (strcmp(szThen,"then" ) == 0 ) { | 
| 766 | 						ThenFoundLast = true; | 
| 767 | 					} | 
| 768 | 				} | 
| 769 | 				else { | 
| 770 | 					szThen[szThenlen++] = static_cast<char>(tolower(ch)); | 
| 771 | 					if (szThenlen == 5) { | 
| 772 | 						szThen[4] = '\0'; | 
| 773 | 					} | 
| 774 | 				} | 
| 775 | 			} | 
| 776 | 		} | 
| 777 | 		// End of Line found so process the information | 
| 778 | 		if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { | 
| 779 | 			// ************************** | 
| 780 | 			// Folding logic for Keywords | 
| 781 | 			// ************************** | 
| 782 | 			// if a keyword is found on the current line and the line doesn't end with _ (continuation) | 
| 783 | 			//    and we are not inside a commentblock. | 
| 784 | 			if (szKeywordlen > 0 && (!(chPrev == '_')) && | 
| 785 | 				((!(IsStreamCommentStyle(style)) || foldInComment)) ) { | 
| 786 | 				szKeyword[szKeywordlen] = '\0'; | 
| 787 | 				// only fold "if" last keyword is "then"  (else its a one line if) | 
| 788 | 				if (strcmp(szKeyword,"if" ) == 0  && ThenFoundLast) { | 
| 789 | 						levelNext++; | 
| 790 | 				} | 
| 791 | 				// create new fold for these words | 
| 792 | 				if (strcmp(szKeyword,"do" ) == 0   || strcmp(szKeyword,"for" ) == 0 || | 
| 793 | 					strcmp(szKeyword,"func" ) == 0 || strcmp(szKeyword,"while" ) == 0|| | 
| 794 | 					strcmp(szKeyword,"with" ) == 0 || strcmp(szKeyword,"#region" ) == 0 ) { | 
| 795 | 						levelNext++; | 
| 796 | 				} | 
| 797 | 				// create double Fold for select&switch because Case will subtract one of the current level | 
| 798 | 				if (strcmp(szKeyword,"select" ) == 0 || strcmp(szKeyword,"switch" ) == 0) { | 
| 799 | 						levelNext++; | 
| 800 | 						levelNext++; | 
| 801 | 				} | 
| 802 | 				// end the fold for these words before the current line | 
| 803 | 				if (strcmp(szKeyword,"endfunc" ) == 0 || strcmp(szKeyword,"endif" ) == 0 || | 
| 804 | 					strcmp(szKeyword,"next" ) == 0    || strcmp(szKeyword,"until" ) == 0 || | 
| 805 | 					strcmp(szKeyword,"endwith" ) == 0 ||strcmp(szKeyword,"wend" ) == 0){ | 
| 806 | 						levelNext--; | 
| 807 | 						levelCurrent--; | 
| 808 | 				} | 
| 809 | 				// end the fold for these words before the current line and Start new fold | 
| 810 | 				if (strcmp(szKeyword,"case" ) == 0      || strcmp(szKeyword,"else" ) == 0 || | 
| 811 | 					strcmp(szKeyword,"elseif" ) == 0 ) { | 
| 812 | 						levelCurrent--; | 
| 813 | 				} | 
| 814 | 				// end the double fold for this word before the current line | 
| 815 | 				if (strcmp(szKeyword,"endselect" ) == 0 || strcmp(szKeyword,"endswitch" ) == 0 ) { | 
| 816 | 						levelNext--; | 
| 817 | 						levelNext--; | 
| 818 | 						levelCurrent--; | 
| 819 | 						levelCurrent--; | 
| 820 | 				} | 
| 821 | 				// end the fold for these words on the current line | 
| 822 | 				if (strcmp(szKeyword,"#endregion" ) == 0 ) { | 
| 823 | 						levelNext--; | 
| 824 | 				} | 
| 825 | 			} | 
| 826 | 			// Preprocessor and Comment folding | 
| 827 | 			int styleNext = GetStyleFirstWord(lineCurrent + 1,styler); | 
| 828 | 			// ************************************* | 
| 829 | 			// Folding logic for preprocessor blocks | 
| 830 | 			// ************************************* | 
| 831 | 			// process preprosessor line | 
| 832 | 			if (foldpreprocessor && style == SCE_AU3_PREPROCESSOR) { | 
| 833 | 				if (!(stylePrev == SCE_AU3_PREPROCESSOR) && (styleNext == SCE_AU3_PREPROCESSOR)) { | 
| 834 | 				    levelNext++; | 
| 835 | 				} | 
| 836 | 				// fold till the last line for normal comment lines | 
| 837 | 				else if (stylePrev == SCE_AU3_PREPROCESSOR && !(styleNext == SCE_AU3_PREPROCESSOR)) { | 
| 838 | 					levelNext--; | 
| 839 | 				} | 
| 840 | 			} | 
| 841 | 			// ********************************* | 
| 842 | 			// Folding logic for Comment blocks | 
| 843 | 			// ********************************* | 
| 844 | 			if (foldComment && IsStreamCommentStyle(style)) { | 
| 845 | 				// Start of a comment block | 
| 846 | 				if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) { | 
| 847 | 				    levelNext++; | 
| 848 | 				} | 
| 849 | 				// fold till the last line for normal comment lines | 
| 850 | 				else if (IsStreamCommentStyle(stylePrev) | 
| 851 | 						&& !(styleNext == SCE_AU3_COMMENT) | 
| 852 | 						&& stylePrev == SCE_AU3_COMMENT | 
| 853 | 						&& style == SCE_AU3_COMMENT) { | 
| 854 | 					levelNext--; | 
| 855 | 				} | 
| 856 | 				// fold till the one but last line for Blockcomment lines | 
| 857 | 				else if (IsStreamCommentStyle(stylePrev) | 
| 858 | 						&& !(styleNext == SCE_AU3_COMMENTBLOCK) | 
| 859 | 						&& style == SCE_AU3_COMMENTBLOCK) { | 
| 860 | 					levelNext--; | 
| 861 | 					levelCurrent--; | 
| 862 | 				} | 
| 863 | 			} | 
| 864 | 			int levelUse = levelCurrent; | 
| 865 | 			int lev = levelUse | levelNext << 16; | 
| 866 | 			if (visibleChars == 0 && foldCompact) | 
| 867 | 				lev |= SC_FOLDLEVELWHITEFLAG; | 
| 868 | 			if (levelUse < levelNext) { | 
| 869 | 				lev |= SC_FOLDLEVELHEADERFLAG; | 
| 870 | 			} | 
| 871 | 			if (lev != styler.LevelAt(lineCurrent)) { | 
| 872 | 				styler.SetLevel(lineCurrent, lev); | 
| 873 | 			} | 
| 874 | 			// reset values for the next line | 
| 875 | 			lineCurrent++; | 
| 876 | 			stylePrev = style; | 
| 877 | 			style = styleNext; | 
| 878 | 			levelCurrent = levelNext; | 
| 879 | 			visibleChars = 0; | 
| 880 | 			// if the last character is an Underscore then don't reset since the line continues on the next line. | 
| 881 | 			if (!(chPrev == '_')) { | 
| 882 | 				szKeywordlen = 0; | 
| 883 | 				szThenlen = 0; | 
| 884 | 				FirstWordStart = false; | 
| 885 | 				FirstWordEnd = false; | 
| 886 | 				ThenFoundLast = false; | 
| 887 | 			} | 
| 888 | 		} | 
| 889 | 		// save the last processed character | 
| 890 | 		if (!isspacechar(ch)) { | 
| 891 | 			chPrev = ch; | 
| 892 | 			visibleChars++; | 
| 893 | 		} | 
| 894 | 	} | 
| 895 | } | 
| 896 |  | 
| 897 |  | 
| 898 | // | 
| 899 |  | 
| 900 | static const char * const AU3WordLists[] = { | 
| 901 |     "#autoit keywords" , | 
| 902 |     "#autoit functions" , | 
| 903 |     "#autoit macros" , | 
| 904 |     "#autoit Sent keys" , | 
| 905 |     "#autoit Pre-processors" , | 
| 906 |     "#autoit Special" , | 
| 907 |     "#autoit Expand" , | 
| 908 |     "#autoit UDF" , | 
| 909 |     0 | 
| 910 | }; | 
| 911 | LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3" , FoldAU3Doc , AU3WordLists); | 
| 912 |  |