~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/sdk/wxscintilla/src/scintilla/lexers/LexPowerPro.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 LexPowerPro.cxx
 
3
// PowerPro utility, written by Bruce Switzer, is available from http://powerpro.webeddie.com
 
4
// PowerPro lexer is written by Christopher Bean (cbean@cb-software.net)
 
5
//
 
6
// Lexer code heavily borrowed from:
 
7
//      LexAU3.cxx by Jos van der Zande
 
8
//      LexCPP.cxx by Neil Hodgson
 
9
//      LexVB.cxx by Neil Hodgson
 
10
//
 
11
// Changes:
 
12
//      2008-10-25 - Initial release
 
13
//      2008-10-26 - Changed how <name> is hilighted in  'function <name>' so that
 
14
//                               local isFunction = "" and local functions = "" don't get falsely highlighted
 
15
//      2008-12-14 - Added bounds checking for szFirstWord and szDo
 
16
//                         - Replaced SetOfCharacters with CharacterSet
 
17
//                         - Made sure that CharacterSet::Contains is passed only positive values
 
18
//                         - Made sure that the return value of Accessor::SafeGetCharAt is positive before
 
19
//                               passing to functions that require positive values like isspacechar()
 
20
//                         - Removed unused visibleChars processing from ColourisePowerProDoc()
 
21
//                         - Fixed bug with folding logic where line continuations didn't end where
 
22
//                               they were supposed to
 
23
//                         - Moved all helper functions to the top of the file
 
24
//      2010-06-03 - Added onlySpaces variable to allow the @function and ;comment styles to be indented
 
25
//                         - Modified HasFunction function to be a bit more robust
 
26
//                         - Renamed HasFunction function to IsFunction
 
27
//                         - Cleanup
 
28
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 
29
// The License.txt file describes the conditions under which this software may be distributed.
 
30
 
 
31
#include <string.h>
 
32
#include <assert.h>
 
33
#include <ctype.h>
 
34
 
 
35
#include "ILexer.h"
 
36
#include "Scintilla.h"
 
37
#include "SciLexer.h"
 
38
 
 
39
#include "WordList.h"
 
40
#include "LexAccessor.h"
 
41
#include "Accessor.h"
 
42
#include "StyleContext.h"
 
43
#include "CharacterSet.h"
 
44
#include "LexerModule.h"
 
45
 
 
46
#ifdef SCI_NAMESPACE
 
47
using namespace Scintilla;
 
48
#endif
 
49
 
 
50
static inline bool IsStreamCommentStyle(int style) {
 
51
        return style == SCE_POWERPRO_COMMENTBLOCK;
 
52
}
 
53
 
 
54
static inline bool IsLineEndChar(unsigned char ch) {
 
55
        return  ch == 0x0a              //LF
 
56
                        || ch == 0x0c   //FF
 
57
                        || ch == 0x0d;  //CR
 
58
}
 
59
 
 
60
static bool IsContinuationLine(unsigned int szLine, Accessor &styler)
 
61
{
 
62
        int startPos = styler.LineStart(szLine);
 
63
        int endPos = styler.LineStart(szLine + 1) - 2;
 
64
        while (startPos < endPos)
 
65
        {
 
66
                char stylech = styler.StyleAt(startPos);
 
67
                if (!(stylech == SCE_POWERPRO_COMMENTBLOCK)) {
 
68
                        char ch = styler.SafeGetCharAt(endPos);
 
69
                        char chPrev = styler.SafeGetCharAt(endPos - 1);
 
70
                        char chPrevPrev = styler.SafeGetCharAt(endPos - 2);
 
71
                        if (ch > 0 && chPrev > 0 && chPrevPrev > 0 && !isspacechar(ch) && !isspacechar(chPrev) && !isspacechar(chPrevPrev) )
 
72
                                return (chPrevPrev == ';' && chPrev == ';' && ch == '+');
 
73
                        }
 
74
                endPos--; // skip to next char
 
75
        }
 
76
        return false;
 
77
}
 
78
 
 
79
// Routine to find first none space on the current line and return its Style
 
80
// needed for comment lines not starting on pos 1
 
81
static int GetStyleFirstWord(int szLine, Accessor &styler)
 
