/* CodeColor, version 0.01
 * (c) 2006 Vladimir Morozov vmoroz@hotmail.com
 *
 * CodeColor is freely distributable under the terms of an MIT-style license.
 * For details, see the CodeColor web site: http://notebar.com/codecolor/
 */
function HighlightCode()
{
var keywords = {
	cs: "abstract|as"
		+ "|base|bool|break|byte"
		+ "|case|catch|char|checked|class|const|continue"
		+ "|decimal|default|delegate|do|double"
		+ "|else|enum|event|explicit|extern"
		+ "|false|finally|fixed|float|for|foreach"
		+ "|goto"
		+ "|if|implicit|in|int|interface|internal|is"
		+ "|lock|long"
		+ "|namespace|new|null"
		+ "|object|operator|out|override"
		+ "|params|private|protected|public"
		+ "|readonly|ref|return"
		+ "|sbyte|sealed|short|sizeof|stackalloc|static|string|struct|switch"
		+ "|this|throw|true|try|typeof"
		+ "|uint|ulong|unchecked|unsafe|ushort|using"
		+ "|virtual|void|volatile"
		+ "|while",
	csPP: "define|undef|if|elif|else|endif|line|error|warning|region|endregion",
	vb: "AddHandler|AddressOf|Alias|And|AndAlso|As"
		+ "|Boolean|ByRef|Byte|ByVal"
		+ "|Call|Case|Catch|CBool|CByte|CChar|CDate|CDec|CDbl|Char"
		+ "|CInt|Class|CLng|CObj|Const|Continue|CSByte|CShort|CSng|CStr|CType|CUInt|CULng|CUShort"
		+ "|Date|Decimal|Declare|Default|Delegate|Dim|DirectCast|Do|Double"
		+ "|Each|Else|ElseIf|End|EndIf|Enum|Erase|Error|Event|Exit"
		+ "|False|Finally|For|Friend|Function"
		+ "|Get|GetType|Global|GoSub|GoTo"
		+ "|Handles"
		+ "|If|Implements|Imports|In|Inherits|Integer|Interface|Is|IsNot"
		+ "|Let|Lib|Like|Long|Loop"
		+ "|Me|Mod|Module|MustInherit|MustOverride|MyBase|MyClass"
		+ "|Namespace|Narrowing|New|Next|Not|Nothing|NotInheritable|NotOverridable"
		+ "|Object|Of|On|Operator|Option|Optional|Or|OrElse|Overloads|Overridable|Overrides"
		+ "|ParamArray|Partial|Private|Property|Protected|Public"
		+ "|RaiseEvent|ReadOnly|ReDim|REM|RemoveHandler|Resume|Return"
		+ "|SByte|Select|Set|Shadows|Shared|Short|Single|Static|Step|Stop|String|Structure|Sub|SyncLock"
		+ "|Then|Throw|To|True|Try|TryCast|TypeOf"
		+ "|Variant"
		+ "|Wend"
		+ "|UInteger|ULong|UShort|Using"
		+ "|When|While|Widening|With|WithEvents|WriteOnly"
		+ "|Xor",
	js: "abstract"
		+ "|boolean|break|byte"
		+ "|case|catch|char|class|const|continue"
		+ "|debugger|default|delete|do|double"
		+ "|else|enum|export|extends"
		+ "|false|final|finally|float|for|function"
		+ "|goto"
		+ "|if|implements|import|in|instanceof|int|interface"
		+ "|long"
		+ "|native|new|null"
		+ "|package|private|protected|public"
		+ "|return"
		+ "|short|static|super|switch|synchronized"
		+ "|this|throw|throws|transient|true|try|typeof"
		+ "|var|void|volatile"
		+ "|while|with",
	url: "https|http|ftp|mailto|ms-help|ldaps|ldap|file|gopher|news|nntp|telnet|wais|prospero"
};

function Text(s)
{
	return s.replace(/(\-|\+|\*|\?|\(|\)|\[|\]|\\|\$|\^|\!)/g, "\\$1");
}

var contexts = {
	csCode: {style:"code", rules:[
		{style:"comment", pattern:Text("/*"), end:Text("*/")},
		{style:"xmlDocTag", pattern:"///", end:"\n", jump:"xmlDocComment"},
		{style:"comment", pattern:"//", end:"\n"},
		{style:"preprocessorKW", pattern:"#[ \\t]*?\\b(?:" + keywords.csPP + ")\\b", end:"\n", jump:"csPP"},
		{style:"string", pattern:'"(?:[^\\n"\\\\]|\\\\[^\\n])*?"'},
		{style:"string", pattern:"'(?:[^\\n'\\\\]|\\\\[^\\n])*?'"},
		{style:"stringCSharpAt", pattern:'@"(?:[^"]|"")*"'},
		{style:"number", pattern:"0[xX][0-9a-fA-F]+(?:[uU][lL]?|[lL][uU])?"},
		{style:"number", pattern:"\\d*\\.(?:\\d+[eE][+-]?\\d+)?[fFdDmM]?"},
		{style:"number", pattern:"\\d+[eE][+-]?\\d+[fFdDmM]?"},
		{style:"number", pattern:"\\d+[fFdDmM]"},
		{style:"number", pattern:"\\d+(?:[uU][lL]?|[lL][uU])?"},
		{style:"operator", pattern:"(?:&lt;|&gt;|&amp;|[-+*/%&|^!~={}\\[\\]().,:;])+"},
		{style:"identifier", pattern:"@[_a-zA-Z]\\w*"},
		{style:"keyword", pattern:"\\b(?:" + keywords.cs + ")\\b"},
		{style:"identifier", pattern:"[_a-zA-Z]\\w*"}
	]},
	csPP: {style:"code"},
	jsCode: {style:"code", rules:[
		{style:"comment", pattern:Text("/*"), end:Text("*/")},
		{style:"comment", pattern:"//", end:"\n"},
		{style:"number", pattern:"0[xX][0-9a-fA-F]+"},
		{style:"number", pattern:"(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?"},
		{style:"number", pattern:"\\.\\d+(?:[eE][+-]?\\d+)?"},
		{style:"string", pattern:'"(?:[^\\n"\\\\]|\\\\[^\\n])*?"'},
		{style:"string", pattern:"'(?:[^\\n'\\\\]|\\\\[^\\n])*?'"},
		{style:"string", pattern:"/(?:[^\\n'/\\\\*]|\\\\[^\\n])(?:[^\\n'/\\\\]|\\\\[^\\n])*?/\\w?"},
		{style:"operator", pattern:"(?:[{}()\\[\\]?:;,.]|(?:&lt;|&gt;|&amp;|[-=!+*/%&|^~])+)"},
		{style:"keyword", pattern:"\\b(?:" + keywords.js + ")\\b"},
		{style:"identifier", pattern:"(?:[$_a-zA-Z]|\\\\u[0-9a-zA-Z]{4})(?:[$_a-zA-Z0-9]|\\\\u[0-9a-zA-Z]{4})*"}
	]},
	vbCode: {style:"code", rules:[
		{style:"xmlDocTag", pattern:"'''", end:"\n", jump:"xmlDocComment"},
		{style:"comment", pattern:"'", end:"\n"},
		{style:"comment", pattern:"rem", end:"\n"},
		{style:"string", pattern:'"(?:[^\\n"]|"")*?"'},
		{style:"number", pattern:"(?:\\d*\\.\\d+(?:E[+-]?\\d+)?|\\d+E[+-]?\\d+)[FRD@!#]?"},
		{style:"number", pattern:"(?:\\d+|&amp;H[0-9A-F]+|&amp;O[0-7]+)(?:S|US|I|UI|L|UL|%|&amp;)?"},
		{style:"number", pattern:"\\d+[FRD@!#]"},
		{style:"number", pattern:"#[ \\t]*(?:\\d+/\\d+/\\d+|\\d+-\\d+-\\d+)?(?:[ \\t]+\\d+:\\d+(?::\\d+)?[ \\t]*(?:AM|PM)?)?[ \\t]*#"},
		{style:"operator", pattern:"(?:&amp;|\\*|\\+|-|/|\\\\|\\^|&lt;|=|&gt;)"},
		{style:"identifier", pattern:"(?:" + keywords.vb + ")(?:[%@!#$]|&amp;)"},
		{style:"keyword", pattern:"\\b(?:" + keywords.vb + ")\\b"},
		{style:"identifier", pattern:"(?:[a-z]|_\\w)\\w*(?:[%@!#$]|&amp;)?"},
		{style:"identifier", pattern:"\\[(?:[a-z]|_\\w)\\w*\]"}
	]},
	xmlDocComment: {style:"xmlDocComment", rules:[
		{style:"xmlDocTag", pattern:"&lt;", end:"&gt;", jump:"xmlDocTag"}
	]},
	xmlDocTag: {style:"xmlDocTag", rules:[
		{style:"xmlDocAttr", pattern:'".*?\"'},
		{style:"xmlDocAttr", pattern:"'.*?\'"}
	]},
	xmlText: {style:"code", rules:[
		{style:"xmlDelimiter", pattern:Text("&lt;!--"), end:Text("--&gt;"), jump:"xmlComment"},
		{style:"xmlAttr", pattern:"&amp;[-._a-zA-Z0-9]+;|&amp;#[0-9]+;|&amp;#[xX][0-9a-fA-F]+;"},
		{style:"xmlDelimiter", pattern:"&lt;\\?[xX][mM][lL]", end:Text("?&gt;"), jump:"xmlTag"},
		{style:"xmlDelimiter", pattern:Text("&lt;?"), end:Text("?&gt;"), jump:"xmlPIName"},
		{style:"xmlDelimiter", pattern:"&lt;!\\[CDATA\\[", end:"\\]\\]&gt;", jump:"xmlCDATA"},
		{style:"xmlDelimiter", pattern:"&lt;!", end:"&gt;", jump:"xmlDecl"},
		{style:"xmlDelimiter", pattern:"&lt;/?", end:"/?&gt;", jump:"xmlTag"}
	]},
	xmlComment: {style:"xmlComment"},
	xmlPIName: {style:"xmlName", rules:[
		{style:"xmlName", pattern:"[-_.:0-9a-zA-Z]+", jump:"xmlPI"}
	]},
	xmlPI: {style:"xmlPI"},
	xmlCDATA: {style:"xmlCDATASection"},
	xmlTag: {style:"xmlName", rules:[
		{style:"xmlName", pattern:"[-_.:0-9a-zA-Z]+", jump:"xmlAttr"}
	]},
	xmlAttr: {style:"xmlName", rules:[
		{style:"xmlName", pattern:"[-_.:0-9a-zA-Z]+"},
		{style:"xmlAttrValue", pattern:"'[^']*'"},
		{style:"xmlAttrValue", pattern:'"[^"]*"'},
		{style:"xmlDelimiter", pattern:"="}
	]},
	xmlDecl: {style:"xmlName", rules:[
		{style:"xmlName", pattern:"[-_.:0-9a-zA-Z]+", jump:"xmlDeclAttr"}
	]},
	xmlDeclAttr: {style:"xmlAttr", rules:[
		{style:"xmlAttr", pattern:"[-_.:0-9a-zA-Z]+"},
		{style:"xmlKeyword", pattern:"#PCDATA|#IMPLIED|#REQUIRED|#FIXED|CDATA|ID|IDREF|IDREFS|ENTITY|ENTITIES|NMTOKEN|NMTOKENS"},
		{style:"xmlAttrValue", pattern:"'[^']*'"},
		{style:"xmlAttrValue", pattern:'"[^"]*"'},
		{style:"xmlDelimiter", pattern:"=\\*\\+\\?\\(\\)"}
	]},
	htmlText: {style:"code", rules:[
		{style:"htmlComment", pattern:Text("&lt;!--"), end:Text("--&gt;")},
		{style:"htmlEntity", pattern:"&amp;[-._a-zA-Z0-9]+;|&amp;#[0-9]+;|&amp;#[xX][0-9a-fA-F]+;"},
		{style:"htmlTagDelim", pattern:"&lt;/?", end:"/?&gt;", jump:"htmlTag"}
	]},
	htmlTag: {style:"htmlElementName", rules:[
		{style:"htmlElementName ", pattern:"[-_.:0-9a-zA-Z]+", jump:"htmlAttr"}
	]},
	htmlAttr: {style:"htmlAttrName", rules:[
		{style:"htmlAttrName", pattern:"[-_.:0-9a-zA-Z]+"},
		{style:"htmlAttrValue", pattern:"'[^']*'"},
		{style:"htmlAttrValue", pattern:'"[^"]*"'},
		{style:"htmlOperator", pattern:"="}
	]}
};

var languages = {
	cs: {start: "csCode"},
	js: {start: "jsCode"},
	vb: {start: "vbCode", ignoreCase: true},
	xml: {start: "xmlText", ignoreCase: true},
	html: {start: "htmlText", ignoreCase: true}
}

var urlRegExp = new RegExp("(" + keywords.url + ")://[-_.+$a-z0-9!*'(){}|\\\\^~\\[\\]<>#%\\\";/?:@&=]*[a-z0-9/]", "i");

function ArrayAdd(arr, item)
{
	arr[arr.length] = item;
}

function Language(def)
{
	this.Context = new Context(contexts[def.start], null, def.ignoreCase);
}

function Context(def, rule, ignoreCase)
{
	this.IgnoreCase = ignoreCase;
	this.Style = def.style;
	this.Rules = [];
	this.RegExp = "";
	if (rule)
	{
		this.Style = this.Style || rule.Style;
		this.IgnoreCase = rule.ParentContext.IgnoreCase;
		this.ParentRule = rule;
		this.AddParentRule(rule);
	}
	if (def.rules)
	{
		for (var i = 0, len = def.rules.length; i < len; i++)
		{
			var rule = new Rule(def.rules[i], this);
			this.AddRule(rule);
		}
	}
	if (this.RegExp)
	{
		this.RegExp = new RegExp(this.RegExp, "m" + (this.IgnoreCase ? "i" : ""));
	}
}

Context.prototype.AddRule = function(rule)
{
	ArrayAdd(this.Rules, rule);
	this.RegExp += (this.RegExp) ? "|" : "";
	this.RegExp += "(" + rule.Pattern + ")";
}

Context.prototype.AddParentRule = function(rule)
{
	if (rule.ParentContext.ParentRule)
	{
		this.AddParentRule(rule.ParentContext.ParentRule);
	}
	if (rule.End)
	{
		this.AddRule(new Rule({style:rule.Style, pattern:rule.End, Context:rule.ParentContext}, this));
	}
}

function Rule(def, context)
{
	this.ParentContext = context;
	this.Style = def.style || context.Style;
	this.Pattern = def.pattern;
	this.End = def.end;
	this.Jump = def.jump;
	if (this.Jump)
	{
		if (this.Jump == "pop")
		{
			this.Context = context.ParentRule.ParentContext;
		}
		else
		{
			this.Context = new Context(contexts[this.Jump], this);
		}
	}
	else if (this.End)
	{
		this.Context = new Context({}, this);
	}
	else
	{
		this.Context = def.Context || context;
	}
}

function InitLanguages()
{
	for (var langName in languages)
	{
		languages[langName] = new Language(languages[langName]);
	}
}

Language.prototype.ProcessText = function(source)
{
	var output = [];
	function simpleAdd(text, style)
	{
		output[output.length] = "<span class=" + style + ">" + text + "</span>";
	}
	function add(text, style)
	{
		var m = urlRegExp.exec(text);
		if (m)
		{
			if (m.index)
			{
				simpleAdd(text.substring(0, m.index), style);
			}
			var href = m[0].replace(/(\"|\\)/g, "\\$1");
			output[output.length] = '<a class="' + style + ' link" href="' + href + '">' + m[0] + '</a>';
			var end = m.index + m[0].length;
			if (end < text.length)
			{
				simpleAdd(text.substring(end), style);
			}
		}
		else
		{
			simpleAdd(text, style);
		}
	}
	var context = this.Context;
	while (source)
	{
		var style = context.Style;
		var matches = context.RegExp.exec(source)
		if (matches)
		{
			if (matches.index)
			{
				add(source.substring(0, matches.index), style);
			}
			for (var i = 1; i < matches.length; i++)
			{
				if (matches[i])
				{
					var rule = context.Rules[i - 1];
					add(matches[0], rule.Style || style);
					context = rule.Context;
					break;
				}
			}
			source = source.substring(matches.index + matches[0].length);
		}
		else
		{
			add(source, style);
			source = null;
		}
	}
	return output.join("");
}

function ProcessDocument()
{
	var preList = document.getElementsByTagName("pre");
	for (var i = 0, len = preList.length; i < len; i++)
	{
		var pre = preList[i];
		var lang = languages[(pre.lang) ? pre.lang.toLowerCase() : ""];
		if (lang)
		{
			var coloredText = lang.ProcessText(pre.innerHTML + "");
			if (pre.outerHTML) //HACK: IE does not preserve end of lines.
			{
				pre.outerHTML = "<pre lang=" + pre.lang + ">" + coloredText + "</pre>";
			}
			else
			{
				pre.innerHTML = coloredText;
			}
		}
	}
}
InitLanguages();
ProcessDocument();
}

