static void ColouriseAU3Doc()

in ext/scintilla/lexers/LexAU3.cxx [196:650]


static void ColouriseAU3Doc(Sci_PositionU startPos,
							Sci_Position length, int initStyle,
							WordList *keywordlists[],
							Accessor &styler) {

    WordList &keywords = *keywordlists[0];
    WordList &keywords2 = *keywordlists[1];
    WordList &keywords3 = *keywordlists[2];
    WordList &keywords4 = *keywordlists[3];
    WordList &keywords5 = *keywordlists[4];
    WordList &keywords6 = *keywordlists[5];
    WordList &keywords7 = *keywordlists[6];
    WordList &keywords8 = *keywordlists[7];
	// find the first previous line without continuation character at the end
	Sci_Position lineCurrent = styler.GetLine(startPos);
	Sci_Position s_startPos = startPos;
	// When not inside a Block comment: find First line without _
	if (!(initStyle==SCE_AU3_COMMENTBLOCK)) {
		while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) ||
			   (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) {
			lineCurrent--;
			startPos = styler.LineStart(lineCurrent); // get start position
			initStyle =  0;                           // reset the start style to 0
		}
	}
	// Set the new length to include it from the start and set the start position
	length = length + s_startPos - startPos;      // correct the total length to process
    styler.StartAt(startPos);

    StyleContext sc(startPos, length, initStyle, styler);
	char si;     // string indicator "=1 '=2
	char ni;     // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3
	char ci;     // comment indicator 0=not linecomment(;)
	char s_save[100] = "";
	si=0;
	ni=0;
	ci=0;
	//$$$
    for (; sc.More(); sc.Forward()) {
		char s[100];
		sc.GetCurrentLowered(s, sizeof(s));
		// **********************************************
		// save the total current word for eof processing
		if (IsAWordChar(sc.ch) || sc.ch == '}')
		{
			strcpy(s_save,s);
			int tp = static_cast<int>(strlen(s_save));
			if (tp < 99) {
				s_save[tp] = static_cast<char>(tolower(sc.ch));
				s_save[tp+1] = '\0';
			}
		}
		// **********************************************
		//
		switch (sc.state)
        {
            case SCE_AU3_COMMENTBLOCK:
            {
				//Reset at line end
				if (sc.atLineEnd) {
					ci=0;
					if (strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0) {
						if (sc.atLineEnd)
							sc.SetState(SCE_AU3_DEFAULT);
						else
							sc.SetState(SCE_AU3_COMMENTBLOCK);
					}
					break;
				}
				//skip rest of line when a ; is encountered
				if (sc.chPrev == ';') {
					ci=2;
					sc.SetState(SCE_AU3_COMMENTBLOCK);
				}
				// skip rest of the line
				if (ci==2)
					break;
				// check when first character is detected on the line
				if (ci==0) {
					if (IsAWordStart(static_cast<char>(sc.ch)) || IsAOperator(static_cast<char>(sc.ch))) {
						ci=1;
						sc.SetState(SCE_AU3_COMMENTBLOCK);
					}
					break;
				}
				if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0))) {
					if ((strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0))
							sc.SetState(SCE_AU3_COMMENT);  // set to comment line for the rest of the line
					else
						ci=2;  // line doesn't begin with #CE so skip the rest of the line
				}
				break;
			}
            case SCE_AU3_COMMENT:
            {
                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
            case SCE_AU3_OPERATOR:
            {
                // check if its a COMobject
				if (sc.chPrev == '.' && IsAWordChar(sc.ch)) {
					sc.SetState(SCE_AU3_COMOBJ);
				}
				else {
					sc.SetState(SCE_AU3_DEFAULT);
				}
                break;
            }
            case SCE_AU3_SPECIAL:
            {
                if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
				if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
            case SCE_AU3_KEYWORD:
            {
                if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && (strcmp(s, "#comments") == 0 || strcmp(s, "#include") == 0))))
                {
                    if (!IsTypeCharacter(sc.ch))
                    {
						if (strcmp(s, "#cs")== 0 || strcmp(s, "#comments-start")== 0 )
						{
							sc.ChangeState(SCE_AU3_COMMENTBLOCK);
							sc.SetState(SCE_AU3_COMMENTBLOCK);
							break;
						}
						else if (keywords.InList(s)) {
							sc.ChangeState(SCE_AU3_KEYWORD);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords2.InList(s)) {
							sc.ChangeState(SCE_AU3_FUNCTION);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords3.InList(s)) {
							sc.ChangeState(SCE_AU3_MACRO);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords5.InList(s)) {
							sc.ChangeState(SCE_AU3_PREPROCESSOR);
							sc.SetState(SCE_AU3_DEFAULT);
							if (strcmp(s, "#include")== 0)
							{
								si = 3;   // use to determine string start for #inlude <>
							}
						}
						else if (keywords6.InList(s)) {
							sc.ChangeState(SCE_AU3_SPECIAL);
							sc.SetState(SCE_AU3_SPECIAL);
						}
						else if ((keywords7.InList(s)) && (!IsAOperator(static_cast<char>(sc.ch)))) {
							sc.ChangeState(SCE_AU3_EXPAND);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (keywords8.InList(s)) {
							sc.ChangeState(SCE_AU3_UDF);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (strcmp(s, "_") == 0) {
							sc.ChangeState(SCE_AU3_OPERATOR);
							sc.SetState(SCE_AU3_DEFAULT);
						}
						else if (!IsAWordChar(sc.ch)) {
							sc.ChangeState(SCE_AU3_DEFAULT);
							sc.SetState(SCE_AU3_DEFAULT);
						}
					}
				}
                if (sc.atLineEnd) {
					sc.SetState(SCE_AU3_DEFAULT);}
                break;
            }
			case SCE_AU3_NUMBER:
            {
				// Numeric indicator error=9 normal=0 normal+dec=1 hex=2 E-not=3
				//
				// test for Hex notation
				if (strcmp(s, "0") == 0 && (sc.ch == 'x' || sc.ch == 'X') && ni == 0)
				{
					ni = 2;
					break;
				}
				// test for E notation
				if (IsADigit(sc.chPrev) && (sc.ch == 'e' || sc.ch == 'E') && ni <= 1)
				{
					ni = 3;
					break;
				}
				//  Allow Hex characters inside hex numeric strings
				if ((ni == 2) &&
					(sc.ch == 'a' || sc.ch == 'b' || sc.ch == 'c' || sc.ch == 'd' || sc.ch == 'e' || sc.ch == 'f' ||
					 sc.ch == 'A' || sc.ch == 'B' || sc.ch == 'C' || sc.ch == 'D' || sc.ch == 'E' || sc.ch == 'F' ))
				{
					break;
				}
				// test for 1 dec point only
				if (sc.ch == '.')
				{
					if (ni==0)
					{
						ni=1;
					}
					else
					{
						ni=9;
					}
					break;
				}
				// end of numeric string ?
				if (!(IsADigit(sc.ch)))
				{
					if (ni==9)
					{
						sc.ChangeState(SCE_AU3_DEFAULT);
					}
					sc.SetState(SCE_AU3_DEFAULT);
				}
				break;
			}
			case SCE_AU3_VARIABLE:
			{
				// Check if its a COMObject
				if (sc.ch == '.' && !IsADigit(sc.chNext)) {
					sc.SetState(SCE_AU3_OPERATOR);
				}
				else if (!IsAWordChar(sc.ch)) {
					sc.SetState(SCE_AU3_DEFAULT);
				}
				break;
            }
			case SCE_AU3_COMOBJ:
			{
				if (!(IsAWordChar(sc.ch))) {
					sc.SetState(SCE_AU3_DEFAULT);
				}
				break;
            }
            case SCE_AU3_STRING:
            {
				// check for " to end a double qouted string or
				// check for ' to end a single qouted string
	            if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>'))
				{
					sc.ForwardSetState(SCE_AU3_DEFAULT);
					si=0;
					break;
				}
                if (sc.atLineEnd)
				{
					si=0;
					// at line end and not found a continuation char then reset to default
					Sci_Position lineCurrent = styler.GetLine(sc.currentPos);
					if (!IsContinuationLine(lineCurrent,styler))
					{
						sc.SetState(SCE_AU3_DEFAULT);
						break;
					}
				}
				// find Sendkeys in a STRING
				if (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ) {
					sc.SetState(SCE_AU3_SENT);}
				break;
            }

            case SCE_AU3_SENT:
            {
				// Send key string ended
				if (sc.chPrev == '}' && sc.ch != '}')
				{
					// set color to SENDKEY when valid sendkey .. else set back to regular string
					char sk[100];
					// split {111 222} and return {111} and check if 222 is valid.
					// if return code = 1 then invalid 222 so must be string
					if (GetSendKey(s,sk))
					{
						sc.ChangeState(SCE_AU3_STRING);
					}
					// if single char between {?} then its ok as sendkey for a single character
					else if (strlen(sk) == 3)
					{
						sc.ChangeState(SCE_AU3_SENT);
					}
					// if sendkey {111} is in table then ok as sendkey
					else if (keywords4.InList(sk))
					{
						sc.ChangeState(SCE_AU3_SENT);
					}
					else
					{
						sc.ChangeState(SCE_AU3_STRING);
					}
					sc.SetState(SCE_AU3_STRING);
				}
				else
				{
					// check if the start is a valid SendKey start
					Sci_Position		nPos	= 0;
					int		nState	= 1;
					char	cTemp;
					while (!(nState == 2) && ((cTemp = s[nPos]) != '\0'))
					{
						if (cTemp == '{' && nState == 1)
						{
							nState = 2;
						}
						if (nState == 1 && !(cTemp == '+' || cTemp == '!' || cTemp == '^' || cTemp == '#' ))
						{
							nState = 0;
						}
						nPos++;
					}
					//Verify characters infront of { ... if not assume  regular string
					if (nState == 1 && (!(sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' ))) {
						sc.ChangeState(SCE_AU3_STRING);
						sc.SetState(SCE_AU3_STRING);
					}
					// If invalid character found then assume its a regular string
					if (nState == 0) {
						sc.ChangeState(SCE_AU3_STRING);
						sc.SetState(SCE_AU3_STRING);
					}
				}
				// check if next portion is again a sendkey
				if (sc.atLineEnd)
				{
					sc.ChangeState(SCE_AU3_STRING);
					sc.SetState(SCE_AU3_DEFAULT);
					si = 0;  // reset string indicator
				}
				//* check in next characters following a sentkey are again a sent key
				// Need this test incase of 2 sentkeys like {F1}{ENTER} but not detect {{}
				if (sc.state == SCE_AU3_STRING && (sc.ch == '{' || sc.ch == '+' || sc.ch == '!' || sc.ch == '^' || sc.ch == '#' )) {
					sc.SetState(SCE_AU3_SENT);}
				// check to see if the string ended...
				// Sendkey string isn't complete but the string ended....
				if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\''))
				{
					sc.ChangeState(SCE_AU3_STRING);
					sc.ForwardSetState(SCE_AU3_DEFAULT);
				}
				break;
            }
        }  //switch (sc.state)

        // Determine if a new state should be entered:

		if (sc.state == SCE_AU3_DEFAULT)
        {
            if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
            else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);}
            else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);}
            else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);}
            else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);}
            //else if (sc.ch == '_') {sc.SetState(SCE_AU3_KEYWORD);}
            else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);}  // string after #include
            else if (sc.ch == '\"') {
				sc.SetState(SCE_AU3_STRING);
				si = 1;	}
            else if (sc.ch == '\'') {
				sc.SetState(SCE_AU3_STRING);
				si = 2;	}
            else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)))
			{
				sc.SetState(SCE_AU3_NUMBER);
				ni = 0;
			}
            else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);}
            else if (IsAOperator(static_cast<char>(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);}
			else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
        }
    }      //for (; sc.More(); sc.Forward())

	//*************************************
	// Colourize the last word correctly
	//*************************************
	if (sc.state == SCE_AU3_KEYWORD)
		{
		if (strcmp(s_save, "#cs")== 0 || strcmp(s_save, "#comments-start")== 0 )
		{
			sc.ChangeState(SCE_AU3_COMMENTBLOCK);
			sc.SetState(SCE_AU3_COMMENTBLOCK);
		}
		else if (keywords.InList(s_save)) {
			sc.ChangeState(SCE_AU3_KEYWORD);
			sc.SetState(SCE_AU3_KEYWORD);
		}
		else if (keywords2.InList(s_save)) {
			sc.ChangeState(SCE_AU3_FUNCTION);
			sc.SetState(SCE_AU3_FUNCTION);
		}
		else if (keywords3.InList(s_save)) {
			sc.ChangeState(SCE_AU3_MACRO);
			sc.SetState(SCE_AU3_MACRO);
		}
		else if (keywords5.InList(s_save)) {
			sc.ChangeState(SCE_AU3_PREPROCESSOR);
			sc.SetState(SCE_AU3_PREPROCESSOR);
		}
		else if (keywords6.InList(s_save)) {
			sc.ChangeState(SCE_AU3_SPECIAL);
			sc.SetState(SCE_AU3_SPECIAL);
		}
		else if (keywords7.InList(s_save) && sc.atLineEnd) {
			sc.ChangeState(SCE_AU3_EXPAND);
			sc.SetState(SCE_AU3_EXPAND);
		}
		else if (keywords8.InList(s_save)) {
			sc.ChangeState(SCE_AU3_UDF);
			sc.SetState(SCE_AU3_UDF);
		}
		else {
			sc.ChangeState(SCE_AU3_DEFAULT);
			sc.SetState(SCE_AU3_DEFAULT);
		}
	}
	if (sc.state == SCE_AU3_SENT)
    {
		// Send key string ended
		if (sc.chPrev == '}' && sc.ch != '}')
		{
			// set color to SENDKEY when valid sendkey .. else set back to regular string
			char sk[100];
			// split {111 222} and return {111} and check if 222 is valid.
			// if return code = 1 then invalid 222 so must be string
			if (GetSendKey(s_save,sk))
			{
				sc.ChangeState(SCE_AU3_STRING);
			}
			// if single char between {?} then its ok as sendkey for a single character
			else if (strlen(sk) == 3)
			{
				sc.ChangeState(SCE_AU3_SENT);
			}
			// if sendkey {111} is in table then ok as sendkey
			else if (keywords4.InList(sk))
			{
				sc.ChangeState(SCE_AU3_SENT);
			}
			else
			{
				sc.ChangeState(SCE_AU3_STRING);
			}
			sc.SetState(SCE_AU3_STRING);
		}
		// check if next portion is again a sendkey
		if (sc.atLineEnd)
		{
			sc.ChangeState(SCE_AU3_STRING);
			sc.SetState(SCE_AU3_DEFAULT);
		}
    }
	//*************************************
	sc.Complete();
}