82
{
 
83
        int startPos = styler.LineStart(szLine);
 
84
        int endPos = styler.LineStart(szLine + 1) - 1;
 
85
        char ch = styler.SafeGetCharAt(startPos);
 
86
 
 
87
        while (ch > 0 && isspacechar(ch) && startPos < endPos)
 
88
        {
 
89
                startPos++; // skip to next char
 
90
                ch = styler.SafeGetCharAt(startPos);
 
91
        }
 
92
        return styler.StyleAt(startPos);
 
93
}
 
94
 
 
95
//returns true if there is a function to highlight
 
96
//used to highlight <name> in 'function <name>'
 
97
//note:
 
98
//              sample line (without quotes): "\tfunction asdf()
 
99
//              currentPos will be the position of 'a'
 
100
static bool IsFunction(Accessor &styler, unsigned int currentPos) {
 
101
 
 
102
        const char function[10] = "function "; //10 includes \0
 
103
        unsigned int numberOfCharacters = sizeof(function) - 1;
 
104
        unsigned int position = currentPos - numberOfCharacters;
 
105
 
 
106
        //compare each character with the letters in the function array
 
107
        //return false if ALL don't match
 
108
        for (unsigned int i = 0; i < numberOfCharacters; i++) {
 
109
                char c = styler.SafeGetCharAt(position++);
 
110
                if (c != function[i])
 
111
                        return false;
 
112
        }
 
113
 
 
114
        //make sure that there are only spaces (or tabs) between the beginning
 
115
        //of the line and the function declaration
 
116
        position = currentPos - numberOfCharacters - 1;                 //-1 to move to char before 'function'
 
117
        for (unsigned int j = 0; j < 16; j++) {                                 //check up to 16 preceeding characters
 
118
                char c = styler.SafeGetCharAt(position--, '\0');        //if can't read char, return NUL (past beginning of document)
 
119
                if (c <= 0)     //reached beginning of document
 
120
                        return true;
 
121
                if (c > 0 && IsLineEndChar(c))
 
122
                        return true;
 
123
                else if (c > 0 && !IsASpaceOrTab(c))
 
124
                        return false;
 
125
        }
 
126
 
 
127
        //fall-through
 
128
        return false;
 
129
}
 
130
 
 
131
static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
 
132
                            Accessor &styler, bool caseSensitive) {
 
133
 
 
134
        WordList &keywords  = *keywordlists[0];
 
135
        WordList &keywords2 = *keywordlists[1];
 
136
        WordList &keywords3 = *keywordlists[2];
 
137
        WordList &keywords4 = *keywordlists[3];
 
138
 
 
139
        //define the character sets
 
140
        CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true);
 
141
        CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);
 
142
 
 
143
        StyleContext sc(startPos, length, initStyle, styler);
 
144
        char s_save[100]; //for last line highlighting
 
145
 
 
146
        //are there only spaces between the first letter of the line and the beginning of the line
 
147
        bool onlySpaces = true;
 
148
 
 
149
        for (; sc.More(); sc.Forward()) {
 
150
 
 
151
                // save the total current word for eof processing
 
152
                char s[100];
 
153
                sc.GetCurrentLowered(s, sizeof(s));
 
154
 
 
155
                if ((sc.ch > 0) && setWord.Contains(sc.ch))
 
156
                {
 
157
                        strcpy(s_save,s);
 
158
                        int tp = static_cast<int>(strlen(s_save));
 
159
                        if (tp < 99) {
 
160
                                s_save[tp] = static_cast<char>(tolower(sc.ch));
 
161
                                s_save[tp+1] = '\0';
 
162
                        }
 
163
                }
 
164
 
 
165
                if (sc.atLineStart) {
 
166
                        if (sc.state == SCE_POWERPRO_DOUBLEQUOTEDSTRING) {
 
167
                                // Prevent SCE_POWERPRO_STRINGEOL from leaking back to previous line which
 
168
                                // ends with a line continuation by locking in the state upto this position.
 
169
                                sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING);
 
170
                        }
 
171
                }
 
172
 
 
173
                // Determine if the current state should terminate.
 
