// Copyright (c) Gate17 System www.gate17.net by Marc Krisnanto. All rights reserved.

function Highlight (lang, s)
{
	lang = lang.toLowerCase ();
	if (lang == "html" || lang == "xml" || lang == "markup")
		return Highlight._html (s);

	if (lang == "plain")
		return Highlight._esc (s);

	var kwds = Highlight.KWDS [lang];
	var spec = Highlight.SPEC [lang];

	if (!kwds)
		kwds = "";

	if (!spec)
		spec = "";

	var r = Highlight._tokens (s);
	var h = "";

	for (var i = 0; i < r.length; i++)
	{
		var q = r[i];
		var v = Highlight._esc (q[1]);
		switch (q[0])
		{
			case 1: /*string*/
				v = '<span style="color:#CC0000">' + v + '</span>';
				break;

			case 2: /*number*/
				v = '<span style="color:#0000CC">' + v + '</span>';
				break;

			case 3: /*name*/
				if (Highlight._is (kwds, v))
					v = '<b>' + v + '</b>';
				else if (Highlight._is (spec, v))
					v = '<span style="color:#999900">' + v + '</span>';
				break;

			case 4: /*comment*/
				v = '<span style="color:#666666">' + v + '</span>';
				break;

			case 5: /*long string*/
				v = '<span style="color:#003366">' + v + '</span>';
				break;

			case 6: /*operator*/
				v = '<span style="color:#666666">' + v + '</span>';
				break;
		}
		r[i] = v;
	}
	return r.join("");
}

Highlight.OPER = "~!@$%^&*()-+=|\\{}[];:<,>.?/";
Highlight.NAME = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Highlight.NAMX = "abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Highlight.BLNK = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x00";
Highlight.NMBR = "0123456789";
Highlight.NMBX = "0123456789ABCDEFabcdef.x_";
Highlight.HTAG = "/!?-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

Highlight.KWDS =
{
	js     : " new this function var const if else while do switch case break continue return ",
	qu     : " as do if in is of or and are end for not sub try use var xor case each elif else enum loop pass redo with alias break catch class const local super throw until while yield assert atomic ensure import lambda pragma return static struct switch unless default finally buffered continue universe ",
	java   : " abstract break case catch class continue default do else extends final finally for goto if implements import interface native package private protected public return switch throw throws try while ",
	python : " and as assert break class continue def del elif else except exec finally for from global if import in is lambda not or pass print raise return try while yield xor ",
	c      : " asm break case catch class const_cast continue default delete do dynamic_cast else explicit export false for friend goto if mutable namespace operator private protected public reinterpret_cast return static_cast switch template this throw try true typeid typename using virtual while "
};


Highlight.SPEC =
{
	js     : " this true false null prototype document window ",
	qu     : " me nil infp infn null self true false __end__ __doc__ __argc__ __line__ __file__ __here__ __swap__ __test__ __frame__ __abstract __accumulator __args __auto __dynamic __extern __final __generator __mixin __once __ondemand __package __public __pure __private __readwrite __readonly __std __sync __transient __uncatchable __unsafe ",
	java   : " this null ",
	python : " None self True False ",
	c      : " sizeof typeof NULL "
};


