2009-06-24 19:09:31 +00:00
// Scintilla source code edit control
// @file LexPowerPro.cxx
// PowerPro utility, written by Bruce Switzer, is available from http://powerpro.webeddie.com
// PowerPro lexer is written by Christopher Bean (cbean@cb-software.net)
//
2010-08-21 23:59:56 +00:00
// Lexer code heavily borrowed from:
2009-06-24 19:09:31 +00:00
// LexAU3.cxx by Jos van der Zande
// LexCPP.cxx by Neil Hodgson
// LexVB.cxx by Neil Hodgson
//
// Changes:
// 2008-10-25 - Initial release
2010-08-21 23:59:56 +00:00
// 2008-10-26 - Changed how <name> is hilighted in 'function <name>' so that
2009-06-24 19:09:31 +00:00
// local isFunction = "" and local functions = "" don't get falsely highlighted
// 2008-12-14 - Added bounds checking for szKeyword and szDo
// - Replaced SetOfCharacters with CharacterSet
// - Made sure that CharacterSet::Contains is passed only positive values
2010-08-21 23:59:56 +00:00
// - Made sure that the return value of Accessor::SafeGetCharAt is positive before
2009-06-24 19:09:31 +00:00
// passsing to functions that require positive values like isspacechar()
// - Removed unused visibleChars processing from ColourisePowerProDoc()
2010-08-21 23:59:56 +00:00
// - Fixed bug with folding logic where line continuations didn't end where
2009-06-24 19:09:31 +00:00
// they were supposed to
// - Moved all helper functions to the top of the file
//
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
# include <stdlib.h>
# include <string.h>
2010-08-21 23:59:56 +00:00
# include <stdio.h>
# include <stdarg.h>
# include <assert.h>
# include <ctype.h>
2009-06-24 19:09:31 +00:00
2010-08-21 23:59:56 +00:00
# include "ILexer.h"
2009-06-24 19:09:31 +00:00
# include "Scintilla.h"
# include "SciLexer.h"
2010-08-21 23:59:56 +00:00
# include "PropSetSimple.h"
# include "WordList.h"
# include "LexAccessor.h"
# include "Accessor.h"
# include "StyleContext.h"
2009-06-24 19:09:31 +00:00
# include "CharacterSet.h"
2010-08-21 23:59:56 +00:00
# include "LexerModule.h"
2009-06-24 19:09:31 +00:00
# ifdef SCI_NAMESPACE
using namespace Scintilla ;
# endif
static inline bool IsStreamCommentStyle ( int style ) {
return style = = SCE_POWERPRO_COMMENTBLOCK ;
}
static bool IsContinuationLine ( unsigned int szLine , Accessor & styler )
{
int nsPos = styler . LineStart ( szLine ) ;
int nePos = styler . LineStart ( szLine + 1 ) - 2 ;
while ( nsPos < nePos )
{
int stylech = styler . StyleAt ( nsPos ) ;
if ( ! ( stylech = = SCE_POWERPRO_COMMENTBLOCK ) ) {
char ch = styler . SafeGetCharAt ( nePos ) ;
char chPrev = styler . SafeGetCharAt ( nePos - 1 ) ;
char chPrevPrev = styler . SafeGetCharAt ( nePos - 2 ) ;
if ( ch > 0 & & chPrev > 0 & & chPrevPrev > 0 & & ! isspacechar ( ch ) & & ! isspacechar ( chPrev ) & & ! isspacechar ( chPrevPrev ) ) {
if ( chPrevPrev = = ' ; ' & & chPrev = = ' ; ' & & ch = = ' + ' )
return true ;
else
return false ;
}
}
nePos - - ; // skip to next char
}
return false ;
}
// Routine to find first none space on the current line and return its Style
2010-08-21 23:59:56 +00:00
// needed for comment lines not starting on pos 1
2009-06-24 19:09:31 +00:00
static int GetStyleFirstWord ( unsigned int szLine , Accessor & styler )
{
int nsPos = styler . LineStart ( szLine ) ;
int nePos = styler . LineStart ( szLine + 1 ) - 1 ;
char ch = styler . SafeGetCharAt ( nsPos ) ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
while ( ch > 0 & & isspacechar ( ch ) & & nsPos < nePos )
{
nsPos + + ; // skip to next char
ch = styler . SafeGetCharAt ( nsPos ) ;
}
return styler . StyleAt ( nsPos ) ;
}
//returns true if there is a function to highlight
//used to highlight <name> in 'function <name>'
static bool HasFunction ( Accessor & styler , unsigned int currentPos ) {
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
//check for presence of 'function '
2010-08-21 23:59:56 +00:00
return ( styler . SafeGetCharAt ( currentPos ) = = ' '
& & tolower ( styler . SafeGetCharAt ( currentPos - 1 ) ) = = ' n '
2009-06-24 19:09:31 +00:00
& & tolower ( styler . SafeGetCharAt ( currentPos - 2 ) ) = = ' o '
& & tolower ( styler . SafeGetCharAt ( currentPos - 3 ) ) = = ' i '
& & tolower ( styler . SafeGetCharAt ( currentPos - 4 ) ) = = ' t '
& & tolower ( styler . SafeGetCharAt ( currentPos - 5 ) ) = = ' c '
& & tolower ( styler . SafeGetCharAt ( currentPos - 6 ) ) = = ' n '
& & tolower ( styler . SafeGetCharAt ( currentPos - 7 ) ) = = ' u '
& & tolower ( styler . SafeGetCharAt ( currentPos - 8 ) ) = = ' f '
//only allow 'function ' to appear at the beginning of a line
2010-08-21 23:59:56 +00:00
& & ( styler . SafeGetCharAt ( currentPos - 9 ) = = ' \n '
2009-06-24 19:09:31 +00:00
| | styler . SafeGetCharAt ( currentPos - 9 ) = = ' \r '
| | ( styler . SafeGetCharAt ( currentPos - 9 , ' \0 ' ) ) = = ' \0 ' ) //is the first line
) ;
}
static void ColourisePowerProDoc ( unsigned int startPos , int length , int initStyle , WordList * keywordlists [ ] ,
Accessor & styler , bool caseSensitive ) {
WordList & keywords = * keywordlists [ 0 ] ;
WordList & keywords2 = * keywordlists [ 1 ] ;
WordList & keywords3 = * keywordlists [ 2 ] ;
WordList & keywords4 = * keywordlists [ 3 ] ;
2010-08-21 23:59:56 +00:00
//define the character sets
2009-06-24 19:09:31 +00:00
CharacterSet setWordStart ( CharacterSet : : setAlpha , " _@ " , 0x80 , true ) ;
CharacterSet setWord ( CharacterSet : : setAlphaNum , " ._ " , 0x80 , true ) ;
StyleContext sc ( startPos , length , initStyle , styler ) ;
char s_save [ 100 ] ; //for last line highlighting
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
for ( ; sc . More ( ) ; sc . Forward ( ) ) {
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
// **********************************************
// save the total current word for eof processing
char s [ 100 ] ;
sc . GetCurrentLowered ( s , sizeof ( s ) ) ;
2010-08-21 23:59:56 +00:00
if ( ( sc . ch > 0 ) & & setWord . Contains ( sc . ch ) )
2009-06-24 19:09:31 +00:00
{
strcpy ( s_save , s ) ;
int tp = strlen ( s_save ) ;
if ( tp < 99 ) {
s_save [ tp ] = static_cast < char > ( tolower ( sc . ch ) ) ;
s_save [ tp + 1 ] = ' \0 ' ;
}
}
// **********************************************
//
if ( sc . atLineStart ) {
if ( sc . state = = SCE_POWERPRO_DOUBLEQUOTEDSTRING ) {
// Prevent SCE_POWERPRO_STRINGEOL from leaking back to previous line which
// ends with a line continuation by locking in the state upto this position.
sc . SetState ( SCE_POWERPRO_DOUBLEQUOTEDSTRING ) ;
}
}
// Determine if the current state should terminate.
switch ( sc . state ) {
case SCE_POWERPRO_OPERATOR :
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
break ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
case SCE_POWERPRO_NUMBER :
if ( ! IsADigit ( sc . ch ) )
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
break ;
case SCE_POWERPRO_IDENTIFIER :
//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
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
char s [ 1000 ] ;
if ( caseSensitive ) {
sc . GetCurrent ( s , sizeof ( s ) ) ;
} else {
sc . GetCurrentLowered ( s , sizeof ( s ) ) ;
}
if ( keywords . InList ( s ) ) {
sc . ChangeState ( SCE_POWERPRO_WORD ) ;
} else if ( keywords2 . InList ( s ) ) {
sc . ChangeState ( SCE_POWERPRO_WORD2 ) ;
} else if ( keywords3 . InList ( s ) ) {
sc . ChangeState ( SCE_POWERPRO_WORD3 ) ;
} else if ( keywords4 . InList ( s ) ) {
sc . ChangeState ( SCE_POWERPRO_WORD4 ) ;
}
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
}
break ;
case SCE_POWERPRO_LINECONTINUE :
if ( sc . atLineStart ) {
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
} else if ( sc . Match ( ' / ' , ' * ' ) | | sc . Match ( ' / ' , ' / ' ) ) {
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
}
break ;
case SCE_POWERPRO_COMMENTBLOCK :
if ( sc . Match ( ' * ' , ' / ' ) ) {
sc . Forward ( ) ;
sc . ForwardSetState ( SCE_POWERPRO_DEFAULT ) ;
}
break ;
case SCE_POWERPRO_COMMENTLINE :
if ( sc . atLineStart ) {
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
}
break ;
case SCE_POWERPRO_DOUBLEQUOTEDSTRING :
if ( sc . atLineEnd ) {
sc . ChangeState ( SCE_POWERPRO_STRINGEOL ) ;
} else if ( sc . ch = = ' \\ ' ) {
if ( sc . chNext = = ' \" ' | | sc . chNext = = ' \' ' | | sc . chNext = = ' \\ ' ) {
sc . Forward ( ) ;
}
} else if ( sc . ch = = ' \" ' ) {
sc . ForwardSetState ( SCE_POWERPRO_DEFAULT ) ;
}
break ;
case SCE_POWERPRO_SINGLEQUOTEDSTRING :
if ( sc . atLineEnd ) {
sc . ChangeState ( SCE_POWERPRO_STRINGEOL ) ;
} else if ( sc . ch = = ' \\ ' ) {
if ( sc . chNext = = ' \" ' | | sc . chNext = = ' \' ' | | sc . chNext = = ' \\ ' ) {
sc . Forward ( ) ;
}
} else if ( sc . ch = = ' \' ' ) {
sc . ForwardSetState ( SCE_POWERPRO_DEFAULT ) ;
}
break ;
case SCE_POWERPRO_STRINGEOL :
if ( sc . atLineStart ) {
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
}
break ;
case SCE_POWERPRO_VERBATIM :
if ( sc . ch = = ' \" ' ) {
if ( sc . chNext = = ' \" ' ) {
sc . Forward ( ) ;
} else {
sc . ForwardSetState ( SCE_POWERPRO_DEFAULT ) ;
}
}
break ;
case SCE_POWERPRO_ALTQUOTE :
if ( sc . ch = = ' # ' ) {
if ( sc . chNext = = ' # ' ) {
sc . Forward ( ) ;
} else {
sc . ForwardSetState ( SCE_POWERPRO_DEFAULT ) ;
}
}
break ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
case SCE_POWERPRO_FUNCTION :
if ( sc . ch = = ' \r ' | | sc . ch = = ' \n ' | | sc . ch = = ' ' | | sc . ch = = ' ( ' ) {
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
}
break ;
}
// Determine if a new state should be entered.
if ( sc . state = = SCE_POWERPRO_DEFAULT ) {
if ( sc . Match ( ' ? ' , ' \" ' ) ) {
sc . SetState ( SCE_POWERPRO_VERBATIM ) ;
sc . Forward ( ) ;
} else if ( IsADigit ( sc . ch ) | | ( sc . ch = = ' . ' & & IsADigit ( sc . chNext ) ) ) {
sc . SetState ( SCE_POWERPRO_NUMBER ) ;
} else if ( sc . Match ( ' ? ' , ' # ' ) ) {
if ( sc . ch = = ' ? ' & & sc . chNext = = ' # ' ) {
sc . SetState ( SCE_POWERPRO_ALTQUOTE ) ;
sc . Forward ( ) ;
}
} else if ( HasFunction ( styler , sc . currentPos ) ) { //highlight <name> in 'function <name>'
2010-08-21 23:59:56 +00:00
sc . SetState ( SCE_POWERPRO_FUNCTION ) ;
2009-06-24 19:09:31 +00:00
} else if ( sc . ch = = ' @ ' & & sc . atLineStart ) { //alternate function definition [label]
sc . SetState ( SCE_POWERPRO_FUNCTION ) ;
} else if ( ( sc . ch > 0 ) & & ( setWordStart . Contains ( sc . ch ) | | ( sc . ch = = ' ? ' ) ) ) {
sc . SetState ( SCE_POWERPRO_IDENTIFIER ) ;
2010-08-21 23:59:56 +00:00
} else if ( sc . Match ( " ;;+ " ) ) {
2009-06-24 19:09:31 +00:00
sc . SetState ( SCE_POWERPRO_LINECONTINUE ) ;
} else if ( sc . Match ( ' / ' , ' * ' ) ) {
sc . SetState ( SCE_POWERPRO_COMMENTBLOCK ) ;
sc . Forward ( ) ; // Eat the * so it isn't used for the end of the comment
} else if ( sc . Match ( ' / ' , ' / ' ) ) {
sc . SetState ( SCE_POWERPRO_COMMENTLINE ) ;
} else if ( sc . atLineStart & & sc . ch = = ' ; ' ) { //legacy comment that can only appear at the beginning of a line
sc . SetState ( SCE_POWERPRO_COMMENTLINE ) ;
} else if ( sc . Match ( " ;; " ) ) {
sc . SetState ( SCE_POWERPRO_COMMENTLINE ) ;
} else if ( sc . ch = = ' \" ' ) {
sc . SetState ( SCE_POWERPRO_DOUBLEQUOTEDSTRING ) ;
} else if ( sc . ch = = ' \' ' ) {
sc . SetState ( SCE_POWERPRO_SINGLEQUOTEDSTRING ) ;
} else if ( isoperator ( static_cast < char > ( sc . ch ) ) ) {
sc . SetState ( SCE_POWERPRO_OPERATOR ) ;
}
}
}
//*************************************
2010-08-21 23:59:56 +00:00
// Colourize the last word correctly
2009-06-24 19:09:31 +00:00
//*************************************
if ( sc . state = = SCE_POWERPRO_IDENTIFIER )
{
if ( keywords . InList ( s_save ) ) {
sc . ChangeState ( SCE_POWERPRO_WORD ) ;
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
}
else if ( keywords2 . InList ( s_save ) ) {
sc . ChangeState ( SCE_POWERPRO_WORD2 ) ;
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
}
else if ( keywords3 . InList ( s_save ) ) {
sc . ChangeState ( SCE_POWERPRO_WORD3 ) ;
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
}
else if ( keywords4 . InList ( s_save ) ) {
sc . ChangeState ( SCE_POWERPRO_WORD4 ) ;
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
}
else {
sc . SetState ( SCE_POWERPRO_DEFAULT ) ;
}
}
sc . Complete ( ) ;
}
static void FoldPowerProDoc ( unsigned int startPos , int length , int , WordList * [ ] , Accessor & styler )
{
//define the character sets
CharacterSet setWordStart ( CharacterSet : : setAlpha , " _@ " , 0x80 , true ) ;
CharacterSet setWord ( CharacterSet : : setAlphaNum , " ._ " , 0x80 , true ) ;
bool isFoldingAll = true ; //used to tell if we're recursively folding the whole document, or just a small piece (ie: if statement or 1 function)
int endPos = startPos + length ;
int lastLine = styler . GetLine ( styler . Length ( ) ) ; //used to help fold the last line correctly
// get settings from the config files for folding comments and preprocessor lines
bool foldComment = styler . GetPropertyInt ( " fold.comment " ) ! = 0 ;
bool foldInComment = styler . GetPropertyInt ( " fold.comment " ) = = 2 ;
bool foldCompact = true ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
// Backtrack to previous line in case need to fix its fold status
int lineCurrent = styler . GetLine ( startPos ) ;
if ( startPos > 0 ) {
isFoldingAll = false ;
if ( lineCurrent > 0 ) {
lineCurrent - - ;
startPos = styler . LineStart ( lineCurrent ) ;
}
}
2010-08-21 23:59:56 +00:00
// vars for style of previous/current/next lines
2009-06-24 19:09:31 +00:00
int style = GetStyleFirstWord ( lineCurrent , styler ) ;
int stylePrev = 0 ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
// find the first previous line without continuation character at the end
while ( ( lineCurrent > 0 & & IsContinuationLine ( lineCurrent , styler ) ) | |
( lineCurrent > 1 & & IsContinuationLine ( lineCurrent - 1 , styler ) ) ) {
lineCurrent - - ;
startPos = styler . LineStart ( lineCurrent ) ;
}
if ( lineCurrent > 0 ) {
stylePrev = GetStyleFirstWord ( lineCurrent - 1 , styler ) ;
}
// vars for getting first word to check for keywords
bool FirstWordStart = false ;
bool FirstWordEnd = false ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
const unsigned int KEYWORD_MAX = 10 ;
char szKeyword [ KEYWORD_MAX ] = " " ;
unsigned int szKeywordlen = 0 ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
char szDo [ 3 ] = " " ;
int szDolen = 0 ;
bool DoFoundLast = false ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
// var for indentlevel
int levelCurrent = SC_FOLDLEVELBASE ;
if ( lineCurrent > 0 ) {
levelCurrent = styler . LevelAt ( lineCurrent - 1 ) > > 16 ;
}
int levelNext = levelCurrent ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
int visibleChars = 0 ;
int functionCount = 0 ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
char chNext = styler . SafeGetCharAt ( startPos ) ;
char chPrev = ' \0 ' ;
char chPrevPrev = ' \0 ' ;
char chPrevPrevPrev = ' \0 ' ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
for ( int i = startPos ; i < endPos ; i + + ) {
char ch = chNext ;
chNext = styler . SafeGetCharAt ( i + 1 ) ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
if ( ( ch > 0 ) & & setWord . Contains ( ch ) ) {
visibleChars + + ;
}
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
// get the syle for the current character neede to check in comment
int stylech = styler . StyleAt ( i ) ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
// get first word for the line for indent check max 9 characters
if ( FirstWordStart & & ( ! ( FirstWordEnd ) ) ) {
if ( ( ch > 0 ) & & ! setWord . Contains ( ch ) ) {
FirstWordEnd = true ;
}
else if ( szKeywordlen < KEYWORD_MAX - 1 ) {
szKeyword [ szKeywordlen + + ] = static_cast < char > ( tolower ( ch ) ) ;
szKeyword [ szKeywordlen ] = ' \0 ' ;
}
}
2010-08-21 23:59:56 +00:00
// start the capture of the first word
2009-06-24 19:09:31 +00:00
if ( ! ( FirstWordStart ) ) {
if ( ( ch > 0 ) & & ( setWord . Contains ( ch ) | | setWordStart . Contains ( ch ) | | ch = = ' ; ' | | ch = = ' / ' ) ) {
FirstWordStart = true ;
if ( szKeywordlen < KEYWORD_MAX - 1 ) {
szKeyword [ szKeywordlen + + ] = static_cast < char > ( tolower ( ch ) ) ;
szKeyword [ szKeywordlen ] = ' \0 ' ;
}
}
}
// only process this logic when not in comment section
if ( stylech ! = SCE_POWERPRO_COMMENTLINE ) {
if ( DoFoundLast ) {
if ( DoFoundLast & & ( ch > 0 ) & & setWord . Contains ( ch ) ) {
DoFoundLast = false ;
2010-08-21 23:59:56 +00:00
}
2009-06-24 19:09:31 +00:00
}
// find out if the word "do" is the last on a "if" line
if ( FirstWordEnd & & strcmp ( szKeyword , " if " ) = = 0 ) {
if ( szDolen = = 2 ) {
szDo [ 0 ] = szDo [ 1 ] ;
szDo [ 1 ] = static_cast < char > ( tolower ( ch ) ) ;
szDo [ 2 ] = ' \0 ' ;
if ( strcmp ( szDo , " do " ) = = 0 ) {
DoFoundLast = true ;
}
}
else if ( szDolen < 2 ) {
szDo [ szDolen + + ] = static_cast < char > ( tolower ( ch ) ) ;
szDo [ szDolen ] = ' \0 ' ;
}
}
}
2010-08-21 23:59:56 +00:00
// End of Line found so process the information
2009-06-24 19:09:31 +00:00
if ( ( ch = = ' \r ' & & chNext ! = ' \n ' ) | | ( ch = = ' \n ' ) | | ( i = = endPos ) ) {
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
// **************************
// Folding logic for Keywords
// **************************
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
// if a keyword is found on the current line and the line doesn't end with ;;+ (continuation)
// and we are not inside a commentblock.
2010-08-21 23:59:56 +00:00
if ( szKeywordlen > 0 & &
( ! ( chPrev = = ' + ' & & chPrevPrev = = ' ; ' & & chPrevPrevPrev = = ' ; ' ) ) & &
2009-06-24 19:09:31 +00:00
( ( ! ( IsStreamCommentStyle ( style ) ) | | foldInComment ) ) ) {
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
// only fold "if" last keyword is "then" (else its a one line if)
if ( strcmp ( szKeyword , " if " ) = = 0 & & DoFoundLast ) {
levelNext + + ;
}
2010-08-21 23:59:56 +00:00
// create new fold for these words
2009-06-24 19:09:31 +00:00
if ( strcmp ( szKeyword , " for " ) = = 0 ) {
levelNext + + ;
}
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
//handle folding for functions/labels
//Note: Functions and labels don't have an explicit end like [end function]
// 1. functions/labels end at the start of another function
// 2. functions/labels end at the end of the file
if ( ( strcmp ( szKeyword , " function " ) = = 0 ) | | ( szKeywordlen > 0 & & szKeyword [ 0 ] = = ' @ ' ) ) {
if ( isFoldingAll ) { //if we're folding the whole document (recursivly by lua script)
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
if ( functionCount > 0 ) {
levelCurrent - - ;
} else {
levelNext + + ;
}
2010-08-21 23:59:56 +00:00
functionCount + + ;
2009-06-24 19:09:31 +00:00
} else { //if just folding a small piece (by clicking on the minus sign next to the word)
levelCurrent - - ;
}
}
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
// end the fold for these words before the current line
if ( strcmp ( szKeyword , " endif " ) = = 0 | | strcmp ( szKeyword , " endfor " ) = = 0 ) {
levelNext - - ;
levelCurrent - - ;
}
2010-08-21 23:59:56 +00:00
// end the fold for these words before the current line and Start new fold
2009-06-24 19:09:31 +00:00
if ( strcmp ( szKeyword , " else " ) = = 0 | | strcmp ( szKeyword , " elseif " ) = = 0 ) {
levelCurrent - - ;
}
}
// Preprocessor and Comment folding
int styleNext = GetStyleFirstWord ( lineCurrent + 1 , styler ) ;
// *********************************
// Folding logic for Comment blocks
// *********************************
if ( foldComment & & IsStreamCommentStyle ( style ) ) {
// Start of a comment block
if ( ! ( stylePrev = = style ) & & IsStreamCommentStyle ( styleNext ) & & styleNext = = style ) {
levelNext + + ;
2010-08-21 23:59:56 +00:00
}
2009-06-24 19:09:31 +00:00
// fold till the last line for normal comment lines
2010-08-21 23:59:56 +00:00
else if ( IsStreamCommentStyle ( stylePrev )
2009-06-24 19:09:31 +00:00
& & ! ( styleNext = = SCE_POWERPRO_COMMENTLINE )
2010-08-21 23:59:56 +00:00
& & stylePrev = = SCE_POWERPRO_COMMENTLINE
2009-06-24 19:09:31 +00:00
& & style = = SCE_POWERPRO_COMMENTLINE ) {
levelNext - - ;
}
// fold till the one but last line for Blockcomment lines
2010-08-21 23:59:56 +00:00
else if ( IsStreamCommentStyle ( stylePrev )
2009-06-24 19:09:31 +00:00
& & ! ( styleNext = = SCE_POWERPRO_COMMENTBLOCK )
& & style = = SCE_POWERPRO_COMMENTBLOCK ) {
levelNext - - ;
levelCurrent - - ;
}
}
int levelUse = levelCurrent ;
int lev = levelUse | levelNext < < 16 ;
if ( visibleChars = = 0 & & foldCompact )
lev | = SC_FOLDLEVELWHITEFLAG ;
if ( levelUse < levelNext ) {
lev | = SC_FOLDLEVELHEADERFLAG ;
}
if ( lev ! = styler . LevelAt ( lineCurrent ) ) {
styler . SetLevel ( lineCurrent , lev ) ;
}
// reset values for the next line
lineCurrent + + ;
stylePrev = style ;
style = styleNext ;
levelCurrent = levelNext ;
visibleChars = 0 ;
2010-08-21 23:59:56 +00:00
2009-06-24 19:09:31 +00:00
// if the last characters are ;;+ then don't reset since the line continues on the next line.
if ( chPrev = = ' + ' & & chPrevPrev = = ' ; ' & & chPrevPrevPrev = = ' ; ' ) {
//do nothing
} else {
szKeywordlen = 0 ;
szDolen = 0 ;
FirstWordStart = false ;
FirstWordEnd = false ;
DoFoundLast = false ;
//blank out keyword
for ( unsigned int i = 0 ; i < KEYWORD_MAX ; i + + ) {
szKeyword [ i ] = ' \0 ' ;
}
}
}
// save the last processed characters
if ( ( ch > 0 ) & & ! isspacechar ( ch ) ) {
chPrevPrevPrev = chPrevPrev ;
chPrevPrev = chPrev ;
chPrev = ch ;
visibleChars + + ;
}
}
2010-08-21 23:59:56 +00:00
//close folds on the last line - without this a 'phantom'
2009-06-24 19:09:31 +00:00
//fold can appear when an open fold is on the last line
//this can occur because functions and labels don't have an explicit end
if ( lineCurrent > = lastLine ) {
int lev = 0 ;
lev | = SC_FOLDLEVELWHITEFLAG ;
styler . SetLevel ( lineCurrent , lev ) ;
}
}
static const char * const powerProWordLists [ ] = {
" Keyword list 1 " ,
" Keyword list 2 " ,
" Keyword list 3 " ,
" Keyword list 4 " ,
0 ,
} ;
static void ColourisePowerProDocWrapper ( unsigned int startPos , int length , int initStyle , WordList * keywordlists [ ] ,
Accessor & styler ) {
ColourisePowerProDoc ( startPos , length , initStyle , keywordlists , styler , false ) ;
}
LexerModule lmPowerPro ( SCLEX_POWERPRO , ColourisePowerProDocWrapper , " powerpro " , FoldPowerProDoc , powerProWordLists ) ;