174
                switch (sc.state) {
 
175
                        case SCE_POWERPRO_OPERATOR:
 
176
                                sc.SetState(SCE_POWERPRO_DEFAULT);
 
177
                                break;
 
178
 
 
179
                        case SCE_POWERPRO_NUMBER:
 
180
 
 
181
                                if (!IsADigit(sc.ch))
 
182
                                        sc.SetState(SCE_POWERPRO_DEFAULT);
 
183
 
 
184
                                break;
 
185
 
 
186
                        case SCE_POWERPRO_IDENTIFIER:
 
187
                                //if ((sc.ch > 0) && !setWord.Contains(sc.ch) || (sc.ch == '.')) { // use this line if don't want to match keywords with . in them. ie: win.debug will match both win and debug so win debug will also be colorized
 
188
                                if ((sc.ch > 0) && !setWord.Contains(sc.ch)){  // || (sc.ch == '.')) { // use this line if you want to match keywords with a . ie: win.debug will only match win.debug neither win nor debug will be colorized separately
 
189
                                        char s[1000];
 
190
                                        if (caseSensitive) {
 
191
                                                sc.GetCurrent(s, sizeof(s));
 
192
                                        } else {
 
193
                                                sc.GetCurrentLowered(s, sizeof(s));
 
194
                                        }
 
195
 
 
196
                                        if (keywords.InList(s)) {
 
197
                                                sc.ChangeState(SCE_POWERPRO_WORD);
 
198
                                        } else if (keywords2.InList(s)) {
 
199
                                                sc.ChangeState(SCE_POWERPRO_WORD2);
 
200
                                        } else if (keywords3.InList(s)) {
 
201
                                                sc.ChangeState(SCE_POWERPRO_WORD3);
 
202
                                        } else if (keywords4.InList(s)) {
 
203
                                                sc.ChangeState(SCE_POWERPRO_WORD4);
 
204
                                        }
 
205
                                        sc.SetState(SCE_POWERPRO_DEFAULT);
 
206
                                }
 
207
                                break;
 
208
 
 
209
                        case SCE_POWERPRO_LINECONTINUE:
 
210
                                if (sc.atLineStart) {
 
211
                                        sc.SetState(SCE_POWERPRO_DEFAULT);
 
212
                                } else if (sc.Match('/', '*') || sc.Match('/', '/')) {
 
213
                                        sc.SetState(SCE_POWERPRO_DEFAULT);
 
214
                                }
 
215
                                break;
 
216
 
 
217
                        case SCE_POWERPRO_COMMENTBLOCK:
 
218
                                if (sc.Match('*', '/')) {
 
219
                                        sc.Forward();
 
220
                                        sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
 
221
                                }
 
222
                                break;
 
223
 
 
224
                        case SCE_POWERPRO_COMMENTLINE:
 
225
                                if (sc.atLineStart) {
 
226
                                        sc.SetState(SCE_POWERPRO_DEFAULT);
 
227
                                }
 
228
                                break;
 
229
 
 
230
                        case SCE_POWERPRO_DOUBLEQUOTEDSTRING:
 
231
                                if (sc.atLineEnd) {
 
232
                                        sc.ChangeState(SCE_POWERPRO_STRINGEOL);
 
233
                                } else if (sc.ch == '\\') {
 
234
                                        if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
 
235
                                                sc.Forward();
 
236
                                        }
 
237
                                } else if (sc.ch == '\"') {
 
238
                                        sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
 
239
                                }
 
240
                                break;
 
241
 
 
242
                        case SCE_POWERPRO_SINGLEQUOTEDSTRING:
 
243
                                if (sc.atLineEnd) {
 
244
                                        sc.ChangeState(SCE_POWERPRO_STRINGEOL);
 
245
                                } else if (sc.ch == '\\') {
 
246
                                        if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
 
247
                                                sc.Forward();
 
248
                                        }
 
249
                                } else if (sc.ch == '\'') {
 
250
                                        sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
 
251
                                }
 
252
                                break;
 
253
 
 
254
                        case SCE_POWERPRO_STRINGEOL:
 
255
                                if (sc.atLineStart) {
 
256
                                        sc.SetState(SCE_POWERPRO_DEFAULT);
 
257
                                }
 
258
                                break;
 
259
 
 
260
                        case SCE_POWERPRO_VERBATIM:
 
261
                                if (sc.ch == '\"') {
 
262
                                        if (sc.chNext == '\"') {
 
263
                                                sc.Forward();
 
264
                                        } else {
 
265
                                                sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
 
266
                                        }
 
267
                                }
 
268
                                break;
 
269
 
 
270
                        case SCE_POWERPRO_ALTQUOTE:
 
271
                                if (sc.ch == '#') {
 
272
                                        if (sc.chNext == '#') {
 
273
                                                sc.Forward();
 
274
                                        } else {
 
275
                                                sc.ForwardSetState(SCE_POWERPRO_DEFAULT);
 
276
                                        }
 
277
                                }
 
