~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/sdk/wxscintilla/src/scintilla/lexers/LexAU3.cxx

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

Show diffs side-by-side

added added

removed removed

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