Пример #1
0
_EXPORT bool Balance(CLanguageProxy& proxy, int32& start, int32& end)
{
	bool in = false;
	const char *txt = proxy.Text(), *st;
	int32 size = proxy.Size();

	if (start < 0 || start > end || end > size)
		return false;

	st = txt + start;

	while (txt < st)
	{
		const char *t = in ? skip_in(txt + 1) : skip_out(txt + 1);
		in = !in;

		if (*t && t > st)
		{
			start = txt - proxy.Text() + 1;
			end = t - proxy.Text();
			return true;
		}

		txt = t;
	}

	return false;
} /* Balance */
Пример #2
0
_EXPORT int32 FindNextWord(const CLanguageProxy& proxy)
{
	int32 mark = 0, i = 0;
	int32 unicode, state, len;
	const char *txt = proxy.Text();

	state = 1;

	while (state && i < proxy.Size())
	{
		proxy.CharInfo(txt + i, unicode, len);

		if (proxy.isspace_uc(unicode))
		{
			state = 0;
		}
		else
		{
			mark = i + len - 1;
		}

		i += len;
	}

	return mark;
} /* FindNextWord */
Пример #3
0
int32 FindNextWord(const CLanguageProxy& proxy)
{
	int32 mark = 0, i = 0;
	int32 unicode, state, len;

	state = 1;

	while (state > 0 && i < proxy.Size())
	{
		proxy.CharInfo(proxy.Text() + i, unicode, len);

		int cl = 0;

		if (unicode == '\n')
			cl = 3;
		else if (proxy.isspace_uc(unicode))
			cl = 2;
		else if (proxy.isalnum_uc(unicode))
			cl = 4;
		else
			switch (unicode)
			{
				case 160:
				case 8199:
				case 8209:
					cl = 1;
					break;
				case '&':
				case '*':
				case '+':
				case '-':
//				case '/':
//				case '<':
				case '=':
//				case '>':
				case '\\':
				case '^':
				case '|':
					cl = 5;
					break;
				default:
					cl = 4;
			}

		unsigned char t = kWordWrapTable[(state - 1) * 6 + cl];

		state = t & 0x7f;

		if (t & 0x80)
			mark = i + len - 1;

		i += len;
	}

	return mark;
} /* FindNextWord */
void add_to_popup(const char* name, PopupList &pul, CLanguageProxy& proxy)
{
	if (pul.size() > 0)
	{
		proxy.AddSeparator(name);
		for (uint i=0; i<pul.size(); i++)
		{
			proxy.AddFunction(pul[i].label.String(), pul[i].text.String(),
				pul[i].position - proxy.Text(), pul[i].italic);
		}
	}
}
Пример #5
0
// ColorLine
_EXPORT
void
ColorLine(CLanguageProxy& proxy, int32& /*state*/)
{
	if (strncmp(proxy.Text(), "diff", 4) == 0
	|| strncmp(proxy.Text(), "@@", 2) == 0) {
		proxy.SetColor(0, kColorComment1);
	} else if (*proxy.Text() == '-' || *proxy.Text() == '<') {
		proxy.SetColor(0, kColorError1);
	} else if (*proxy.Text() == '+' || *proxy.Text() == '>') {
		proxy.SetColor(0, kColorString1);
	} else
		proxy.SetColor(0, kColorText);
}
Пример #6
0
void ScanForFunctions(CLanguageProxy& proxy)
{
	const char *text = proxy.Text(), *max = text + proxy.Size();

	if (*max != 0) return;

	while (text < max)
	{
		text = comment(text);
		
		switch (*text++)
		{
			case 'c':
			case 'C':
				if (!strncasecmp(text, "onstructor", 10)) text = parseFunction(text + 10, proxy);
			break;

			case 'd':
			case 'D':
				if (!strncasecmp(text, "estructor", 9)) text = parseFunction(text + 9, proxy);
			break;

			case 'f':
			case 'F':
				if (!strncasecmp(text, "unction", 7))
					text = parseFunction(text + 7, proxy);
			break;

			case 'p':
			case 'P':
				if (!strncasecmp(text, "rocedure", 8))
					text = parseFunction(text + 8, proxy);
			break;

			case 'u':
			case 'U':
				if (!strncasecmp(text, "ses", 3)) text = parseUses(text + 3, proxy);
			break;
		}
	}
}
Пример #7
0
void ScanForFunctions(CLanguageProxy& proxy)
{
	const char *text = proxy.Text(), *max = text + proxy.Size();
	if (*max != 0)
		return;
	
	while (text < max)
	{
		text = skip(text, '<');
		text = skip_white(text);
		
		switch (toupper(*text))
		{
			case 0:
				return;
			case 'A':
				if (isspace(*++text))
					text = Anchor(text, proxy);
				else
					text = skip_nc(text, '>');
				break;
			case 'H':
				if (*++text >= '1' && *text <= '6')
				{
					text = Heading(text, proxy);
				}
				else
					text = skip_nc(text, '>');
				break;
			case 'S':
				if (strncasecmp(text, "SCRIPT", 6) == 0)
					text = JavaScript(text, proxy);
				break;
			default:
				text = skip_nc(text + 1, '>');
				break;
		}
	}
} /* ScanForFunctions */
Пример #8
0
void ScanForFunctions(CLanguageProxy& proxy)
{
	const char* text = proxy.Text(), *max = text + proxy.Size();
	char* scope = (char*)"file";
	if (*max != 0)
		return;
	
	while (text < max)
	{
		text = comment(text, false);
		
		switch (*text)
		{
			case 0:
				return;
			case '\'':
				text = skip(text + 1, '\'');
				break;
			case '"':
				text = skip(text + 1, '"');
				break;
			case '(':
			case '{':
			case '[':
				text = parens(text + 1, *text);
				break;
			case '#':
				text = preprocessor(text + 1, proxy);
				break;
			default:
				if (isidentf(*text))
					text = ident(text, proxy, scope);
				else
					text++;
				break;
		}
	}
} /* ScanForFunctions */
Пример #9
0
// ScanForFunctions
_EXPORT
void
ScanForFunctions(CLanguageProxy& proxy)
{
	const char* text = proxy.Text();
	for(const char* pos = text; pos != NULL; ) {
		if (strncmp(pos, "--- ", 4) == 0 && !isdigit(*(pos+4))) {
			const char* displayPos = pos + 4;
				// skip to filename
			const char* lineEnd = strchr(pos, '\n');
			if (!lineEnd)
				lineEnd = pos + strlen(pos);
			const char* tabPos = strchr(pos, '\t');
			if (tabPos && tabPos < lineEnd)
				// cut line off at tab, in order to drop the date following the filename
				lineEnd = tabPos;
			BString matchLine(pos, lineEnd-pos);
			BString displayLine(displayPos, lineEnd-displayPos);
			proxy.SetNestLevel(0);
			proxy.AddFunction(displayLine.String(), matchLine.String(), pos-text, false);
		} else if (strncmp(pos, "@@", 2) == 0
			|| (strncmp(pos, "--- ", 4) == 0 && isdigit(*(pos+4)))) {
			const char* displayPos = pos + 2;
				// skip over "@@" or "--"
			const char* lineEnd = strchr(pos, '\n');
			if (!lineEnd)
				lineEnd = pos + strlen(pos);
			BString matchLine(pos, lineEnd-pos);
			BString displayLine(displayPos, lineEnd-2-displayPos);
				// -2 in order to skip back over '@@'
			proxy.SetNestLevel(1);
			proxy.AddFunction(displayLine.String(), matchLine.String(), pos-text, false);
		}
		if ((pos = strchr(pos+1, '\n')) != NULL)
			pos++;
	}
}
Пример #10
0
_EXPORT void ColorLine(CLanguageProxy& proxy, int32& state)
{
	const char *text = proxy.Text();
	int32 size = proxy.Size();
	int32 i = 0, s = 0, kws = 0, esc = 0;
	char c;
	bool leave = false;

	if (state == LCOMMENT)
		proxy.SetColor(0, kColorComment1);
	else
		proxy.SetColor(0, kColorText);

	if (size <= 0)
		return;

	while (!leave)
	{
		GETCHAR;
		if (c == '`')
		{
			GETCHAR;
			c = ' ';
		}

		switch (state)
		{
			case START:
				if (c == '\\')
					state = COMMAND1;
				else if (c == '%')
					state = LCOMMENT;
				else if (c == '$')
					state = MATH;
				else if (c == '\n' || c == 0)
					leave = true;
				else if (isalnum(c))
					state = WORD;
                /* This is a bit strange to have some of the characters covered above, but who cares?*/
				else if (c == '#' || c == '&'
						|| c == '~' || c == '_' || c == '^'
						|| c == '{' || c == '}'
						|| c == '[' || c == ']'
						)
					state = CONSTCHAR;

				if ((leave || state != START) && s < i)
				{
					proxy.SetColor(s, kColorText);
					s = i - 1;
				}
				break;

			case CONSTCHAR:
				proxy.SetColor(s, kColorCharConst);
				s = --i;
				state = START;
				break;

			case WORD:
				if (!isalnum(c))
				{
					proxy.SetColor(s, kColorText);
					s = --i;
					state = START;
				}
				break;

			case LCOMMENT:
				proxy.SetColor(s, kColorComment1);
				leave = true;
				if (text[size - 1] == '\n')
					state = START;
				break;

			case COMMAND1:
                                     if (c=='('){
                                              state = MATH;
                                     } else if ((isalnum(c)) || (c=='@'))   /* a generic command has been found. */
			    /* Note that commands with "@" in their name only appear in .cls or .sty files */
                                     {
					kws = proxy.Move(c, 1);
					state = COMMAND2;
				}
				else   /* we are escaping a special text character such as \# or \$*/
				{
					proxy.SetColor(s, kColorText);
					s = i;
					state = START;
				}
				break;

			case COMMAND2:    /* Inside the name of a generic command */
				if (!(isalnum(c)) && !(c=='@')) /* found end of command name */
				{      /* now check the command name against a keyword list */
					int kwc;

					if (i > s + 1 && (kwc = proxy.IsKeyword(kws)) != 0)
					{
						switch (kwc)
						{    /* use a specific keyword category color */
							case 1:	proxy.SetColor(s, kColorKeyword1); break;
							case 2:	proxy.SetColor(s, kColorUserSet1); break;
							case 3:	proxy.SetColor(s, kColorUserSet2); break;
							case 4:	proxy.SetColor(s, kColorUserSet3); break;
							case 5:	proxy.SetColor(s, kColorUserSet4); break;
//							default:	ASSERT(false);
						}
					}
					else      /* use a generic keyword color */
					{
						proxy.SetColor(s, kColorKeyword1);
					}

					s = --i;
					state = START;
				}
				else if (kws) /* still in command name */
					kws = proxy.Move((int)(unsigned char)c, kws);
				break;


			case MATH:
                                     /* both "$" and "\)" will end math mode */
				if ( (c == '$' && !esc) || (c == ')' && esc) )
				{
					proxy.SetColor(s, kColorString1);
					s = i;
					state = START;
				}
				else if (c == '\n' || c == 0)
				{
					proxy.SetColor(s, kColorString1);
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;

			default:	// error condition, gracefully leave the loop
				leave = true;
				break;
		}
	}
} /* ColorLine */
Пример #11
0
_EXPORT void ColorLine(CLanguageProxy& proxy, int32& state)
{
	const char *text = proxy.Text();
	int32 size = proxy.Size();
	int32 i = 0, s = 0, kws = 0, esc = 0;
	char c = 0;
	bool leave = false;

	if (state == LCOMMENT)
		proxy.SetColor(0, kColorComment1);
	else
		proxy.SetColor(0, kColorText);

	if (size <= 0)
		return;

	while (!leave)
	{
		char b = c;
		GETCHAR;

		switch (state) {
			case START:
				if (c == '#' && (!b || isspace(b)))
					state = LCOMMENT;
				else if (isalpha(c) || c == '_')
				{
					kws = proxy.Move(c, 1);
					state = IDENT;
				}
				else if (c == '"')
					state = STRING1;
				else if (c == '\'')
					state = STRING2;
				else if (c == '\n' || c == 0)
					leave = true;

				if (leave || (state != START && s < i))
				{
					proxy.SetColor(s, kColorText);
					s = i - 1;
				}
				break;

			case LCOMMENT:
				proxy.SetColor(s, kColorComment1);
				leave = true;
				if (text[size - 1] == '\n')
					state = START;
				break;

			case IDENT:
				if (!isalnum(c) && c != '_')
				{
					int kwc;

					if (i >= s + 1 && (kwc = proxy.IsKeyword(kws)) != 0)
					{
						switch (kwc)
						{
							case 1:	proxy.SetColor(s, kColorKeyword1); break;
							case 2:	proxy.SetColor(s, kColorUserSet1); break;
							case 3:	proxy.SetColor(s, kColorUserSet2); break;
							case 4:	proxy.SetColor(s, kColorUserSet3); break;
							case 5:	proxy.SetColor(s, kColorUserSet4); break;
//							default:ASSERT(false);
						}
					}
					else
					{
						proxy.SetColor(s, kColorText);
					}

					s = --i;
					state = START;
				}
				else if (kws)
					kws = proxy.Move((int)(unsigned char)c, kws);
				break;

			case STRING1:
				if (c == '"' && !esc)
				{
					proxy.SetColor(s, kColorString1);
					s = i;
					state = START;
				}
				else if (c == '\n' || c == 0)
				{
					if (text[i - 2] == '\\' && text[i - 3] != '\\')
					{
						proxy.SetColor(s, kColorString1);
					}
					else
					{
						proxy.SetColor(s, kColorText);
						state = START;
					}

					s = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;

			case STRING2:
				if (c == '\'' && !esc)
				{
					proxy.SetColor(s, kColorString1);
					s = i;
					state = START;
				}
				else if (c == '\n' || c == 0)
				{
					if (text[i - 2] == '\\' && text[i - 3] != '\\')
					{
						proxy.SetColor(s, kColorString1);
					}
					else
					{
						proxy.SetColor(s, kColorText);
						state = START;
					}

					s = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;

			default:	// error condition, gracefully leave the loop
				leave = true;
				break;
		}
	}
} /* CshellIntf::ColorLine */
Пример #12
0
_EXPORT void ColorLine(CLanguageProxy& proxy, int32& state)
{
	const char *text = proxy.Text();
	int32 size = proxy.Size();
	int32 i = 0, s = 0, kws = 0, cc_cnt = 0, esc = 0;
	char c;
	bool leave = false;

	if (state == COMMENT || state == LCOMMENT)
		proxy.SetColor(0, kColorComment1);
	else
		proxy.SetColor(0, kColorText);

	if (size <= 0)
		return;

	while (!leave)
	{
		GETCHAR;

		switch (state) {
			case START:
				if (isalpha(c) || c == '_')
				{
					kws = proxy.Move(c, 1);
					state = IDENT;
				}
				else if (c == '/' && text[i] == '*')
					state = COMMENT;
				else if (c == '/' && text[i] == '/')
					state = LCOMMENT;
				else if (c == '"')
					state = STRING;
				else if (c == '\'')
				{
					state = CHAR_CONST;
					cc_cnt = 0;
				}
				else if (c == '\n' || c == 0)
					leave = true;

				if (leave || (state != START && s < i))
				{
					proxy.SetColor(s, kColorText);
					s = i - 1;
				}
				break;

			case COMMENT:
				if ((s == 0 || i > s + 1) && c == '*' && text[i] == '/')
				{
					proxy.SetColor(s, kColorComment1);
					s = i + 1;
					state = START;
				}
				else if (c == 0 || c == '\n')
				{
					proxy.SetColor(s, kColorComment1);
					leave = true;
				}
				break;

			case LCOMMENT:
				proxy.SetColor(s, kColorComment1);
				leave = true;
				if (text[size - 1] == '\n')
					state = START;
				break;

			case IDENT:
				if (!isalnum(c) && c != '_' && c != '.')
				{
					int32 kwc;

					if (i > s + 1 && (kwc = proxy.IsKeyword(kws)) != 0)
					{
						switch (kwc)
						{
							case 1:	proxy.SetColor(s, kColorKeyword1); break;
							case 2:	proxy.SetColor(s, kColorUserSet1); break;
							case 3:	proxy.SetColor(s, kColorUserSet2); break;
							case 4:	proxy.SetColor(s, kColorUserSet3); break;
							case 5:	proxy.SetColor(s, kColorUserSet4); break;
//							default:	ASSERT(false);
						}
					}
					else
					{
						proxy.SetColor(s, kColorText);
					}

					s = --i;
					state = START;
				}
				else if (kws)
					kws = proxy.Move((int)(unsigned char)c, kws);
				break;

			case STRING:
				if (c == '"' && !esc)
				{
					proxy.SetColor(s, kColorString1);
					s = i;
					state = START;
				}
				else if (c == '\n' || c == 0)
				{
					if (text[i - 2] == '\\' && text[i - 3] != '\\')
					{
						proxy.SetColor(s, kColorString1);
					}
					else
					{
						proxy.SetColor(s, kColorText);
						state = START;
					}

					s = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;

			case CHAR_CONST:
				if (c == '\t' || c == '\n' || c == 0)	// don't like this
				{
					proxy.SetColor(s, kColorText);
					s = i;
					state = START;
				}
				else if (c == '\'' && !esc)
				{
					if (cc_cnt != 1 && cc_cnt != 2 && cc_cnt != 4)
					{
						proxy.SetColor(s, kColorText);
						s = --i;
						state = START;
					}
					else
					{
						proxy.SetColor(s, kColorCharConst);
						s = i;
						state = START;
					}
				}
				else
				{
					if (!esc) cc_cnt++;
					esc = !esc && (c == '\\');
				}
				break;

			default:	// error condition, gracefully leave the loop
				leave = true;
				break;
		}
	}
} /* ColorLine */
Пример #13
0
_EXPORT void ColorLine(CLanguageProxy& proxy, int32& state)
{
	const char *text = proxy.Text();
	int32 size = proxy.Size();
	int32 i = 0, s = 0, kws = 0, esc = 0;
	char c;
	bool leave = false;
	bool floating_point = false;
	bool hex_num = false;

//    int sqrBraquetStrCount = 0;

	if (state == LCOMMENT)
		proxy.SetColor(0, kColorComment1);
	else
		proxy.SetColor(0, kColorText);

	if (size <= 0)
		return;

	while (!leave)
	{
		GETCHAR;

		switch (state) {
			case START:
				if (isalpha(c) || c == '_')
				{
					kws = proxy.Move(tolower(c), 1);
					state = IDENT;
				}
				else if (c == '-' && text[i] == '-')
				{
					i++;
					state = LCOMMENT;
				}
				else if (c == '"')
					state = STRING;
				else if (c == '\'')
					state = STRING2;
/*
				else if (c == '[' && text[i] == '[')
				{
					sqrBraquetStrCount++;
					state = STRING3;
				}
*/
				else if (isNumeric(c) || (c == '$' && isHexNum(text[i])))
				{
					state = NUMERIC;
				}
				else if (isOperator(c))
				{
					state = OPERATOR;
				}
				else if (isSymbol(c))
				{
					state = SYMBOL;
				}
				else if (c == '\n' || c == 0)
					leave = true;

				if (leave || (state != START && s < i))
				{
					proxy.SetColor(s, kColorText);
					s = i - 1;
				}
			break;

			// -- format comments
			case LCOMMENT:
				proxy.SetColor(s - 1, kColorComment1);
				leave = true;
				if (text[size - 1] == '\n')
					state = START;
			break;

			case IDENT:
				if (!isalnum(c) && c != '_')
				{
					int32 kwc;

					if (i > s + 1 && (kwc = proxy.IsKeyword(kws)) != 0)
					{
						switch (kwc)
						{
							case 1:	proxy.SetColor(s, kColorKeyword1); break;
							case 2:	proxy.SetColor(s, kColorUserSet1); break;
							case 3:	proxy.SetColor(s, kColorUserSet2); break;
							case 4:	proxy.SetColor(s, kColorUserSet3); break;
							case 5:	proxy.SetColor(s, kColorUserSet4); break;
						}
						s = --i;
						state = START;
					}
					else
					{
						proxy.SetColor(s, kColorText);
						s = --i;
						state = START;
					}
				}
				else if (kws)
					kws = proxy.Move((int)(unsigned char) c, kws);
			break;

			case STRING:
				if (c == '"' && !esc)
				{
					proxy.SetColor(s, kColorString1);
					s = i;
					state = START;
				}
				else if (c == '\n' || c == 0)
				{
					if (text[i - 2] == '\\' && text[i - 3] != '\\')
					{
						proxy.SetColor(s, kColorString1);
					}
					else
					{
						proxy.SetColor(s, kColorText);
						state = START;
					}

					s = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
			break;

			case STRING2:
				if (c == '\'' && !esc)
				{
					proxy.SetColor(s, kColorString1);
					s = i;
					state = START;
				}
				else if (c == '\n' || c == 0)
				{
					if (text[i - 2] == '\\' && text[i - 3] != '\\')
					{
						proxy.SetColor(s, kColorString1);
					}
					else
					{
						proxy.SetColor(s, kColorText);
						state = START;
					}

					s = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
			break;
/*
			case STRING3:

			break;
*/
			case NUMERIC:
				proxy.SetColor(s, kColorNumber1);
				if (isNumeric(text[i - 1]) || (hex_num && isHexNum(text[i - 1])))
					;
				else
					if (text[i - 1] == '.' && floating_point == false)
						floating_point = true;
					else if (isHexNum(text[i - 1]) && hex_num == false)
						hex_num = true;
					else
					{
						s = i - 1;
						i--;
						state = START;
					}
			break;

			case OPERATOR:
				proxy.SetColor(s, kColorOperator1);
				if (isOperator(text[i - 1]))
					;
				else
				{
					s = i - 1;
					i--;
					state = START;
				}
			break;

			case SYMBOL:
				proxy.SetColor(s, kColorSeparator1);
				if (isSymbol(text[i - 1]))
					;
				else
				{
					s = i - 1;
					i--;
					state = START;
				}
			break;

			default:
				leave = true;
			break;
		}
	}
}
Пример #14
0
_EXPORT void ColorLine(CLanguageProxy& proxy, int& state)
{
	const char *text = proxy.Text();
	int size = proxy.Size();
	int i = 0, s = 0, kws = 0, esc = 0;
	char c, mc = 0;
	bool leave = false;
	
	if (state == COMMENT || state == LCOMMENT)
		proxy.SetColor(0, kColorComment1);
	else
		proxy.SetColor(0, kColorText);
	
	if (size <= 0)
		return;
	
	while (!leave)
	{
		GETCHAR;
		
		switch (state) {
			case START:
				if (c == '#' && text[i - 2] != '$')
					state = LCOMMENT;
				else if (isalpha(c) || c == '_')
				{
					kws = proxy.Move(c, 1);
					state = IDENT;
				}
				else if (c == '"')
					state = STRING1;
				else if (c == '\'')
					state = STRING2;
				else if (c == '&')
					state = SCOPE;
				else if (c == '$')
				{
					if (isalpha(text[i]) || text[i] == '#')
					{
						i++;
						state = VAR;
					}
					else
					{
						i++;
						proxy.SetColor(s, kColorText);
						s = i;
					}
				}
				else if (c == '@' || c == '*')
					state = VAR;
				else if (c == '/')
				{
					mc = '/';
					state = REGEX1;
				}
				else if (c == '\n' || c == 0)
					leave = true;
					
				if (leave || (state != START && s < i))
				{
					proxy.SetColor(s, kColorText);
					s = i - 1;
				}
				break;
			
			case LCOMMENT:
				proxy.SetColor(s, kColorComment1);
				leave = true;
				if (text[size - 1] == '\n')
					state = START;
				break;
			
			case IDENT:
				if (!isalnum(c) && c != '_')
				{
					int kwc;

					if (i >= s + 1 && (kwc = proxy.IsKeyword(kws)) != 0)
					{
						switch (kwc)
						{
							case 1:	proxy.SetColor(s, kColorKeyword1); break;
							case 2:	proxy.SetColor(s, kColorUserSet1); break;
							case 3:	proxy.SetColor(s, kColorUserSet2); break;
							case 4:	proxy.SetColor(s, kColorUserSet3); break;
							case 5:	proxy.SetColor(s, kColorUserSet4); break;
//							default:ASSERT(false);
						}
					}
					else
					{
						proxy.SetColor(s, kColorText);
					}
					
					if (i == s + 2)
					{
						switch (*(text + s))
						{
							case 'm': state = REGEX1; break;
							case 's': state = REGEX2; break;
							case 'q': state = REGEX1; break;
							case 'y': state = REGEX2; break;
							default:  state = START; break;
						}
					}
					else if (i == s + 3)
					{
						if (strncmp(text + s, "qq", 2) == 0)
							state = REGEX1;
						else if (strncmp(text + s, "qx", 2) == 0)
							state = REGEX1;
						else if (strncmp(text + s, "qw", 2) == 0)
							state = REGEX1;
						else if (strncmp(text + s, "tr", 2) == 0)
							state = REGEX2;
						else
							state = START;
					}
					else if (i == s + 4 && strncmp(text + s, "sub", 3) == 0)// && ci < 2)
						state = SUB1;
					else
						state = START;
					
					if (state == START || state == SUB1)
						s = --i;
					else
					{
						switch (c)
						{
							case '(':	mc = ')'; break;
							case '{':	mc = '}'; break;
							case '[':	mc = ']'; break;
							case '<':	mc = '>'; break;
							case ' ':	state = START; s = --i; break;
							default:	mc = c; break;
						}
						
						if (state != START)
							s = i - 1;
					}
				}
				else if (kws)
					kws = proxy.Move((int)(unsigned char)c, kws);
				break;
			
			case SUB1:
				if (isalpha(c))
					state = SUB2;
				else if (!isspace(c))
				{
					state = START;
					s = --i;
				}
				break;
			
			case SUB2:
				if (!isalnum(c) && c != '\'' && c != '_')
				{
					proxy.SetColor(s, kColorText);
					state = START;
					s = --i;
				}
				break;
			
			case STRING1:
				if (c == '"' && !esc)
				{
					proxy.SetColor(s, kColorString1);
					s = i;
					state = START;
				}
				else if (c == '\n' || c == 0)
				{
					if (text[i - 2] == '\\' && text[i - 3] != '\\')
					{
						proxy.SetColor(s, kColorString1);
					}
					else
					{
						proxy.SetColor(s, kColorText);
						state = START;
					}
					
					s = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;
			
			case STRING2:
				if (c == '\'' && !esc)
				{
					proxy.SetColor(s, kColorString1);
					s = i;
					state = START;
				}
				else if (c == '\n' || c == 0)
				{
					if (text[i - 2] == '\\' && text[i - 3] != '\\')
					{
						proxy.SetColor(s, kColorString1);
					}
					else
					{
						proxy.SetColor(s, kColorText);
						state = START;
					}
					
					s = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;
			
			case REGEX1:
				if (c == 0)	// don't like this
				{
					proxy.SetColor(s, kColorText);
					s = i;
					state = START;
				}
				else if (c == mc && !esc)
				{
					proxy.SetColor(s, kColorCharConst);
					s = i;
					state = START;
				}
				else
					esc = !esc && (c == '\\');
				break;
			
			case REGEX2:
				if (c == 0)	// don't like this
				{
					proxy.SetColor(s, kColorText);
					s = i;
					state = START;
				}
				else if (c == mc && !esc)
				{
					if (mc == ')' || mc == '}' || mc == ']' || mc == '>')
					{
						switch (text[i])
						{
							case '(':	mc = ')'; break;
							case '{':	mc = '}'; break;
							case '[':	mc = ']'; break;
							case '<':	mc = '>'; break;
							case ' ':	state = START; s = --i; break;
							default:	mc = text[i]; break;
						}
						i++;
					}

					if (state != START)
						state = REGEX1;
				}
				else
					esc = !esc && (c == '\\');
				break;
			
			case SCOPE:
				if (c == '\'' || (!isalnum(c) && c != '_'))
				{
					proxy.SetColor(s, kColorText);
					state = START;
				}
				break;
			
			case VAR:
				if (!isalnum(c) && c != '_')
				{
					proxy.SetColor(s, kColorText);
					state = START;
				}
				break;
			
			default:	// error condition, gracefully leave the loop
				leave = true;
				break;
		}
	}
} /* CperlIntf::ColorLine */
Пример #15
0
_EXPORT void ColorLine(CLanguageProxy& proxy, int& state)
{
	const char *text = proxy.Text();
	int size = proxy.Size();
	int i = 0, s = 0, kws = 0, cc_cnt = 0, esc = 0;
	char c;
	bool leave = false;
	// floating point flag, true when the NUMERIC: label finds a . inside a number, and checks to make sure that a number with two '.' is invalid. (and not highlighted as numeric)
	bool floating_point = false;
	// same flag, only for hex numbers. allows proper highlighting only for 1 x per number. (0x21 is ok. 0x023x31 is not. will look wierd.)
	bool hex_num = false;
	int ifZeroCounter = state >> STATE_SHIFT;
	state = state & STATE_MASK;
	
	if (state == COMMENT || state == LCOMMENT)
		proxy.SetColor(0, kColorComment1);
	else
		proxy.SetColor(0, kColorText);
	
	if (size <= 0)
		return;
	
	while (!leave)
	{
		GETCHAR;
		
		switch (state) {
			case START:
				s = i - 1;
				proxy.SetColor(s, kColorText);
				if (c == '#')
				{
					kws = proxy.Move(c, 1);
					state = PRAGMA1;
				}
				else if (isalpha(c) || c == '_')
				{
					kws = proxy.Move(c, 1);
					state = IDENT;
				}
				else if (c == '/' && text[i] == '*')
				{
					i++;
					state = COMMENT;
				}
				else if (c == '/' && text[i] == '/')
				{
					i++;
					state = LCOMMENT;
				}
				else if (c == '"')
					state = STRING;
				else if (c == '\'')
				{
					state = CHAR_CONST;
					cc_cnt = 0;
				}
				// m7m: here are the 3 magic IFs.
				else if (isNumeric(c))
				{
					state = NUMERIC;	
				}
				else if (isOperator(c))
				{
					state = OPERATOR;	
				}
				else if (isSymbol(c))
				{
					state = SYMBOL;
				}
				else if (c == '\n' || c == 0)
					leave = true;
				break;
			
			case COMMENT:
				if ((s == 0 || i > s + 1) && c == '*' && text[i] == '/')
				{
					proxy.SetColor(s, kColorComment1);
					i++;
					state = START;
				}
				else if (c == 0 || c == '\n')
				{
					proxy.SetColor(s, kColorComment1);
					leave = true;
				}
				break;

			case LCOMMENT:
				proxy.SetColor(s, kColorComment1);
				leave = true;
				if (text[size - 1] == '\n')
					state = START;
				break;
			
			case IDENT:
				if (!isalnum(c) && c != '_')
				{
					int kwc;

					if (i > s + 1 && (kwc = proxy.IsKeyword(kws)) != 0)
					{
						switch (kwc)
						{
							case 1:	proxy.SetColor(s, kColorKeyword1); break;
							case 2:	proxy.SetColor(s, kColorUserSet1); break;
							case 3:	proxy.SetColor(s, kColorUserSet2); break;
							case 4:	proxy.SetColor(s, kColorUserSet3); break;
							case 5:	proxy.SetColor(s, kColorUserSet4); break;
//							default:	ASSERT(false);
						}
					}
					else
						proxy.SetColor(s, kColorText);
					
					i--;
					state = START;
				}
				else if (kws)
					kws = proxy.Move((int)(unsigned char)c, kws);
				break;
			
			case PRAGMA1:
				if (c == ' ' || c == '\t')
					;
				else if (islower(c))
				{
					kws = proxy.Move((int)(unsigned char)c, kws);
					state = PRAGMA2;
				}
				else
				{
					proxy.SetColor(s, kColorText);
					i--;
					state = START;
				}	
				break;
			
			case PRAGMA2:
				if (!islower(c))
				{
					int kwc;

					if (i > s + 2 && (kwc = proxy.IsKeyword(kws)) != 0)
					{
						switch (kwc)
						{
							case 1:	proxy.SetColor(s, kColorKeyword1); break;
							case 2:	proxy.SetColor(s, kColorUserSet1); break;
							case 3:	proxy.SetColor(s, kColorUserSet2); break;
							case 4:	proxy.SetColor(s, kColorUserSet3); break;
							case 5:	proxy.SetColor(s, kColorUserSet4); break;
//							default:	ASSERT(false);
						}

						// check for "#if 0" or "elif 0"
						bool ifZero = false;
						int k = s + 1;
						while (text[k] == ' ' || text[k] == '\t')
							k++;
						int len = i - 1 - k;
						if (strings_equal(text + k, "if", len, 2)
							|| strings_equal(text + k, "elif", len, 4))
						{
							k = i - 1;
							while (text[k] == ' ' || text[k] == '\t')
								k++;
							if (text[k] == '0'
								&& (k + 1 == size || text[k + 1] == 0
									|| isspace(text[k + 1])))
							{
								proxy.SetColor(s, kColorComment1);
								state = IF_ZERO;
								ifZeroCounter = 1;
								leave = true;
							}
						}
					}
					else
					{
						proxy.SetColor(s, kColorText);
					}
					
					if (state != IF_ZERO)
					{
						state = strncmp(text+i-8, "include", 7) ? START : INCL1;
						s = --i;
					}
				}
				else if (kws)
					kws = proxy.Move((int)(unsigned char)c, kws);
				break;
			
			case INCL1:
				if (c == '"')
					state = INCL2;
				else if (c == '<')
					state = INCL3;
				else if (c != ' ' && c != '\t')
				{
					state = START;
					i--;
				}
				break;
			
			case INCL2:
				if (c == '"')
				{
					proxy.SetColor(s, kColorString1);
					state = START;
				}
				else if (c == '\n' || c == 0)
				{
					proxy.SetColor(s, kColorText);
					leave = true;
					state = START;
				}	
				break;
			
			case INCL3:
				if (c == '>')
				{
					proxy.SetColor(s, kColorString1);
					state = START;
				}
				else if (c == '\n' || c == 0)
				{
					proxy.SetColor(s, kColorText);
					leave = true;
					state = START;
				}	
				break;
			
			case STRING:
				if (c == '"' && !esc)
				{
					proxy.SetColor(s, kColorString1);
					state = START;
				}
				else if (c == '\n' || c == 0)
				{
					if (text[i - 2] == '\\' && text[i - 3] != '\\')
					{
						proxy.SetColor(s, kColorString1);
					}
					else
					{
						proxy.SetColor(s, kColorText);
						state = START;
					}
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;
			
			case CHAR_CONST:
				if (c == '\t' || c == '\n' || c == 0
					|| (c == '\'' && !esc && (cc_cnt == 0 || cc_cnt > 5)))
				{
					// invalid char constant - either invalid char or too short/long
					proxy.SetColor(s, kColorText);
					state = START;
				}
				else if (c == '\'' && !esc)
				{
					proxy.SetColor(s, kColorCharConst);
					state = START;
				}
				else
				{
					if (!esc)
						cc_cnt++;

					esc = !esc && (c == '\\');
				}
				break;

			case NUMERIC:
			{
				proxy.SetColor(s, kColorNumber1);
				if (isNumeric(text[i-1]) || (hex_num && isHexNum(text[i - 1])))
					;
				else
					if (text[i-1]=='.' && floating_point==false && hex_num==false)
						floating_point = true;
					else if (text[i-1]=='x' && hex_num==false && floating_point==false)
						hex_num = true;
					else
					{
						i--;
						hex_num = false;
						state = START;
					}
			}
			break;

			case OPERATOR:
			{
				proxy.SetColor(s, kColorOperator1);
				if (isOperator(text[i-1]))
					;
				else
				{
					i--;
					state = START;
				}
			}
			break;
			
			case SYMBOL:
			{
				proxy.SetColor(s, kColorSeparator1);
				if (isSymbol(text[i-1]))
					;
				else
				{
					i--;
					state = START;
				}
			}
			break;			

			case IF_ZERO:
			{
				if (isspace(c))
					break;
				proxy.SetColor(i - 1, kColorComment1);
				if (c == '#')
				{
					// get the preprocessor keyword
					while (isspace(GETCHAR));
					int s = i - 1;
					int end = s;
					while (end < size && text[end] != 0 && !isspace(text[end]))
						end++;
					int len = end - s;
					// on "#if", "#ifdef", "#ifndef" increment the nesting
					// counter
					if (strings_equal(text + s, "if", len, 2)
						|| strings_equal(text + s, "ifdef", len, 5)
						|| strings_equal(text + s, "ifndef", len, 6))
					{
						ifZeroCounter++;
						i = end + 1;
					}
					// on "endif" decrement the nesting counter
					else if (strings_equal(text + s, "endif", len, 5))
					{
						ifZeroCounter--;
						i = end + 1;
						// if the counter drops to zero, we fall be to normal
						// parsing
						if (ifZeroCounter == 0)
						{
							state = START;
							leave = true;
							break;
						}
					}
					// on "else" or "elif" and nest count 1, fall back to normal
					// parsing:
					else if (ifZeroCounter == 1
						&& (strings_equal(text + s, "else", len, 4)
							|| strings_equal(text + s, "elif", len, 4)))
					{
						i = end + 1;
						ifZeroCounter == 0;
						state = START;
						leave = true;
						break;
					}
				}
				// we need to check for C style comments
				int commentOffset;
				if (find_comment_start(text + i - 1, size - i + 1,
						commentOffset))
				{
					state = IF_ZERO_COMMENT;
					i += commentOffset + 1;
				}
				else
					leave = true;
			}
			break;

			case IF_ZERO_COMMENT:
			{
				proxy.SetColor(i - 1, kColorComment1);
				int commentEnd;
				if (find_comment_end(text + i - 1, size - i + 1, commentEnd)) {
					i += commentEnd + 1;
					state = IF_ZERO;
				} else
					leave = true;
			}
			break;

			default:	// error condition, gracefully leave the loop
				leave = true;
				break;
		}
	}
	state |= ifZeroCounter << STATE_SHIFT;
} /* ColorLine */
Пример #16
0
_EXPORT void ColorLine(CLanguageProxy& proxy, int32& state)
{
	const char *text = proxy.Text();
	int32 size = proxy.Size();
	char c;					// Current character
	int32 nxt = 0,			// Position after current character in text (i)
		beg = 0,			// (s)
		kws = 0,			//
		forceState = START,	//
		color,				//
		kwc;				// Keywordcode
	bool leave = false, esc = false, script = false, percent = false, style = false;

	proxy.SetColor(0, kColorText);

	if (size <= 0)
		return;

	script = (state >= JAVASCRIPT);
	percent = false;

#if DEBUG_PHP
	printf("#############################################################################\nColorLine(%s:%s)\n%s\n", DEB_StateName(state), script ? "IsScript" : "NoScript", text);
#endif

	while (!leave)
	{
		c = get_char(nxt, size, text);

		switch (state)
		{
			case START:
				DEB_PrintState(state, c);
				if (c == '<')
					state = TAG_START;
				else if (c == '&')
					state = SPECIAL;
				else if (c == 0 || c == '\n')
					leave = true;

				if ((leave || state != START) && beg < nxt)
				{
					proxy.SetColor(beg, kColorText);
					beg = nxt-1;
				}
				break;

			case TAG_START:
				DEB_PrintState(state, c);
				if (c == '/')
					state = TAG_KEYWORD_END;
				else if (c == '!')
				{
					state = COMMENT_DTD;
					forceState = START;
				}
				else if (c == '?' || c == '%')
				{
					proxy.SetColor(beg, kColorTag);
					beg = nxt;

					if (strncasecmp(text+beg, "php", 3) == 0)
					{
						proxy.SetColor(beg, kColorTag);
						beg = (nxt += 3);
					}

					state = PHP_SCRIPT;
					percent = (c == '%');
				}
				else if (isalpha(c))
				{
					proxy.SetColor(beg, kColorTag);
					beg = nxt-1;
					kws = proxy.Move(CASE_SENSITIVE_TAG ? c : tolower(c), 1);
					state = TAG_KEYWORD_START;
				}
				else if (c == 0 || c == '\n')
				{
					proxy.SetColor(beg, kColorTag);
					leave = true;
				}
				else if (!isspace(c))
				{
					nxt--;
					state = TAG;
				}
				break;

			case TAG_KEYWORD_END:
				DEB_PrintState(state, c);
				if (isalpha(c))
				{
					proxy.SetColor(beg, kColorTag);
					beg = nxt-1;
					kws = proxy.Move(CASE_SENSITIVE_TAG ? c : tolower(c), 1);
					state = TAG_KEYWORD_START;
				}
				else if (c == 0 || c == '\n')
				{
					proxy.SetColor(beg, kColorTag);
					leave = true;
				}
				else if (!isspace(c))
				{
					nxt--;
					state = TAG;
				}
				break;

			case TAG_KEYWORD_START:
				DEB_PrintState(state, c);
				if (!isalnum(c) && c != '-')
				{
					switch (kwc = proxy.IsKeyword(kws, kKwHtmlTag|kKwUsersets))
					{
						case kKwHtmlTag:  color = kColorTag;      break;
						case kKwUserset1: color = kColorUserSet1; break;
						case kKwUserset2: color = kColorUserSet2; break;
						case kKwUserset3: color = kColorUserSet3; break;
						case kKwUserset4: color = kColorUserSet4; break;
						default:          color = kColorText;     break;
					}
					proxy.SetColor(beg, color);
					DEB_PrintSetKw(state, kwc);

					if (text[beg-1] != '/')
					{
						if (strncasecmp(text+beg, "script", 6) == 0)
							script = true;
						else if (strncasecmp(text+beg, "style", 5) == 0)
							style = true;
					}
					state = TAG;
					beg = --nxt;
				}
				else if (kws)
					kws = proxy.Move(CASE_SENSITIVE_TAG ? c : tolower(c), kws);
				break;

			case TAG:
				DEB_PrintState(state, c);
				switch (c)
				{
					case 0:
					case '\n':
						proxy.SetColor(beg, kColorTag);
						leave = true;
						break;
					case '>':
						proxy.SetColor(beg, kColorTag);
						beg = nxt;
						proxy.SetColor(beg, kColorText);
						if (script)
							state = JAVASCRIPT;
						else if (style)
							state = STYLESHEET;
						else
							state = START;
						break;
					case '"':
						proxy.SetColor(beg, kColorTag);
						beg = nxt-1;
						state = TAG_STRING_DOUBLE_QUOTES;
						break;
					case '\'':
						proxy.SetColor(beg, kColorTag);
						beg = nxt-1;
						state = TAG_STRING_SINGLE_QUOTES;
						break;
					case '!':
						if (nxt == beg+2)
						{
							proxy.SetColor(beg, kColorTag);
							state = COMMENT_DTD;
							forceState = START;
						}
						break;
					default:
						if (isalpha(c))
						{
							proxy.SetColor(beg, kColorTag);
							beg = nxt-1;
							kws = proxy.Move(CASE_SENSITIVE_ATTR ? c : tolower(c), 1);
							state = TAG_ATTRIBUTE;
						}
						break;
				}
				break;

			case TAG_STRING_DOUBLE_QUOTES:
				DEB_PrintState(state, c);
				if (c == '"')
				{
					proxy.SetColor(beg, kColHtmlTagStringDoubleQuotes);
					beg = nxt;
					state = TAG;
				}
				else if (c == '\n' || c == 0)
				{
					proxy.SetColor(beg, kColHtmlTagStringDoubleQuotes);
					leave = true;
				}
				break;

			case TAG_STRING_SINGLE_QUOTES:
				DEB_PrintState(state, c);
				if (c == '\'')
				{
					proxy.SetColor(beg, kColHtmlTagStringSingleQuotes);
					beg = nxt;
					state = TAG;
				}
				else if (c == '\n' || c == 0)
				{
					proxy.SetColor(beg, kColHtmlTagStringSingleQuotes);
					leave = true;
				}
				break;

			case TAG_ATTRIBUTE:
				DEB_PrintState(state, c);
				if (!isalnum(c) && c != '-')
				{
					switch (kwc = proxy.IsKeyword(kws, kKwHtmlAttribute|kKwUsersets))
					{
						case kKwHtmlAttribute: color = kColHtmlAttribute; break;
						case kKwUserset1:      color = kColorUserSet1;    break;
						case kKwUserset2:      color = kColorUserSet2;    break;
						case kKwUserset3:      color = kColorUserSet3;    break;
						case kKwUserset4:      color = kColorUserSet4;    break;
						default:               color = kColorText;        break;
					}
					proxy.SetColor(beg, color);
					DEB_PrintSetKw(state, kwc);

					beg = --nxt;
					state = TAG;
				}
				else if (kws)
					kws = proxy.Move(CASE_SENSITIVE_ATTR ? c : tolower(c), kws);
				break;

			case SPECIAL:
				DEB_PrintState(state, c);
				if (c == 0 || c == '\n')
				{
					proxy.SetColor(beg, kColorText);
					state = START;
					leave = true;
				}
				else if (c == ';')
				{
					proxy.SetColor(beg, kColHtmlEntity);
					beg = nxt;
					state = START;
				}
				else if (isspace(c))
					state = START;
				break;

			case COMMENT_DTD:
				DEB_PrintState(state, c);
				if (c == '-' && text[nxt] == '-' && nxt == beg+3 && text[nxt-2] == '!' && text[nxt-3] == '<')
				{
					proxy.SetColor(beg, kColHtmlDtd);
					beg = nxt-1;
					state = COMMENT;
				}
				else if (c == '>')
				{
					proxy.SetColor(beg, kColHtmlDtd);
					beg = nxt;
					state = forceState;
				}
				else if (c == 0 || c == '\n')
				{
					proxy.SetColor(beg, kColHtmlDtd);
					leave = true;
				}
				break;

			case COMMENT:
				DEB_PrintState(state, c);
				if (beg == 0 && c == ':')
				{
					if (strncasecmp(text+nxt, "javascript", 10) == 0)
						forceState = JAVASCRIPT;
					else if (strncasecmp(text+nxt, "php", 3) == 0)
						forceState = PHP_SCRIPT;
				}
				else if (c == '-' && text[nxt] == '-')
				{
					proxy.SetColor(beg, kColHtmlComment);
					beg = ++nxt;
					state = COMMENT_DTD;
				}
				else if (c == 0 || c == '\n')
				{
					proxy.SetColor(beg, kColHtmlComment);
					leave = true;
				}
				break;

			case STYLESHEET:
				DEB_PrintState(state, c);

				if (c == '<' && text[nxt] == '/')
				{
					if (strncasecmp(text+nxt+1, "style", 5) == 0)
					{
						nxt++;
						state = TAG_START;
					}
				}
				else if (c == '/' && text[nxt] == '*')
					state = CSS_COMMENT;
//				else if (isalpha(c))
//				{
//					kws = proxy.Move(CASE_SENSITIVE_JS ? c : tolower(c), 1);
//					state = JS_IDENTIFIER;
//				}
				else if (c == '{')
					state = CSS_DEFINITION;
				else if (c == 0 || c == '\n')
					leave = true;

				if ((leave || state != STYLESHEET) && beg < nxt)
				{
					proxy.SetColor(beg, kColCssText);
					beg = nxt-1;
				}
				break;

			case CSS_COMMENT:
				DEB_PrintState(state, c);
				if ((beg == 0 || nxt > beg+1) && c == '*' && text[nxt] == '/')
				{
					proxy.SetColor(beg, kColJsComment);
					beg = nxt+1;
					state = STYLESHEET;
				}
				else if (c == 0 || c == '\n')
				{
					proxy.SetColor(beg, kColJsComment);
					leave = true;
				}
				break;

			case CSS_DEFINITION:
				DEB_PrintState(state, c);
				if (c == '}')
				{
					state = STYLESHEET;
				}
				else if (c == 0 || c == '\n')
					leave = true;
				break;

			case JAVASCRIPT:
				DEB_PrintState(state, c);
				script = false;

				if (c == '<' && strncasecmp(text+nxt, "!--", 3) == 0)
				{
					proxy.SetColor(beg, kColorTag);
					proxy.SetColor(nxt+1, kColorComment1);
					nxt += 3;
					beg = nxt;
				}
				else if (c == '<' && text[nxt] == '/')
				{
					if (strncasecmp(text+nxt+1, "script", 6) == 0)
					{
						nxt++;
						state = TAG_START;
					}
				}
				else if (c == '/' && text[nxt] == '*')
					state = JS_COMMENT_MULTI_LINE;
				else if (c == '/' && text[nxt] == '/')
					state = JS_COMMENT_SINGLE_LINE;
				else if (isalpha(c))
				{
					kws = proxy.Move(CASE_SENSITIVE_JS ? c : tolower(c), 1);
					state = JS_IDENTIFIER;
				}
				else if (c == '\'')
					state = JS_STRING_SINGLE_QUOTES;
				else if (c == '"')
					state = JS_STRING_DOUBLE_QUOTES;
				else if (c == 0 || c == '\n')
					leave = true;

				if ((leave || state != JAVASCRIPT) && beg < nxt)
				{
					proxy.SetColor(beg, kColorText);
					beg = nxt-1;
				}
				break;

			case JS_COMMENT_MULTI_LINE:
				DEB_PrintState(state, c);
				if ((beg == 0 || nxt > beg+1) && c == '*' && text[nxt] == '/')
				{
					proxy.SetColor(beg, kColJsComment);
					beg = nxt+1;
					state = JAVASCRIPT;
				}
				else if (c == 0 || c == '\n')
				{
					proxy.SetColor(beg, kColJsComment);
					leave = true;
				}
				break;

			case JS_COMMENT_SINGLE_LINE:
				DEB_PrintState(state, c);
				if (c == '-' && text[nxt] == '-')
				{
					proxy.SetColor(beg, kColJsCommentL);
					beg = nxt+1;
					state = TAG;
				}
				else if (c == '\n' || c == 0)
				{
					proxy.SetColor(beg, kColJsCommentL);
					state = JAVASCRIPT;
					leave = true;
				}
				break;

			case JS_IDENTIFIER:
				DEB_PrintState(state, c);
				if (!isalnum(c) && c != '_')
				{
					if (nxt > beg+1 && (kwc = proxy.IsKeyword(kws, kKwJs|kKwUsersets)) != 0)
					{
						switch (kwc)
						{
							case kKwJsLanguage:  color = kColorKeyword1;  break;
							case kKwJsConstants: color = kColorCharConst; break;
							case kKwUserset1:    color = kColorUserSet1;  break;
							case kKwUserset2:    color = kColorUserSet2;  break;
							case kKwUserset3:    color = kColorUserSet3;  break;
							case kKwUserset4:    color = kColorUserSet4;  break;
							default:             color = kColorText;      break;
						}
						proxy.SetColor(beg, color);
						DEB_PrintSetKw(state, kwc);
					}
					else
					{
						proxy.SetColor(beg, kColorText);
					}

					beg = --nxt;
					state = JAVASCRIPT;
				}
				else if (kws)
					kws = proxy.Move(CASE_SENSITIVE_JS ? c : tolower(c), kws);
				break;

			case JS_STRING_SINGLE_QUOTES:
			case JS_STRING_DOUBLE_QUOTES:
				DEB_PrintState(state, c);
				if (!esc &&
					((state == JS_STRING_SINGLE_QUOTES && c == '\'') ||
					(state == JS_STRING_DOUBLE_QUOTES && c == '"')))
				{
					proxy.SetColor(beg, (state == JS_STRING_SINGLE_QUOTES) ? kColJsStringSingleQuotes : kColJsStringDoubleQuotes);
					beg = nxt;
					state = JAVASCRIPT;
				}
				else if (c == '\n' || c == 0)
				{
					if (text[nxt-2] == '\\' && text[nxt-3] != '\\')
					{
						proxy.SetColor(beg, (state == JS_STRING_SINGLE_QUOTES) ? kColJsStringSingleQuotes : kColJsStringDoubleQuotes);
					}
					else
					{
						proxy.SetColor(beg, kColorText);
						state = JAVASCRIPT;
					}

					beg = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;

			case PHP_SCRIPT:
				DEB_PrintState(state, c);
				if (((c == '?' && !percent) || (c == '%' && percent)) && text[nxt] == '>')
				{
					proxy.SetColor(beg, kColorTag);
					beg = ++nxt;
					state = START;
				}
				else if (isalpha(c))
				{
					kws = proxy.Move(CASE_SENSITIVE_PHP ? c : tolower(c), 1);
					state = PHP_IDENTIFIER;
				}
				else if (c == '"')
					state = PHP_STRING_DOUBLE_QUOTES;
				else if (c == '\'')
					state = PHP_STRING_SINGLE_QUOTES;
				else if (c == '#' || (c == '/' && text[nxt] == '/'))
					state = PHP_COMMENT_SINGLE_LINE;
				else if (c == '/' && text[nxt] == '*')
					state = PHP_COMMENT_MULTI_LINE;
				else if (c == 0 || c == '\n')
					leave = true;

				if ((leave || state != START) && beg < nxt)
				{
					proxy.SetColor(beg, kColorText);
					beg = nxt-1;
				}
				break;

			case PHP_IDENTIFIER:
				if (!isalnum(c) && c != '_')
				{
					if (nxt > beg+1 && (kwc = proxy.IsKeyword(kws, kKwPhp|kKwUsersets)))
					{
						DEB_PrintState(state, c, "KWD");
						switch (kwc)
						{
							case kKwPhpLanguage:   color = kColPhpLanguage;  break;
							case kKwPhpFunctions:  color = kColPhpFunction;  break;
							case kKwPhpConstants:  color = kColPhpConstants; break;
							case kKwUserset1:      color = kColorUserSet1;   break;
							case kKwUserset2:      color = kColorUserSet2;   break;
							case kKwUserset3:      color = kColorUserSet3;   break;
							case kKwUserset4:      color = kColorUserSet4;   break;
							default:               color = kColorText;       break;
						}
						proxy.SetColor(beg, color);
						DEB_PrintSetKw(state, kwc);
					}
					else
					{
						DEB_PrintState(state, c, "TXT");
						proxy.SetColor(beg, kColorText);
					}

					beg = --nxt;
					state = PHP_SCRIPT;
				}
				else if (kws)
					DEB_PrintState(state, c, "MOV");
					kws = proxy.Move(CASE_SENSITIVE_PHP ? c : tolower(c), kws);
				break;

			case PHP_STRING_DOUBLE_QUOTES:
				DEB_PrintState(state, c);
				if (!esc && c == '"')
				{
					proxy.SetColor(beg, kColPhpStringDoubleQuotes);
					beg = nxt;
					state = PHP_SCRIPT;
				}
				else if (c == '\n' || c == 0)
				{
					proxy.SetColor(beg, kColPhpStringDoubleQuotes);
					beg = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;

			case PHP_STRING_SINGLE_QUOTES:
				DEB_PrintState(state, c);
				if (!esc && c == '\'')
				{
					proxy.SetColor(beg, kColPhpStringSingleQuotes);
					beg = nxt;
					state = PHP_SCRIPT;
				}
				else if (c == '\n' || c == 0)
				{
					proxy.SetColor(beg, kColPhpStringSingleQuotes);
					beg = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;

			case PHP_COMMENT_MULTI_LINE:
				DEB_PrintState(state, c);
				if ((beg == 0 || nxt > beg+1) && c == '*' && text[nxt] == '/')
				{
					proxy.SetColor(beg, kColPhpComment);
					beg = nxt+1;
					state = PHP_SCRIPT;
				}
				else if (c == 0 || c == '\n')
				{
					proxy.SetColor(beg, kColPhpComment);
					leave = true;
				}
				else if (((percent && c == '%') || (!percent && c == '?')) &&
					text[nxt] == '>')
				{
					proxy.SetColor(beg, kColPhpComment);
					beg = nxt-1;
					proxy.SetColor(beg, kColorTag);
					beg = ++nxt;
					state = START;
				}
				break;

			case PHP_COMMENT_SINGLE_LINE:
				DEB_PrintState(state, c);
				if (c == 0 || c == '\n')
				{
					proxy.SetColor(beg, kColPhpCommentL);
					state = PHP_SCRIPT;
					leave = true;
				}
				else if (((percent && c == '%') || (!percent && c == '?')) &&
					text[nxt] == '>')
				{
					proxy.SetColor(beg, kColPhpCommentL);
					beg = nxt-1;
					proxy.SetColor(beg, kColorTag);
					beg = ++nxt;
					state = START;
				}
				break;

			default:	// error condition, gracefully leave the loop
				leave = true;
				break;
		}
	}

#if DEBUG_PHP
	printf("--> (%s:%s)\n", DEB_StateName(state), script ? "IsScript" : "NoScript");
#endif

//	if (script)
//		state |= 0x8000;
//
//	if (percent)
//		state |= 0x4000;
} /* ColorLine */
Пример #17
0
_EXPORT bool Balance(CLanguageProxy& proxy, int32& start, int32& end)
{
	int32 langStart;
	Language lang = get_language_for_offset(proxy, start, langStart);
	const char *txt = proxy.Text();
	int32 size = proxy.Size();

	if (lang == kLanguageHtml)
	{
		bool in = false;

		if (start < 0 || start > end || end > size)
			return false;

		const char *st = txt + start;

		while (txt < st)
		{
			const char *t = in ? skip_in(txt + 1) : skip_out(txt + 1);
			in = !in;

			if (*t && st < t)
			{
				start = txt - proxy.Text() + 1;
				end = t - proxy.Text();
				return true;
			}

			txt = t;
		}
	}
	else
	{
		if (start < 0 || start > end || end > size)
			return false;

		const char *et(txt + end);
		const char *st(txt + langStart);

		std::stack<int32> bls, sbls, pls;

		while (*txt && txt < et)
		{
			switch (*txt)
			{
				case '{':	bls.push(txt - st);				break;
				case '[':	sbls.push(txt - st);			break;
				case '(':	pls.push(txt - st);				break;
				case '}':	if (!bls.empty()) bls.pop();	break;
				case ']':	if (!sbls.empty()) sbls.pop();	break;
				case ')':	if (!pls.empty()) pls.pop();	break;
			}
			txt = skip(txt + 1);
		}

		char ec = 0, oc = 0;
		std::stack<int32> *s = 0;

		int32 db, dsb, dp;

		db = bls.empty() ? -1 : start - bls.top();
		dsb = sbls.empty() ? -1 : start - sbls.top();
		dp = pls.empty() ? -1 : start - pls.top();

		if (db < 0 && dsb < 0 && dp < 0)
			return false;

		if (db >= 0 && (dsb < 0 || db < dsb) && (dp < 0 || db < dp))
		{
			oc = '{';
			ec = '}';
			s = &bls;
		}

		if (dsb >= 0 && (db < 0 || dsb < db) && (dp < 0 || dsb < dp))
		{
			oc= '[';
			ec = ']';
			s = &sbls;
		}

		if (dp >= 0 && (dsb < 0 || dp < dsb) && (db < 0 || dp < db))
		{
			oc = '(';
			ec = ')';
			s = &pls;
		}

		if (ec)
		{
			int32 l = 1;

			while (*txt)
			{
				if (*txt == ec)
				{
					if (--l == 0)
					{
						start = s->top() + 1 + langStart;
						end = txt - st + langStart;
						return true;
					}
					if (!s->empty()) s->pop();
				}
				else if (*txt == oc)
				{
					l++;
					s->push(0);
				}

				txt = skip(txt + 1);
			}
		}
	}

	return false;
} /* Balance */
Пример #18
0
Language get_language_for_offset(const CLanguageProxy& proxy, int32 inOffset, int32& outLangStart)
{
	const char *text = proxy.Text();
	int32 size = proxy.Size(), forceState = START;

	if (inOffset > size)
		inOffset = size;

	char c = 0;
	int32 i = 0, bo = 0, s = 0;
	bool leave = false, esc = false, script = false, percent = false;
	int state = 0;

	while (i < inOffset)
	{
		c = get_char(i, size, text);

		switch (state)
		{
			case START:
				if (c == '<')
					state = TAG_START;
				else if (c == '&')
					state = SPECIAL;
				else if (c == 0 || c == '\n')
					leave = true;

				if ((leave || state != START) && s < i)
					s = i - 1;
				break;

			case TAG_START:
				if (c == '/')
					state = TAG_KEYWORD_END;
				else if (c == '!')
				{
					state = COMMENT_DTD;
					forceState = START;
				}
				else if (c == '?' || c == '%')
				{
					s = i;
					outLangStart = s;

					if (strncasecmp(text + s, "php", 3) == 0)
						s = (i += 3);

					state = PHP_SCRIPT;
					percent = (c == '%');
				}
				else if (isalpha(c))
				{
					s = i - 1;
					state = TAG_KEYWORD_START;
				}
				else if (c == 0 || c == '\n')
				{
					leave = true;
				}
				else if (!isspace(c))
				{
					--i;
					state = TAG;
				}
				break;

			case TAG_KEYWORD_END:
				if (isalpha(c))
				{
					s = i - 1;
					state = TAG_KEYWORD_START;
				}
				else if (c == 0 || c == '\n')
				{
					leave = true;
				}
				else if (!isspace(c))
				{
					--i;
					state = TAG;
				}
				break;

			case TAG_KEYWORD_START:
				if (!isalnum(c) && c != '-')
				{
					if (strncasecmp(text + s, "script", 6) == 0 && text[s - 1] != '/')
						script = true;

					state = TAG;
					s = --i;
				}
				break;

			case TAG:
				switch (c)
				{
					case 0:
					case '\n':
						leave = true;
						break;
					case '>':
						s = i;
						if (script)
						{
							outLangStart = s;
							state = JAVASCRIPT;
						}
						else
							state = START;
						break;
					case '"':
						s = i - 1;
						state = TAG_STRING_DOUBLE_QUOTES;
						break;
					case '\'':
						s = i - 1;
						state = TAG_STRING_SINGLE_QUOTES;
						break;
					case '!':
						if (i == s + 2)
						{
							state = COMMENT_DTD;
							forceState = START;
						}
						break;
					default:
						if (isalpha(c))
						{
							s = i - 1;
							state = TAG_ATTRIBUTE;
						}
						break;
				}
				break;

			case TAG_STRING_DOUBLE_QUOTES:
				if (c == '"')
				{
					s = i;
					state = TAG;
				}
				else if (c == '\n' || c == 0)
					leave = true;
				break;

			case TAG_STRING_SINGLE_QUOTES:
				if (c == '\'')
				{
					s = i;
					state = TAG;
				}
				else if (c == '\n' || c == 0)
					leave = true;
				break;

			case TAG_ATTRIBUTE:
				if (!isalnum(c) && c != '-')
				{
					s = --i;
					state = TAG;
				}
				break;

			case SPECIAL:
				if (c == 0 || c == '\n')
				{
					state = START;
					leave = true;
				}
				else if (c == ';')
				{
					s = i;
					state = START;
				}
				else if (isspace(c))
					state = START;
				break;

			case COMMENT_DTD:
				if (c == '-' && text[i] == '-' && i == s + 3 && text[i - 2] == '!' && text[i - 3] == '<')
				{
					s = i - 1;
					forceState = START;
					state = COMMENT;
				}
				else if (c == '>')
				{
					s = i;
					state = forceState;
				}
				else if (c == 0 || c == '\n')
				{
					leave = true;
				}
				break;

			case COMMENT:
				if (c == ':')
				{
					if (strncasecmp(text, "JavaScript", 10) == 0)
						forceState = JAVASCRIPT;
					else if (strncasecmp(text, "PHP", 3) == 0)
						forceState = PHP_SCRIPT;
				}
				else if (c == '-' && text[i] == '-')
				{
					s = ++i;
					state = COMMENT_DTD;
				}
				else if (c == 0 || c == '\n')
				{
					leave = true;
				}
				break;

			case JAVASCRIPT:
				script = false;

				if (c == '<' && strncasecmp(text + i, "!--", 3) == 0)
				{
					i += 3;
					s = i;
				}
				else if (c == '<' && text[i] == '/')
				{
					if (strncasecmp(text + i + 1, "script", 6) == 0)
					{
						i--;
						state = TAG_START;
						outLangStart = i - 1;
					}
				}
				else if (c == '/' && text[i] == '*')
					state = JS_COMMENT_MULTI_LINE;
				else if (c == '/' && text[i] == '/')
					state = JS_COMMENT_SINGLE_LINE;
				else if (isalpha(c))
					state = JS_IDENTIFIER;
				else if (c == '\'')
					state = JS_STRING_SINGLE_QUOTES;
				else if (c == '"')
					state = JS_STRING_DOUBLE_QUOTES;
				else if (c == 0 || c == '\n')
					leave = true;

				if ((leave || state != JAVASCRIPT) && s < i)
					s = i - 1;
				break;

			case JS_COMMENT_MULTI_LINE:
				if ((s == 0 || i > s + 1) && c == '*' && text[i] == '/')
				{
					s = i + 1;
					state = JAVASCRIPT;
				}
				else if (c == 0 || c == '\n')
					leave = true;
				break;

			case JS_COMMENT_SINGLE_LINE:
				if (c == '-' && text[i] == '-')
				{
					s = i + 1;
					state = TAG;
					outLangStart = s;
				}
				else if (c == '\n' || c == 0)
				{
					state = JAVASCRIPT;
					leave = true;
				}
				break;

			case JS_IDENTIFIER:
				if (!isalnum(c) && c != '_')
				{
					s = --i;
					state = JAVASCRIPT;
				}
				break;

			case JS_STRING_SINGLE_QUOTES:
			case JS_STRING_DOUBLE_QUOTES:
				if (!esc &&
					((state == JS_STRING_SINGLE_QUOTES && c == '\'') ||
					(state == JS_STRING_DOUBLE_QUOTES && c == '"')))
				{
					s = i;
					state = JAVASCRIPT;
				}
				else if (c == '\n' || c == 0)
				{
					if (!(text[i - 2] == '\\' && text[i - 3] != '\\'))
						state = JAVASCRIPT;

					s = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;

			case PHP_SCRIPT:
				if (((c == '?' && !percent) || (c == '%' && percent)) &&
					text[i] == '>')
				{
					s = ++i;
					state = START;
					outLangStart = s;
				}
				else if (isalpha(c))
				{
					state = PHP_IDENTIFIER;
				}
				else if (c == '"')
					state = PHP_STRING_DOUBLE_QUOTES;
				else if (c == '\'')
					state = PHP_STRING_SINGLE_QUOTES;
				else if (c == '#' || (c == '/' && text[i] == '/'))
					state = PHP_COMMENT_SINGLE_LINE;
				else if (c == '/' && text[i] == '*')
					state = PHP_COMMENT_MULTI_LINE;
				else if (c == 0 || c == '\n')
					leave = true;

				if ((leave || state != START) && s < i)
					s = i - 1;
				break;

			case PHP_IDENTIFIER:
				if (!isalnum(c) && c != '_')
				{
					s = --i;
					state = PHP_SCRIPT;
				}
				break;

			case PHP_STRING_DOUBLE_QUOTES:
				if (!esc && c == '"')
				{
					s = i;
					state = PHP_SCRIPT;
				}
				else if (c == '\n' || c == 0)
				{
					s = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;

			case PHP_STRING_SINGLE_QUOTES:
				if (!esc && c == '\'')
				{
					s = i;
					state = PHP_SCRIPT;
				}
				else if (c == '\n' || c == 0)
				{
					s = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;

			case PHP_COMMENT_MULTI_LINE:
				if ((s == 0 || i > s + 1) && c == '*' && text[i] == '/')
				{
					s = i + 1;
					state = PHP_SCRIPT;
				}
				else if (c == 0 || c == '\n')
				{
					leave = true;
				}
				else if (((percent && c == '%') || (!percent && c == '?')) &&
					text[i] == '>')
				{
					s = i - 1;
					s = ++i;
					state = START;
					outLangStart = s;
				}
				break;

			case PHP_COMMENT_SINGLE_LINE:
				if (c == 0 || c == '\n')
				{
					state = PHP_SCRIPT;
					leave = true;
				}
				else if (((percent && c == '%') || (!percent && c == '?')) &&
					text[i] == '>')
				{
					s = i - 1;
					s = ++i;
					state = START;
					outLangStart = s;
				}
				break;

			default:	// error condition, gracefully leave the loop
				leave = true;
				break;
		}

		if (leave)
		{
			while (c != '\n' && c != 0 && i < inOffset)
				c = get_char(i, size, text);

			s = i;
			leave = false;
		}
	}

	if (state >= JAVASCRIPT && state <= JS_STRING_DOUBLE_QUOTES)
		return kLanguageJs;
	else if (state >= PHP_SCRIPT && state <= PHP_STRING_SINGLE_QUOTES)
		return kLanguagePhp;
	else
		return kLanguageHtml;
} /* get_language_for_offset */
void ScanForFunctions(CLanguageProxy& proxy)
{
	bool sorted = proxy.Sorted();
	PopupList lstHeadings, lstAnchors, lstPhpFunctions, lstPhpClasses, lstJsFunctions, lstJsClasses;

	const char *text = proxy.Text(), *max = text + proxy.Size();
	if (*max != 0)
		return;

	if (strncasecmp(text, "<!--:javascript", 15) == 0)
		text = JavaScript(text, lstJsFunctions, lstJsClasses, sorted);
	else if (strncasecmp(text, "<!--:php", 8) == 0)
		text = PhpScript(text + 11, lstPhpFunctions, lstPhpClasses, sorted);

	while (*text && text < max)
	{
		text = skip(text, '<');
		text = skip_whitespace(text);
		
		switch (toupper(*text))
		{
			case '?':
				text = PhpScript(text, lstPhpFunctions, lstPhpClasses, sorted);
				break;

			case 'A':
				if (isspace(*++text))
					text = anchor(text, proxy, lstAnchors, sorted);
				else
					text = skip_nc(text, '>');
				break;

			case 'L':
				if (strncasecmp(text, "LINK", 4) == 0)
					text = anchor(text + 4, proxy, lstAnchors, sorted);
				else
					text = skip_nc(text, '>');
				break;

			case 'H':
				if (*++text >= '1' && *text <= '6')
				{
					text = heading(text, lstHeadings, sorted);
				}
				else
					text = skip_nc(text, '>');
				break;

			case 'S':
				if (strncasecmp(text, "SCRIPT", 6) == 0)
					text = JavaScript(text, lstJsFunctions, lstJsClasses, sorted);
				break;

			default:
				text = skip_nc(text + 1, '>');
				break;
		}
	}

	add_to_popup("PHP-Classes",   lstPhpClasses,   proxy);
	add_to_popup("PHP-Functions", lstPhpFunctions, proxy);
	add_to_popup("JS-Classes",    lstJsClasses,    proxy);
	add_to_popup("JS-Functions",  lstJsFunctions,  proxy);
	add_to_popup("HTML-Anchors",  lstAnchors,      proxy);
	add_to_popup("HTML-Headings", lstHeadings,     proxy);
} /* ScanForFunctions */
Пример #20
0
_EXPORT void ColorLine(CLanguageProxy& proxy, int32& state)
{
	const char *text = proxy.Text();
	int32 size = proxy.Size();
	char c;
	int32 i = 0, s = 0, kws = 0;
	bool leave = false, esc = false;

	proxy.SetColor(0, kColorText);

	if (size <= 0)
		return;

	while (!leave)
	{
		GETCHAR;

		switch (state)
		{
			case START:
				if (c == '<')
					state = TAG;
				else if (c == '&')
					state = SPECIAL;
				else if (c == 0 || c == '\n')
					leave = true;

				if ((leave || state != START) && s < i)
				{
					proxy.SetColor(s, kColorText);
					s = i - 1;
				}
				break;

			case TAG:
			case JSTAG:
				switch (c)
				{
					case 0:
					case '\n':
						proxy.SetColor(s, kColorTag);
						leave = true;
						break;
					case '>':
						proxy.SetColor(s, kColorTag);
						s = i;
						proxy.SetColor(s, kColorText);
						state--;	// START
						break;
					case '"':
						proxy.SetColor(s, kColorTag);
						s = i - 1;
						state++;	// TAGSTRING1
						break;
					case '\'':
						proxy.SetColor(s, kColorTag);
						s = i - 1;
						state += 2;	// TAGSTRING2
						break;
					case '!':
						if (i == s + 2)
						{
							proxy.SetColor(s, kColorTag);
							state += 5;	// COMMENT_DTD
						}
						break;
					default:
						if (isalpha(c))
						{
							proxy.SetColor(s, kColorTag);
							s = i - 1;
							kws = proxy.Move(tolower(c), 1);
							state += 3;	// TAGKEYWORD
						}
						break;
				}
				break;

			case TAGSTRING1:
			case JSTAGSTRING1:
				if (c == '"')
				{
					proxy.SetColor(s, kColorString2);
					s = i;
					state--; // TAG
				}
				else if (c == '\n' || c == 0)
				{
					proxy.SetColor(s, kColorString2);
					leave = true;
				}
				break;

			case TAGSTRING2:
			case JSTAGSTRING2:
				if (c == '\'')
				{
					proxy.SetColor(s, kColorString2);
					s = i;
					state -= 2; // TAG
				}
				else if (c == '\n' || c == 0)
				{
					proxy.SetColor(s, kColorString2);
					leave = true;
				}
				break;

			case TAGKEYWORD:
			case JSTAGKEYWORD:
				if (! isalnum(c))
				{
					switch (proxy.IsKeyword(kws))
					{
						case 1:	 proxy.SetColor(s, kColorKeyword1); break;
						case 2:	 proxy.SetColor(s, kColorUserSet1); break;
						case 3:	 proxy.SetColor(s, kColorUserSet2); break;
						case 4:	 proxy.SetColor(s, kColorUserSet3); break;
						case 5:	 proxy.SetColor(s, kColorUserSet4); break;
						default: proxy.SetColor(s, kColorTag);      break;
					}

					if (strncasecmp(text + s, "SCRIPT", 6) == 0)
					{
						if (state == TAGKEYWORD)
							state += JAVASCRIPT;
						else
							state -= JAVASCRIPT;
					}

					s = --i;
					state -= 3;	// TAG
				}
				else if (kws)
					kws = proxy.Move(tolower(c), kws);
				break;

			case SPECIAL:
			case JSSPECIAL:
				if (c == 0 || c == '\n')
				{
					proxy.SetColor(s, kColorText);
					state = START;
					leave = true;
				}
				else if (c == ';')
				{
					proxy.SetColor(s, kColorCharConst);
					s = i;
					state = START;
				}
				else if (isspace(c))
					state = START;
				break;

			case COMMENT_DTD:
			case JSCOMMENT_DTD:
				if (c == '-' && text[i] == '-' && i == s + 3 && text[i - 2] == '!' && text[i - 3] == '<')
				{
					proxy.SetColor(s, kColorTag);
					s = i - 1;
					state++;
				}
				else if (c == '>')
				{
					proxy.SetColor(s, kColorTag);
					s = i;
					state -= 5;
				}
				else if (c == 0 || c == '\n')
				{
					proxy.SetColor(s, kColorTag);
					leave = true;
				}
				break;

			case COMMENT:
				if (c == '-' && text[i] == '-')
				{
					proxy.SetColor(s, kColorComment1);
					s = ++i;
					state = COMMENT_DTD;
				}
				else if (c == 0 || c == '\n')
				{
					proxy.SetColor(s, kColorComment1);
					leave = true;
				}
				break;

			case JSCOMMENT:
				state = JAVASCRIPT;
				i--;
				break;

			case JAVASCRIPT:
				if (c == '<')
				{
					if (strncasecmp(text + i, "/script", 7) == 0)
						state = JSTAG;
				}
//				{
//					if (strncmp(text + i, "!--", 3))
//						state = JSTAG;
//				}
				else if (c == '/' && text[i] == '*')
					state = JS_COMMENT;
				else if (c == '/' && text[i] == '/')
					state = JS_LCOMMENT;
				else if (isalpha(c))
				{
					kws = proxy.Move(tolower(c), 1);
					state = JS_IDENT;
				}
				else if (c == '\'')
					state = JS_STRING1;
				else if (c == '"')
					state = JS_STRING2;
				else if (c == 0 || c == '\n')
					leave = true;

				if ((leave || state != JAVASCRIPT) && s < i)
				{
					proxy.SetColor(s, kColorText);
					s = i - 1;
				}
				break;

			case JS_COMMENT:
				if ((s == 0 || i > s + 1) && c == '*' && text[i] == '/')
				{
					proxy.SetColor(s, kColorComment1);
					s = i + 1;
					state = JAVASCRIPT;
				}
				else if (c == 0 || c == '\n')
				{
					proxy.SetColor(s, kColorComment1);
					leave = true;
				}
				break;

			case JS_LCOMMENT:
				proxy.SetColor(s, kColorComment1);
				leave = true;
				if (text[size - 1] == '\n')
					state = JAVASCRIPT;
				break;

			case JS_IDENT:
				if (!isalnum(c) && c != '_' && c != '.')
				{
					int32 kwc;

					if (i > s + 1 && (kwc = proxy.IsKeyword(kws)) != 0)
					{
						switch (kwc)
						{
							case 1:
							case 6:	proxy.SetColor(s, kColorKeyword1); break;
							case 2:	proxy.SetColor(s, kColorUserSet1); break;
							case 3:	proxy.SetColor(s, kColorUserSet2); break;
							case 4:	proxy.SetColor(s, kColorUserSet3); break;
							case 5:	proxy.SetColor(s, kColorUserSet4); break;
//							default:	ASSERT(false);
						}
					}
					else
					{
						proxy.SetColor(s, kColorText);
					}

					s = --i;
					state = JAVASCRIPT;
				}
				else if (kws)
					kws = proxy.Move((int)(unsigned char)c, kws);
				break;

			case JS_STRING1:
			case JS_STRING2:
				if (!esc &&
					((state == JS_STRING1 && c == '\'') ||
					(state == JS_STRING2 && c == '"')))
				{
					proxy.SetColor(s, kColorString1);
					s = i;
					state = JAVASCRIPT;
				}
				else if (c == '\n' || c == 0)
				{
					if (text[i - 2] == '\\' && text[i - 3] != '\\')
					{
						proxy.SetColor(s, kColorString1);
					}
					else
					{
						proxy.SetColor(s, kColorText);
						state = JAVASCRIPT;
					}

					s = size;
					leave = true;
				}
				else
					esc = !esc && (c == '\\');
				break;

			default:	// error condition, gracefully leave the loop
				leave = true;
				break;
		}
	}
} /* ColorLine */