278
                                break;
 
279
 
 
280
                        case SCE_POWERPRO_FUNCTION:
 
281
                                if (isspacechar(sc.ch) || sc.ch == '(') {
 
282
                                        sc.SetState(SCE_POWERPRO_DEFAULT);
 
283
                                }
 
284
                        break;
 
285
                }
 
286
 
 
287
                // Determine if a new state should be entered.
 
288
                if (sc.state == SCE_POWERPRO_DEFAULT) {
 
289
                        if (sc.Match('?', '\"')) {
 
290
                                sc.SetState(SCE_POWERPRO_VERBATIM);
 
291
                                sc.Forward();
 
292
                        } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
 
293
                                sc.SetState(SCE_POWERPRO_NUMBER);
 
294
                        }else if (sc.Match('?','#')) {
 
295
                                if (sc.ch == '?' && sc.chNext == '#') {
 
296
                                        sc.SetState(SCE_POWERPRO_ALTQUOTE);
 
297
                                        sc.Forward();
 
298
                                }
 
299
                        } else if (IsFunction(styler, sc.currentPos)) { //highlight <name> in 'function <name>'
 
300
                                sc.SetState(SCE_POWERPRO_FUNCTION);
 
301
                        } else if (onlySpaces && sc.ch == '@') {                //alternate function definition [label]
 
302
                                sc.SetState(SCE_POWERPRO_FUNCTION);
 
303
                        } else if ((sc.ch > 0) && (setWordStart.Contains(sc.ch) || (sc.ch == '?'))) {
 
304
                                sc.SetState(SCE_POWERPRO_IDENTIFIER);
 
305
                        } else if (sc.Match(";;+")) {
 
306
                                sc.SetState(SCE_POWERPRO_LINECONTINUE);
 
307
                        } else if (sc.Match('/', '*')) {
 
308
                                sc.SetState(SCE_POWERPRO_COMMENTBLOCK);
 
309
                                sc.Forward();   // Eat the * so it isn't used for the end of the comment
 
310
                        } else if (sc.Match('/', '/')) {
 
311
                                sc.SetState(SCE_POWERPRO_COMMENTLINE);
 
312
                        } else if (onlySpaces && sc.ch == ';') {                //legacy comment that can only have blank space in front of it
 
313
                                sc.SetState(SCE_POWERPRO_COMMENTLINE);
 
314
                        } else if (sc.Match(";;")) {
 
315
                                sc.SetState(SCE_POWERPRO_COMMENTLINE);
 
316
                        } else if (sc.ch == '\"') {
 
317
                                sc.SetState(SCE_POWERPRO_DOUBLEQUOTEDSTRING);
 
318
                        } else if (sc.ch == '\'') {
 
319
                                sc.SetState(SCE_POWERPRO_SINGLEQUOTEDSTRING);
 
320
                        } else if (isoperator(static_cast<char>(sc.ch))) {
 
321
                                sc.SetState(SCE_POWERPRO_OPERATOR);
 
322
                        }
 
323
                }
 
324
 
 
325
                //maintain a record of whether or not all the preceding characters on
 
326
                //a line are space characters
 
327
                if (onlySpaces && !IsASpaceOrTab(sc.ch))
 
328
                        onlySpaces = false;
 
329
 
 
330
                //reset when starting a new line
 
331
                if (sc.atLineEnd)
 
332
                        onlySpaces = true;
 
333
        }
 
334
 
 
335
        //*************************************
 
336
        // Colourize the last word correctly
 
337
        //*************************************
 
338
        if (sc.state == SCE_POWERPRO_IDENTIFIER)
 
339
        {
 
340
                if (keywords.InList(s_save)) {
 
341
                        sc.ChangeState(SCE_POWERPRO_WORD);
 
342
                        sc.SetState(SCE_POWERPRO_DEFAULT);
 
343
                }
 
344
                else if (keywords2.InList(s_save)) {
 
345
                        sc.ChangeState(SCE_POWERPRO_WORD2);
 
346
                        sc.SetState(SCE_POWERPRO_DEFAULT);
 
347
                }
 
348
                else if (keywords3.InList(s_save)) {
 
349
                        sc.ChangeState(SCE_POWERPRO_WORD3);
 
350
                        sc.SetState(SCE_POWERPRO_DEFAULT);
 
351
                }
 
352
                else if (keywords4.InList(s_save)) {
 
353
                        sc.ChangeState(SCE_POWERPRO_WORD4);
 
354
                        sc.SetState(SCE_POWERPRO_DEFAULT);
 
355
                }
 
356
                else {
 
357
                        sc.SetState(SCE_POWERPRO_DEFAULT);
 
358
                }
 
359
        }
 