Highlight._esc = function (s)
{
	return s.replace (/</g, "&lt;").replace (/>/g, "&gt;").replace (/\n/g, "<br>").replace (/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;").replace (/\s/g, "&nbsp;");
};


Highlight._is = function (a, s)
{
	return a.indexOf (" " + s + " ") >= 0;
};


Highlight._tokens = function (s)
{
	var r = [];
	var i = 0;
	var n = s.length;
	
	while (i < n)
	{
		var k;
		var j = i;
		var c = s.charAt (i++);
		if (Highlight.BLNK.indexOf (c) >= 0)
		{
			while (i < n)
			{
				c = s.charAt (i);
				if (Highlight.BLNK.indexOf (c) < 0)
					break;
				i++;
			}
			k = 0;
		}
		else if (c == "`" && s.charAt (i) == "`" && s.charAt (i + 1) == "`")
		{
			while (i < n)
			{
				c = s.charAt (i++);
				if (c == "`" && s.charAt (i) == "`" && s.charAt (i + 1) == "`")
				{
					i += 2;
					break;
				}
			}
			k = 4;
		}
		else if (c == '"' && s.charAt (i) == '"' && s.charAt (i + 1) == '"')
		{
			while (i < n)
			{
				c = s.charAt (i++);
				if (c == '"' && s.charAt (i) == '"' && s.charAt (i + 1) == '"')
				{
					i += 2;
					break;
				}
			}
			k = 5;
		}
		else if (c == '"' || c == "'" || c == '`')
		{
			var q = c;
			while (i < n)
			{
				c = s.charAt (i++);
				if (c == "\\" && q != '`')
				{
					i++;
					continue;
				}
				if (c == q)
					break;
			}
			k = 1;
		}
		else if (Highlight.NMBR.indexOf (c) >= 0)
		{
			while (i < n)
			{
				c = s.charAt (i);
				if (Highlight.NMBX.indexOf (c) < 0)
					break;
				i++;
			}
			k = 2;
		}
		else if (Highlight.NAME.indexOf (c) >= 0)
		{
			while (i < n)
			{
				c = s.charAt (i);
				if (Highlight.NAMX.indexOf (c) < 0)
					break;
				i++;
			}
			k = 3;
		}
		else if (c == "/" && s.charAt (i) == "*")
		{
			i++;
			while (i < n)
			{
				c = s.charAt (i++);
				if (c == "*" && s.charAt (i) == "/")
				{
					i++;
					break;
				}
			}
			k = 4;
		}
		else if (c == "#")
		{
			while (i < n)
			{
				c = s.charAt (i);
				if (c == "\n")
					break;
				i++;
			}
			k = 4;
		}
		else if (Highlight.OPER.indexOf (c) >= 0)
		{
			while (i < n)
			{
				c = s.charAt (i);
				if (Highlight.OPER.indexOf (c) < 0)
					break;
				i++;
			}
			k = 6;
		}
		else
		{
			j = i++;
			k = 0;
		}
		r.push ([k, s.substr (j, i - j)]);
	}
	return r;
};


Highlight._html = function  (s)
{
	function esc (c)
	{
		switch (c)
		{
			case "<" : return "&lt;";
			case ">" : return "&gt;";
			case " " : return "&nbsp;";
			case "\t": return "&nbsp;&nbsp;&nbsp;&nbsp;";
			case "\n": return "<br>";
		}
		return c;
	}

	var r = "";
	var i = 0, n = s.length;
	var k = false;
	var q, c;

	while (i < n)
	{
		c = s.charAt (i);

		if (c == "<" && !k)
		{
			c = (i < n - 1) ? s.charAt (i + 1) : '';
			if (c && Highlight.HTAG.indexOf (c) >= 0)
			{
				k = true;
				r += '<b>&lt;' + c;
				i += 2;
				while (i < n)
				{
					c = s.charAt (i);
					if (Highlight.HTAG.indexOf (c) < 0)
						break;
					r += c;
					i++;
				}
				r += '</b><span style="color:#666600">';
				continue;
			}
		}

		if (k)
		{
			if (c == "\"")
			{
				q = true;
				r += '<span style="color:#006666">"';
				i++;
				while (i < n)
				{
					c = s.charAt (i++);
					if (c == "\"")
					{
						q = false;
						r += '"</span>';
						break;
					}
					r += esc (c);
				}
				if (q)
					r += '</span>';
				continue;
			}

			if (c == ">")
			{
				r += '</span><b>&gt;</b>';
				k = false;
				i++;
				continue;
			}

			if (c == "/" && s.charAt (i + 1) == ">")
			{
				r += '</span><b>/&gt;</b>';
				k = false;
				i += 2;
				continue;
			}

			if (c == "?" && s.charAt (i + 1) == ">")
			{
				r += '</span><b>?&gt;</b>';
				k = false;
				i += 2;
				continue;
			}
		}

		i++;
		r += esc (c);
	}
	return r;
};