360
        sc.Complete();
 
361
}
 
362
 
 
363
static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
 
364
{
 
365
        //define the character sets
 
366
        CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true);
 
367
        CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true);
 
368
 
 
369
        //used to tell if we're recursively folding the whole document, or just a small piece (ie: if statement or 1 function)
 
370
        bool isFoldingAll = true;
 
371
 
 
372
        int endPos = startPos + length;
 
373
        int lastLine = styler.GetLine(styler.Length()); //used to help fold the last line correctly
 
374
 
 
375
        // get settings from the config files for folding comments and preprocessor lines
 
376
        bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
 
377
        bool foldInComment = styler.GetPropertyInt("fold.comment") == 2;
 
378
        bool foldCompact = true;
 
379
 
 
380
        // Backtrack to previous line in case need to fix its fold status
 
381
        int lineCurrent = styler.GetLine(startPos);
 
382
        if (startPos > 0) {
 
383
                isFoldingAll = false;
 
384
                if (lineCurrent > 0) {
 
385
                        lineCurrent--;
 
386
                        startPos = styler.LineStart(lineCurrent);
 
387
                }
 
388
        }
 
389
        // vars for style of previous/current/next lines
 
390
        int style = GetStyleFirstWord(lineCurrent,styler);
 
391
        int stylePrev = 0;
 
392
 
 
393
        // find the first previous line without continuation character at the end
 
394
        while ((lineCurrent > 0 && IsContinuationLine(lineCurrent, styler))
 
395
               || (lineCurrent > 1 && IsContinuationLine(lineCurrent - 1, styler))) {
 
396
                lineCurrent--;
 
397
                startPos = styler.LineStart(lineCurrent);
 
398
        }
 
399
 
 
400
        if (lineCurrent > 0) {
 
401
                stylePrev = GetStyleFirstWord(lineCurrent-1,styler);
 
402
        }
 
403
 
 
404
        // vars for getting first word to check for keywords
 
405
        bool isFirstWordStarted = false;
 
406
        bool isFirstWordEnded = false;
 
407
 
 
408
        const unsigned int FIRST_WORD_MAX_LEN = 10;
 
409
        char szFirstWord[FIRST_WORD_MAX_LEN] = "";
 
410
        unsigned int firstWordLen = 0;
 
411
 
 
412
        char szDo[3]="";
 
413
        int      szDolen = 0;
 
414
        bool isDoLastWord = false;
 
415
 
 
416
        // var for indentlevel
 
417
        int levelCurrent = SC_FOLDLEVELBASE;
 
418
        if (lineCurrent > 0)
 
419
                levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
 
420
        int levelNext = levelCurrent;
 
421
 
 
422
        int     visibleChars = 0;
 
423
        int functionCount = 0;
 
424
 
 
425
        char chNext = styler.SafeGetCharAt(startPos);
 
426
        char chPrev = '\0';
 
427
        char chPrevPrev = '\0';
 
428
        char chPrevPrevPrev = '\0';
 
429
 
 
430
        for (int i = startPos; i < endPos; i++) {
 
431
 
 
432
                char ch = chNext;
 
433
                chNext = styler.SafeGetCharAt(i + 1);
 
434
 
 
435
                if ((ch > 0) && setWord.Contains(ch))
 
436
                        visibleChars++;
 
437
 
 
438
                // get the syle for the current character neede to check in comment
 
439
                int stylech = styler.StyleAt(i);
 
440
 
 
441
                // start the capture of the first word
 
442
                if (!isFirstWordStarted && (ch > 0)) {
 
443
                        if (setWord.Contains(ch) || setWordStart.Contains(ch) || ch == ';' || ch == '/') {
 
444
                                isFirstWordStarted = true;
 
445
                                if (firstWordLen < FIRST_WORD_MAX_LEN - 1) {
 
446
                                        szFirstWord[firstWordLen++] = static_cast<char>(tolower(ch));
 
447
                                        szFirstWord[firstWordLen] = '\0';
 
448
                                }
 
449
                        }
 
450
                } // continue capture of the first word on the line
 
451
                else if (isFirstWordStarted && !isFirstWordEnded && (ch > 0)) {
 
452
                        if (!setWord.Contains(ch)) {
 
453
                                isFirstWordEnded = true;
 
454
                        }
 
455
                        else if (firstWordLen < (FIRST_WORD_MAX_LEN - 1)) {
 
456
                                szFirstWord[firstWordLen++] = static_cast<char>(tolower(ch));
 
457
                                szFirstWord[firstWordLen] = '\0';
 
458
                        }
 
459
                }
 
460
 
 
461
                if (stylech != SCE_POWERPRO_COMMENTLINE) {
 
462
 
 
463
                        //reset isDoLastWord if we find a character(ignoring spaces) after 'do'
 
464
                        if (isDoLastWord && (ch > 0) && setWord.Contains(ch))
 
465
                                isDoLastWord = false;
 
466
 
 
467
                        // --find out if the word "do" is the last on a "if" line--
 
468
                        // collect each letter and put it into a buffer 2 chars long
 
469
                        // if we end up with "do" in the buffer when we reach the end of
 
470
                        // the line, "do" was the last word on the line
 
471
                        if ((ch > 0) && isFirstWordEnded && strcmp(szFirstWord, "if") == 0) {
 
472
                                if (szDolen == 2) {
 
473
                                        szDo[0] = szDo[1];
 
474
                                        szDo[1] = static_cast<char>(tolower(ch));
 
475
                                        szDo[2] = '\0';
 
476
 
 
477
                                        if (strcmp(szDo, "do") == 0)
 
478
                                                isDoLastWord = true;
 
479
 
 
480
                                } else if (szDolen < 2) {
 
481
                                        szDo[szDolen++] = static_cast<char>(tolower(ch));
 
482
                                        szDo[szDolen] = '\0';
 
483
                                }
 
484
                        }
 
485
                }
 
486
 
 
487
                // End of Line found so process the information
 
488
                 if ((ch == '\r' && chNext != '\n') // \r\n
 
489
                        || ch == '\n'                                   // \n
 
490
                        || i == endPos) {                               // end of selection
 
491
 
 
492
                        // **************************
 
493
                        // Folding logic for Keywords
 
494
                        // **************************
 
495
 
 
496
                        // if a keyword is found on the current line and the line doesn't end with ;;+ (continuation)
 
497
                        //    and we are not inside a commentblock.
 
498
                        if (firstWordLen > 0
 
499
                                && chPrev != '+' && chPrevPrev != ';' && chPrevPrevPrev !=';'
 
500
                                && (!IsStreamCommentStyle(style) || foldInComment) ) {
 
501
 
 
502
                                // only fold "if" last keyword is "then"  (else its a one line if)
 
503
                                if (strcmp(szFirstWord, "if") == 0  && isDoLastWord)
 
504
                                                levelNext++;
 
505
 
 
506
                                // create new fold for these words
 
507
                                if (strcmp(szFirstWord, "for") == 0)
 
508
                                        levelNext++;
 
509
 
 
510
                                //handle folding for functions/labels
 
511
                                //Note: Functions and labels don't have an explicit end like [end function]
 
512
                                //      1. functions/labels end at the start of another function
 
513
                                //      2. functions/labels end at the end of the file
 
514
                                if ((strcmp(szFirstWord, "function") == 0) || (firstWordLen > 0 && szFirstWord[0] == '@')) {
 
515
                                        if (isFoldingAll) { //if we're folding the whole document (recursivly by lua script)
 
516
 
 
517
                                                if (functionCount > 0) {
 
518
                                                        levelCurrent--;
 
519
                                                } else {
 
520
                                                        levelNext++;
 
521
                                                }
 
522
                                                functionCount++;
 
523
 
 
524
                                        } else { //if just folding a small piece (by clicking on the minus sign next to the word)
 
525
                                                levelCurrent--;
 
526
                                        }
 
527
                                }
 
528
 
 
529
                                // end the fold for these words before the current line
 
530
                                if (strcmp(szFirstWord, "endif") == 0 || strcmp(szFirstWord, "endfor") == 0) {
 
531
                                                levelNext--;
 
532
                                                levelCurrent--;
 
533
                                }
 
534
 
 
535
                                // end the fold for these words before the current line and Start new fold
 
536
                                if (strcmp(szFirstWord, "else") == 0 || strcmp(szFirstWord, "elseif") == 0 )
 
537
                                                levelCurrent--;
 
538
 
 
539
                        }
 
540
                        // Preprocessor and Comment folding
 
541
                        int styleNext = GetStyleFirstWord(lineCurrent + 1,styler);
 
542
 
 
543
                        // *********************************
 
544
                        // Folding logic for Comment blocks
 
545
                        // *********************************
 
546
                        if (foldComment && IsStreamCommentStyle(style)) {
 
547
 
 
548
                                // Start of a comment block
 
549
                                if (stylePrev != style && IsStreamCommentStyle(styleNext) && styleNext == style) {
 
550
                                    levelNext++;
 
551
                                } // fold till the last line for normal comment lines
 
552
                                else if (IsStreamCommentStyle(stylePrev)
 
553
                                                && styleNext != SCE_POWERPRO_COMMENTLINE
 
554
                                                && stylePrev == SCE_POWERPRO_COMMENTLINE
 
555
                                                && style == SCE_POWERPRO_COMMENTLINE) {
 
556
                                        levelNext--;
 
557
                                } // fold till the one but last line for Blockcomment lines
 
558
                                else if (IsStreamCommentStyle(stylePrev)
 
559
                                                && styleNext != SCE_POWERPRO_COMMENTBLOCK
 
560
                                                && style == SCE_POWERPRO_COMMENTBLOCK) {
 
561
                                        levelNext--;
 
562
                                        levelCurrent--;
 
563
                                }
 
564
                        }
 
565
 
 
566
                        int levelUse = levelCurrent;
 
567
                        int lev = levelUse | levelNext << 16;
 
568
                        if (visibleChars == 0 && foldCompact)
 
569
                                lev |= SC_FOLDLEVELWHITEFLAG;
 
570
                        if (levelUse < levelNext)
 
571
                                lev |= SC_FOLDLEVELHEADERFLAG;
 
572
                        if (lev != styler.LevelAt(lineCurrent))
 
573
                                styler.SetLevel(lineCurrent, lev);
 
574
 
 
575
                        // reset values for the next line
 
576
                        lineCurrent++;
 
577
                        stylePrev = style;
 
578
                        style = styleNext;
 
579
                        levelCurrent = levelNext;
 
580
                        visibleChars = 0;
 
581
 
 
582
                        // if the last characters are ;;+ then don't reset since the line continues on the next line.
 
583
                        if (chPrev != '+' && chPrevPrev != ';' && chPrevPrevPrev != ';') {
 
584
                                firstWordLen = 0;
 
585
                                szDolen = 0;
 
586
                                isFirstWordStarted = false;
 
587
                                isFirstWordEnded = false;
 
588
                                isDoLastWord = false;
 
589
 
 
590
                                //blank out first word
 
591
                                for (unsigned int i = 0; i < FIRST_WORD_MAX_LEN; i++)
 
592
                                        szFirstWord[i] = '\0';
 
593
                        }
 
594
                }
 
595
 
 
596
                // save the last processed characters
 
597
                if ((ch > 0) && !isspacechar(ch)) {
 
598
                        chPrevPrevPrev = chPrevPrev;
 
599
                        chPrevPrev = chPrev;
 
600
                        chPrev = ch;
 
601
                }
 
602
        }
 
603
 
 
604
        //close folds on the last line - without this a 'phantom'
 
605
        //fold can appear when an open fold is on the last line
 
606
        //this can occur because functions and labels don't have an explicit end
 
607
        if (lineCurrent >= lastLine) {
 
608
                int lev = 0;
 
609
                lev |= SC_FOLDLEVELWHITEFLAG;
 
610
                styler.SetLevel(lineCurrent, lev);
 
611
        }
 
612
 
 
613
}
 
614
 
 
615
static const char * const powerProWordLists[] = {
 
616
            "Keyword list 1",
 
617
            "Keyword list 2",
 
618
            "Keyword list 3",
 
619
            "Keyword list 4",
 
620
            0,
 
621
        };
 
622
 
 
623
static void ColourisePowerProDocWrapper(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
 
624
                                       Accessor &styler) {
 
625
        ColourisePowerProDoc(startPos, length, initStyle, keywordlists, styler, false);
 
626
}
 
627
 
 
628
LexerModule lmPowerPro(SCLEX_POWERPRO, ColourisePowerProDocWrapper, "powerpro", FoldPowerProDoc, powerProWordLists);
 
629
 
 
630