
/* Unobtrustive Code Highlighter By Dan Webb 11/2005
   Version: 0.4
	
	Usage:
		Add a script tag for this script and any stylesets you need to use
		to the page in question, add correct class names to CODE elements, 
		define CSS styles for elements. That's it! 
	
	Known to work on:
		IE 5.5+ PC
		Firefox/Mozilla PC/Mac
		Opera 7.23 + PC
		Safari 2
		
	Known to degrade gracefully on:
		IE5.0 PC
	
	Note: IE5.0 fails due to the use of lookahead in some stylesets.  To avoid script errors
	in older browsers use expressions that use lookahead in string format when defining stylesets.
	
	This script is inspired by star-light by entirely cunning Dean Edwards
	http://dean.edwards.name/star-light/.  
*/

// replace callback support for safari.
if ("a".replace(/a/, function() {return "b"}) != "b") (function(){
  var default_replace = String.prototype.replace;
  String.prototype.replace = function(search,replace){
	// replace is not function
	if(typeof replace != "function"){
		return default_replace.apply(this,arguments)
	}
	var str = "" + this;
	var callback = replace;
	// search string is not RegExp
	if(!(search instanceof RegExp)){
		var idx = str.indexOf(search);
		return (
			idx == -1 ? str :
			default_replace.apply(str,[search,callback(search, idx, str)])
		)
	}
	var reg = search;
	var result = [];
	var lastidx = reg.lastIndex;
	var re;
	while((re = reg.exec(str)) != null){
		var idx  = re.index;
		var args = re.concat(idx, str);
		result.push(
			str.slice(lastidx,idx),
			callback.apply(null,args).toString()
		);
		if(!reg.global){
			lastidx += RegExp.lastMatch.length;
			break
		}else{
			lastidx = reg.lastIndex;
		}
	}
	result.push(str.slice(lastidx));
	return result.join("")
  }
})();

var CodeHighlighter = { styleSets : new Array };

CodeHighlighter.addStyle = function(name, rules) {
	// using push test to disallow older browsers from adding styleSets
	if ([].push) this.styleSets.push({
		name : name, 
		rules : rules,
		ignoreCase : arguments[2] || false
	})
	
	function setEvent() {
		// set highlighter to run on load (use LowPro if present)
		if (typeof Event != 'undefined' && typeof Event.onReady == 'function') 
		  return Event.onReady(CodeHighlighter.init.bind(CodeHighlighter));
		
		var old = window.onload;
		
		if (typeof window.onload != 'function') {
			window.onload = function() { CodeHighlighter.init() };
		} else {
			window.onload = function() {
				old();
				CodeHighlighter.init();
			}
		}
	}
	
	// only set the event when the first style is added
	if (this.styleSets.length==1) setEvent();
}

CodeHighlighter.init = function() {
	if (!document.getElementsByTagName) return; 
	if ("a".replace(/a/, function() {return "b"}) != "b") return; // throw out Safari versions that don't support replace function
	// throw out older browsers
	
	var codeEls = document.getElementsByTagName("CODE");
	// collect array of all pre elements
	codeEls.filter = function(f) {
		var a =  new Array;
		for (var i = 0; i < this.length; i++) if (f(this[i])) a[a.length] = this[i];
		return a;
	} 
	
	var rules = new Array;
	rules.toString = function() {
		// joins regexes into one big parallel regex
		var exps = new Array;
		for (var i = 0; i < this.length; i++) exps.push(this[i].exp);
		return exps.join("|");
	}
	
	function addRule(className, rule) {
		// add a replace rule
		var exp = (typeof rule.exp != "string")?String(rule.exp).substr(1, String(rule.exp).length-2):rule.exp;
		// converts regex rules to strings and chops of the slashes
		rules.push({
			className : className,
			exp : "(" + exp + ")",
			length : (exp.match(/(^|[^\\])\([^?]/g) || "").length + 1, // number of subexps in rule
			replacement : rule.replacement || null 
		});
	}
	
	function parse(text, ignoreCase) {
		// main text parsing and replacement
		return text.replace(new RegExp(rules, (ignoreCase)?"gi":"g"), function() {
			var i = 0, j = 1, rule;
			while (rule = rules[i++]) {
				if (arguments[j]) {
					// if no custom replacement defined do the simple replacement
					if (!rule.replacement) return "<span class=\"" + rule.className + "\">" + arguments[0] + "</span>";
					else {
						// replace $0 with the className then do normal replaces
						var str = rule.replacement.replace("$0", rule.className);
						for (var k = 1; k <= rule.length - 1; k++) str = str.replace("$" + k, arguments[j + k]);
						return str;
					}
				} else j+= rule.length;
			}
		});
	}
	
	function highlightCode(styleSet) {
		// clear rules array
		var parsed;
		rules.length = 0;
		
		// get stylable elements by filtering out all code elements without the correct className	
		var stylableEls = codeEls.filter(function(item) {return (item.className.indexOf(styleSet.name)>=0)});
		
		// add style rules to parser
		for (var className in styleSet.rules) addRule(className, styleSet.rules[className]);
		
			
		// replace for all elements
		for (var i = 0; i < stylableEls.length; i++) {
			// EVIL hack to fix IE whitespace badness if it's inside a <pre>
			if (/MSIE/.test(navigator.appVersion) && stylableEls[i].parentNode.nodeName == 'PRE') {
				stylableEls[i] = stylableEls[i].parentNode;
				
				parsed = stylableEls[i].innerHTML.replace(/(<code[^>]*>)([^<]*)<\/code>/i, function() {
					return arguments[1] + parse(arguments[2], styleSet.ignoreCase) + "</code>"
				});
				parsed = parsed.replace(/\n( *)/g, function() { 
					var spaces = "";
					for (var i = 0; i < arguments[1].length; i++) spaces+= "&nbsp;";
					return "\n" + spaces;  
				});
				parsed = parsed.replace(/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;");
				parsed = parsed.replace(/\n(<\/\w+>)?/g, "<br />$1").replace(/<br \/>[\n\r\s]*<br \/>/g, "<p><br></p>");
				
			} else parsed = parse(stylableEls[i].innerHTML, styleSet.ignoreCase);
			
			stylableEls[i].innerHTML = parsed;
		}
	}
	
	// run highlighter on all stylesets
	for (var i=0; i < this.styleSets.length; i++) {
		highlightCode(this.styleSets[i]);
	}
}


CodeHighlighter.addStyle("html", {
	comment : {
		exp: /&lt;!\s*(--([^-]|[\r\n]|-[^-])*--\s*)&gt;/
	},
	tag : {
		exp: /(&lt;\/?)([a-zA-Z]+\s?)/, 
		replacement: "$1<span class=\"$0\">$2</span>"
	},
	string : {
		exp  : /'[^']*'|"[^"]*"/
	},
	attribute : {
		exp: /\b([a-zA-Z-:]+)(=)/, 
		replacement: "<span class=\"$0\">$1</span>$2"
	},
	doctype : {
		exp: /&lt;!DOCTYPE([^&]|&[^g]|&g[^t])*&gt;/
	}
});


CodeHighlighter.addStyle("javascript",{
	comment : {
		exp  : /(\/\/[^\n]*(\n|$))|(\/\*[^*]*\*+([^\/][^*]*\*+)*\/)/
	},
	brackets : {
		exp  : /\(|\)/
	},
	regex : {
         exp : /\/(.*?)[g|s|m]?\/[;|\n]/
  },
	string : {
		exp  : /'(?:\.|(\\\')|[^\''])*'|"(?:\.|(\\\")|[^\""])*"/
	},
	keywords : {
		exp  : /\b(arguments|break|case|continue|default|delete|do|else|false|for|function|if|in|instanceof|new|null|return|switch|this|true|typeof|var|void|while|with)\b/
	},
	global : {
		exp  : /\b(toString|valueOf|window|element|prototype|constructor|document|escape|unescape|parseInt|parseFloat|setTimeout|clearTimeout|setInterval|clearInterval|NaN|isNaN|Infinity)\b/
	}
});


CodeHighlighter.addStyle("CSharp",{
	comment : {
		exp  : /(\/\/[^\n]*(\n|$))|(\/\*[^*]*\*+([^\/][^*]*\*+)*\/)/
	},
	brackets : {
		exp  : /\(|\)/
	},
	regex : {
         exp : /\/(.*?)[g|s|m]?\/[;|\n]/
  },
	string : {
		exp  : /'(?:\.|(\\\')|[^\''])*'|"(?:\.|(\\\")|[^\""])*"/
	},    
	ClsAbleitung : {
		exp  : /(?:class)?:(.*?)[\r\n](?=\{)/
	},
	classe : {
		exp  : /(?:class)/
	},
	keywords : {
		exp  : /\b(private|public|null|protected|readonly|static|abstract|as|base|break|case|catch|checked|continue|default|delegate|do|else|event|explicit|extern|false|finally|fixed|for|foreach|goto|if|implicit|in|interface|internal|is|lock|namespace|new|null|object|operator|out|override|params|private|protected|public|readonly|ref|return|sealed|sizeof|stackalloc|switch|this|throw|true|try|typeof|unchecked|unsafe|using|virtual|while)\b/
	},
	DatenTypen : {
		exp  : /\b(bool|byte|char|int|double|float|long|object|sbyte|single|string|short|ushort)\b/
	},
	keywordsCls : {
		exp  : /\b(Boolean|Buffer|DateTime|Double|DllImport|CallingConvention|Compress_Class|Convert|Delegate|Object|String|IComparable|IFormattable|IConvertible|ISerializable|IComparable|IEquatable|IDisposable|SqlDataReader|SqlConnection|SqlCommand|StreamReader)\b/
	},
	global : {
		exp  : /\b(toString|valueOf|window|element|prototype|constructor|document|escape|unescape|parseInt|parseFloat|setTimeout|clearTimeout|setInterval|clearInterval|NaN|isNaN|Infinity)\b/
	}
});


//

CodeHighlighter.addStyle("php",{
	comment : {
		exp  : /(\/\/[^\n]*(\n|$))|(\/\*[^*]*\*+([^\/][^*]*\*+)*\/)/
	},
	brackets : {
		exp  : /\(|\)/
	},
	regex : {
         exp : /\/(.*?)[g|s|m]?\/[;|\n]/
  },
	string : {
		exp  : /'(?:\.|(\\\')|[^\''])*'|"(?:\.|(\\\")|[^\""])*"/
	},
	keywords : {
		exp  : /\b(arguments|break|case|chdir|as|break|case|continue|declare|default|do|echo|else|elseif|endif|endfor|endswitch|endwhile|exit|for|foreach|function|global|if|include|include_once|next|return|require|require_once|switch|while|default|delete|do|echo|else|false|for|function|if|in|instanceof|new|null|return|switch|this|true|typeof|var|void|while|with)\b/
	},
	global : {
		exp  : /\b(toString|valueOf|window|element|prototype|constructor|document|escape|unescape|parseInt|parseFloat|setTimeout|clearTimeout|setInterval|clearInterval|NaN|isNaN|Infinity)\b/
	}
});


CodeHighlighter.addStyle("css", {
	comment : {
		exp  : /\/\*[^*]*\*+([^\/][^*]*\*+)*\//
	},
	keywords : {
		exp  : /@\w[\w\s]*/
	},
	selectors : {
		exp  : "([\\w-:\\[.#][^{};>]*)(?={)"
	},
	properties : {
		exp  : "([\\w-]+)(?=\\s*:)"
	},
	units : {
		exp  : /([0-9])(em|en|px|%|pt)\b/,
		replacement : "$1<span class=\"$0\">$2</span>"
	},
	urls : {
		exp  : /url\([^\)]*\)/
	}
 });


CodeHighlighter.addStyle("ruby",{
	comment : {
		exp  : /#[^\n]*/
	},
	brackets : {
		exp  : /\(|\)|\[|\]|\{|\}/
	},
	string : {
		exp  : /'[^']*'|"[^"]*"/
	},
	keywords : {
		exp  : /\b(do|end|self|class|def|if|module|yield|then|else|for|until|unless|while|elsif|case|when|break|retry|redo|rescue|require|raise)\b/
	},
	constants : {
	  exp  : /\b(true|false|__[A-Z][^\W]+|[A-Z]\w+)\b/
	},
	symbol : {
	  exp  : /:[^\W]+/
	},
	instance : {
	  exp  : /@+[^\W]+/
	},
	method : {
	  exp  : /[^\w]*\.(\w*)[!?]*/
	}
});


CodeHighlighter.addStyle("ebnf",{
	method : {
		exp  : /^(\w+)/
	},
	brackets : {
		exp  : /\(|\)/
	},
        arrow : {
                exp: /\-&gt;/
        },
	'return' : {
		exp  : /\w+$/
	}
});





// ------------------------------------------------------------------------------------------------------------------------------------------------------------

// (C) Andrea Giammarchi - JSHighLighter 0.2 - http://www.devpro.it/jshighlighter/  ******************************************

/* public constructor,
 *	new JSHighLighter(theme:Object[, fullHighlight:Boolean])
 * @param	Object		theme object with these keys:
 * 					comments	// single or multiline comments span class name
 *					strings		// strings span class name
 *					numbers		// numbers span class name
 *					operators	// operators span class name
 *					globals		// OPTIONAL: global top level functions or some reserved words name
 *					properties	// OPTIONAL: Objects properties (i.e. str.length ) name
 *					methods		// OPTIONAL: Objects methods (i.e. str.charAt(... )
 * @param	Boolean		if true, use full highlight
 */
function JSHighLighter(	// requires SourceMap.js
	theme,
	fullHighlight
) {
	/* public method,
	 *	self.parse(source:String[, withHtml:Mixed]):String
	 * @param	String		javascript source code to parse
	 * @param	Mixed		Optional,
	 * 					use <br /> and &nbsp; instead of \n, \r or \t chars
	 * 				Boolean			use 8 &nbsp; chars for each tab
	 *                              Unsigned Integer	use N &nbsp; chars
	 * @return	String		Highlighted javascript source code
	 */
	this.parse = function(str, moreHtml) {
		var 	len = 0, span = "", highlightSource = [], map = [];
		str = str.replace(/</g, "&lt;").replace(/>/g, "&gt;");
		len = str.length;
		map = sourceMap.getMap(str, jsRules);
		for(var a = 0, b = map.length; a < b; a++) {
			span = str.substr(map[a].start, map[a].end - map[a].start);
			switch(map[a].name) {
				case "singlelinecomment":
				case "multilinecomment":
					span = "<span class=\"" + theme.comments + "\">" + span + "</span>";
					break;
				case "singlequote":
				case "doublequote":	
					span = "<span class=\"" + theme.strings + "\">" + span + "</span>";
					break;
				case "code":
					span = highlightSintax(span);
					break;
				
			};
			highlightSource.push(span);
		};
		if(highlightSource.length === 0)
			highlightSource.push(highlightSintax(str));
		str = highlightSource.join("");
		return !moreHtml ? str : addHtml(str, moreHtml);
	};
	
	/** list of all private methods */
	function addHtml(str, tabs) {
		var tabchar = "";
		if(!tabs || tabs.constructor !== Number)
			tabs = 8;
		for(var a = 0; a < tabs; a++)
			tabchar += "&nbsp;";
		if(/\r\n/.test(str))
			str = str.replace(/\r\n/g, "\n");
		else if(/\r/.test(str))
			str = str.replace(/\r/g, "\n");
		return str.replace(/\n/g, "<br />").replace(/\t/g, tabchar);
	};
	function highlightSintax(str) {
		str = str.replace(/([\+\-\*\/=\?!]{1,3}|[\-\+]{1,2})/g, "<span class=\"" + theme.operators + "\">$1</span>").replace(/\b([0-9]+)\b/g, "<span class=\"" + theme.numbers + "\">$1</span>");
		if(fullHighlight) {
			for(var a = 0, b = jsColors.length; a < b; a++)
				str = str.replace(new RegExp(jsSyntax[a], "g"), "<span class=\"" + jsColors[a] + "\">$1</span>");
		};
		return str;
	};
	
	/** list of all private variables */
	var 	jsColors = [theme.globals, theme.properties, theme.methods],
		jsRules = [
			{name:'doublequote', start:'"', end:'"', noslash:true},
			{name:'singlequote', start:"'", end:"'", noslash:true},
			{name:'singlelinecomment', start:'//', end:['\n', '\r']},
			{name:'multilinecomment', start:'/*', end:'*/'},
			{name:'regexp', start:'/', end:'/', match:/^\/[^\n\r]+\/$/, noslash:true}
		],
		jsSyntax = [
			"Infinity|NaN|undefined|decodeURI|decodeURIComponent|encodeURI|encodeURIComponent|eval|isFinite|isNaN|parseFloat|parseInt|delete|function|in|instanceof|new|this|typeof|void|block|break|const|continue|do|while|export|for|if|else|import|label|return|switch|throw|try|catch|var|with|RegExp|Packages|Math|Error|Date|Array|Boolean|Number|Object|Function|String",
			"constructor|global|ignoreCase|lastIndex|multiline|prototype|source|className|java|netscape|sun|E|LN2|LN10|LOG2E|LOG10E|PI|SQRT1_2|SQRT2|description|fileName|lineNumber|message|name|number|stack|index|input|length|MAX_VALUE|MIN_VALUE|NaN|NEGATIVE_INFINITY|POSITIVE_INFINITY|arguments|arity|caller",
			"exec|test|toSource|toString|abs|acos|asin|atan|atan2|ceil|cos|exp|floor|log|max|min|pow|random|round|sin|sqrt|tan|now|parse|UTC|getDate|getDay|getFullYear|getHours|getMilliseconds|getMinutes|getMonth|getSeconds|getTime|getTimezoneOffset|getUTCDate|getUTCDay|getUTCFullYear|getUTCHours|getUTCMilliseconds|getUTCMinutes|getUTCMonth|getUTCSeconds|getYear|setDate|setFullYear|setHours|setMilliseconds|setMinutes|setMonth|setSeconds|setTime|setUTCDate|setUTCFullYear|setUTCHours|setUTCMilliseconds|setUTCMinutes|setUTCMonth|setUTCSeconds|setYear|toGMTString|toLocaleString|toLocaleDateString|toLocaleTimeString|toUTCString|valueOf|pop|push|reverse|shift|sort|splice|unshift|concat|indexOf|join|lastIndexOf|slice|filter|forEach|every|map|some|toExponential|toFixed|toPrecision|__defineGetter__|__defineSetter__|eval|hasOwnProperty|isPrototypeOf|__lookupGetter__|__lookupSetter__|propertyIsEnumerable|unwatch|watch|apply|call|fromCharCode|charAt|charCodeAt|match|replace|search|split|substr|substring|toLowerCase|toUpperCase|anchor|big|blink|bold|fixed|fontcolor|fontsize|italics|link|small|strike|sub|sup"
		],
		reminder = [],
		sourceMap = new SourceMap();
	
	if(jsColors.some(function(str){return str === undefined})) jsColors = [];
	jsSyntax = jsSyntax.map(function(str){return str.split("|").map(function(str){return "\\b" + str + "\\b"})}).map(function(str){return  "(" + str.join("|") + ")"});
};




// --------------
/**
 * SourceMap class,
 *	reads a generic language source code and returns its map.
 * ______________________________________________________________
 * The SourceMap goals is to create a map of a generic script/program language.
 * The getMap method returns an array/list of arrays/dictionary/objects
 * of source map using delimeters variable to map correctly:
 *  - multi line comments
 *  - single line comments
 *  - double quoted strings
 *  - single quoted strings
 *  - pure code
 *  - everything else (for example regexp [/re/] with javascript), just adding a correct delimeter
 * --------------------------------------------------------------
 * What about the delimeter
 * 	It's an array/list of arrays/dictionary/obects with some properties to find what you're looking for.
 * 
 * parameters are:
 *  - name, the name of the delimeter (i.e. "doublequote")
 *  - start, one or mode chars to find as start delimeter (i.e. " for double quoted string)
 *  - end, one or mode chars to find as end delimeter (i.e. " for double quoted string) [end should be an array/list too]
 * 
 * optional parameters are:
 *  - noslash, if true find the end of the delimeter only if last char is not slashed (i.e. "string\"test" find " after test)
 *  - match, if choosed language has regexp, verify if string from start to end matches used regexp (i.e. /^\/[^\n\r]+\/$/ for JavaScript regexp)
 * 
 * If end parameter is an array, match and noslash are not supported (i.e. ["\n", "\r"] for end delimeter of a single line comment)
 * --------------------------------------------------------------
 * What about SourceMap usage
 * 	It should be a good solution to create sintax highlighter, parser,
 * 	verifier or some other source code parsing procedure
 * --------------------------------------------------------------
 * What about SourceMap performance script/languages
 * 	I've created different version of this class to test each script/program language performance too.
 * Python with or without Psyco is actually the faster parser.
 * --------------------------------------------------------------
 * @Compatibility	>= JavaScript 1.1
 * @Author		Andrea Giammarchi
 * @Site		http://www.devpro.it/
 * @Date		2006/08/01
 * @LastMOd		2006/08/01
 * @Version		0.1
 */
function SourceMap() {
	
	/**
	 * public method
         * 	getMap(source:string, delimeters:array):array
	 * Maps the source code using $delimeters rules and returns map as an array
         * NOTE: read comments to know more about map and delimeter
         *
         * @param	string		generic source code
         * @param	array		array with nested objects with code rules
	 */
	this.getMap = function(source, delimeters) {
		
		// "unsigned integer" variables
		var 	sourcePosition = 0,
			delimetersPosition = 0,
			findLength = 0,
			len = 0,
			tempIndex = 0,
			sourceLength = source.length,
			delimetersLength = delimeters.length;
		
		// integer variables
		var	tempPosition = -1,
			endPosition = -1;
		
		// array variables
		var	map = [],
			tempMap = [];
		
		// object variable	
		var	tempDelimeter = {};
		
		while(sourcePosition < sourceLength) {
			endPosition = -1;
			for(delimetersPosition = 0; delimetersPosition < delimetersLength; delimetersPosition++) {
				tempPosition = source.indexOf(delimeters[delimetersPosition].start, sourcePosition);
				if(tempPosition !== -1 && (tempPosition < endPosition || endPosition === -1)) {
					endPosition = tempPosition;
					tempIndex = delimetersPosition;
				}
			}
			if(endPosition !== -1) {
				sourcePosition = endPosition;
				tempDelimeter = delimeters[tempIndex];
				findLength = tempDelimeter.start.length;
				if(tempDelimeter.end.constructor === Array) {
					delimetersPosition = 0;
					endPosition = -1;
					for(len = tempDelimeter.end.length; delimetersPosition < len; delimetersPosition++) {
						tempPosition = source.indexOf(tempDelimeter.end[delimetersPosition], sourcePosition + findLength);
						if(tempPosition !== -1 && (tempPosition < endPosition || endPosition === -1)) {
							endPosition = tempPosition;
							tempIndex = delimetersPosition;
						}	
					}
					if(endPosition !== -1)
						endPosition = endPosition + tempDelimeter.end[tempIndex].length;
					else
						endPosition = sourceLength;
					map.push({name:tempDelimeter.name, start:sourcePosition, end:endPosition});
					sourcePosition = endPosition - 1;
				}
				else if(tempDelimeter.match) {
					tempPosition = source.indexOf(tempDelimeter.end, sourcePosition + findLength);
					len = tempDelimeter.end.length;
					if(tempPosition !== -1 && tempDelimeter.match.test(source.substr(sourcePosition, tempPosition - sourcePosition + len))) {
						endPosition = tempDelimeter.noslash ? __endCharNoSlash(source, sourcePosition, tempDelimeter.end, sourceLength) : tempPosition + len;
						map.push({name:tempDelimeter.name, start:sourcePosition, end:endPosition});
						sourcePosition = endPosition - 1;
					}
				}
				else {
					if(tempDelimeter.noslash)
						endPosition = __endCharNoSlash(source, sourcePosition, tempDelimeter.end, sourceLength);
					else {
						tempPosition = source.indexOf(tempDelimeter.end, sourcePosition + findLength);
						if(tempPosition !== -1)
							endPosition = tempPosition + tempDelimeter.end.length;
						else
							endPosition = sourceLength;
					}
					map.push({name:tempDelimeter.name, start:sourcePosition, end:endPosition});
					sourcePosition = endPosition - 1;
				}
			}
			else
				sourcePosition = sourceLength - 1;
			++sourcePosition;
		}
		len = map.length;
		if(len === 0)
			tempMap.push({name:'code', start:0, end:sourceLength});
		else {
			for(tempIndex = 0; tempIndex < len; tempIndex++) {
				if(tempIndex === 0 && map[tempIndex].start > 0)
					tempMap.push({name:'code', start:0, end:map[tempIndex].start});
				else if(tempIndex > 0 && map[tempIndex].start > map[tempIndex-1].end)
					tempMap.push({name:'code', start:map[tempIndex-1].end, end:map[tempIndex].start});
				tempMap.push({name:map[tempIndex].name, start:map[tempIndex].start, end:map[tempIndex].end});
				if(tempIndex + 1 === len && map[tempIndex].end < sourceLength)
					tempMap.push({name:'code', start:map[tempIndex].end, end:sourceLength});
			}
		}
		return tempMap;
	};
	
	function __endCharNoSlash(source, position, find, len) {
		var	temp = find.length;
		do {
			position = source.indexOf(find, position + 1);
		}while(position !== -1 && !__charNoSlash(source, position));
		if(position === -1) position = len - temp;
		return position + temp;
	};
	
	function __charNoSlash(source, position) {
		var	next = 1,
			len = position - next;
		while(len > 0 && source.charAt(len) === '\\') len = position - (++next);
		return ((next - 1) % 2 === 0);
	};
};


// ----------------------------

// (C) Andrea Giammarchi - JSL 1.4b
eval(function(A,G){return eval('["'+A.replace(/(\\|")/g,'\\$1').replace(/(\w+)/g,'",G[parseInt("$1",36)],"')+'"].join("")')}("0 1;2 $3(){4.5=2(){0 6=7,8=9[a].b;c(8&&!6)6=9[a][--8]===9[d];e 6;};4.f=2(g){e $3.5(g,$f)};4.h=2(i){0 6=$3.$h();c(j(i[6])!==\"1\")6=$3.$h();e 6;};4.$h=2(){e(k.h()*l).m()};4.n=2(g){e g.o(\"\").n().p(\"\")};4.q=2(g){0 6=g.o(\"\"),8=6.b;c(8>d)6[--8]=$3.$q(6[8]);e 6.p(\"\");};4.$q=2(6){0 8=6.b===a?6.r(d):d;s(8){t u:6=\"\\\\v\";w;t x:6=\"\\\\y\";w;t z:6=\"\\\\10\";w;t 11:6=\"\\\\12\";w;t 13:6=\"\\\\14\";w;t 15:6=\"\\\\\\\"\";w;t 16:6=\"\\\\\\\\\";w;17:6=6.q(/([\\18-\\19]|[\\1a-\\1b]|[\\1c-\\1d])/1e,2(1f,v){e \"\\\\1g\"+$3.r(v)}).q(/([\\1h-\\1i])/1e,2(1f,v){v=$3.r(v);e v.b<1j?\"\\\\1k\"+v:\"\\\\1l\"+v});w;};e 6;};4.r=2(g){e $3.$r(g.r(d))};4.$r=2(8){0 g=8.m(1m).1n();e g.b<1o?\"d\"+g:g;};4.$1p=2(i){e i.1p().q(/^(\\(1q \\1r+\\()([^\\d]+)(\\)\\))$/,\"$1o\")};4.$1s=2(i){0 6=1t;s(i.1u){t 1v:t 1w:6=i;w;t 1x:6=$3.$1p(i);w;17:6=i.1p();w;};e 6;};4.1y=2(1z,8,i,g){0 6=$3.$1y(1z),20=6.b,$6=[];c(8<20){21(6[8][g]===i||i===\"*\")$6.22($3.$23(6[8]));++8};21(!$6.24){21(!$3.f(\"24\"))$f.22(\"24\");$6.24=2(6){e 4[6]}};e $6;};4.$1y=2(1z){e 1z.25||1z.26};4.$23=2(i){21(!i.1y)i.1y=27.1y;e i;};4.28=2(g){e g.q(/\"/1e,\"%29\").q(/\\\\/1e,\"%2a\")};4.$28=2(g){e $3.$r(g)};4.$2b=2(1f,v){0 8=v.r(d),g=[];21(8<2c)g.22(8);2d 21(8<2e)g.22(2f+(8>>2g),2c+(8&2h));2d 21(8<2i)g.22(2j+(8>>11),2c+(8>>2g&2h),2c+(8&2h));2d g.22(2k+(8>>2l),2c+(8>>11&2h),2c+(8>>2g&2h),2c+(8&2h));e \"%\"+g.2m($3.$28).p(\"%\");};4.$2n=2(1f,v,2o,2p,2q){0 8=d;21(2q)8=2r(2q.2s(a,1o),1m);2d 21(2p)8=((2r(2p.2s(a,1o),1m)-2f)<<2g)+(2r(2p.2s(1j,1o),1m)-2c);2d 21(2o)8=((2r(2o.2s(a,1o),1m)-2j)<<11)+((2r(2o.2s(1j,1o),1m)-2c)<<2g)+(2r(2o.2s(2t,1o),1m)-2c);2d 8=((2r(v.2s(a,1o),1m)-2k)<<2l)+((2r(v.2s(1j,1o),1m)-2c)<<11)+((2r(v.2s(2t,1o),1m)-2c)<<2g)+(2r(v.2s(x,1o),1m)-2c);e 1x.2u(8);};0 $f=[];21(!2v.2w.1p){$f[$f.b]=\"1p\";2v.2w.1p=2(){0 g=[];s(4.1u){t 1v:g.22(\"(1q 1v(\",4,\"))\");w;t 1w:g.22(\"(1q 1w(\",4,\"))\");w;t 1x:g.22(\"(1q 1x(\\\"\",$3.q(4),\"\\\"))\");w;t 2x:g.22(\"(1q 2x(\",4.2y(),\"))\");w;t 2z().1u:g.22(\"(1q 2z(\",$3.$1p(4.30),\",\",$3.$1p(4.31),\",\",4.32,\"))\");w;t 33:g.22(\"(\",$3.$q(4.m()),\")\");w;t 34:0 8=d,20=4.b;c(8<20)g.22($3.$1s(4[8++]));g=[\"[\",g.p(\", \"),\"]\"];w;17:0 8=d,6;35(8 36 4){21(8!==\"1p\")g.22($3.$1p(8)+\":\"+$3.$1s(4[8]));};g=[\"{\",g.p(\", \"),\"}\"];w;};e g.p(\"\");}};21(!33.2w.37){$f[$f.b]=\"37\";33.2w.37=2(){0 8=9.b===1o?9[a].b:d,g,6=[],i=(\"\"+4).q(/[^\\(]+/,\"2\");21(!9[d])9[d]={};c(8)6.38(\"9[a][\"+(--8)+\"]\");39{g=\"3a\".3b($3.h(9[d]).q(/\\./,\"3c\"),\"3a\")}c(1q 3d(g).3e(i));3f(\"0 \".3b(g,\"=9[d];6=(\",i.q(/([^$])\\3g\\v([^$])/1e,\"$a\".3b(g,\"$1o\")),\")(\",6.p(\",\"),\")\"));e 6;}};21(!33.2w.3h){$f[$f.b]=\"3h\";33.2w.3h=2(){0 8=9.b,6=[];c(8>a)6.38(9[--8]);e 4.37((8?9[d]:{}),6);}};21(!34.2w.3i){$f[$f.b]=\"3i\";34.2w.3i=2(){0 1f=4.b,14=4[--1f];21(1f>=d)4.b=1f;e 14;}};21(!34.2w.22){$f[$f.b]=\"22\";34.2w.22=2(){0 1f=d,v=9.b,14=4.b;c(1f<v)4[14++]=9[1f++];e 14;}};21(!34.2w.3j){$f[$f.b]=\"3j\";34.2w.3j=2(){4.n();0 14=4.3i();4.n();e 14;}};21(!34.2w.3k){$f[$f.b]=\"3k\";34.2w.3k=2(){0 1f,v,2o,2p=9.b,6=[],14=[];21(2p>a){9[d]=2r(9[d]);9[a]=2r(9[a]);2o=9[d]+9[a];35(1f=d,v=4.b;1f<v;1f++){21(1f<9[d]||1f>=2o){21(1f===2o&&2p>1o){35(1f=1o;1f<2p;1f++)6.22(9[1f]);1f=2o;};6.22(4[1f]);}2d 14.22(4[1f]);};35(1f=d,v=6.b;1f<v;1f++)4[1f]=6[1f];4.b=1f;};e 14;}};21(!34.2w.38){$f[$f.b]=\"38\";34.2w.38=2(){0 8=9.b;4.n();c(8>d)4.22(9[--8]);4.n();e 4.b;}};21(!34.2w.3l){$f[$f.b]=\"3l\";34.2w.3l=2(i,8){0 20=4.b;21(!8)8=d;21(8>=d){c(8<20){21(4[8++]===i){8=8-a+20;20=8-20;}}}2d 20=4.3l(i,20+8);e 20!==4.b?20:-a;}};21(!34.2w.3m){$f[$f.b]=\"3m\";34.2w.3m=2(i,8){0 20=-a;21(!8)8=4.b;21(8>=d){39{21(4[8--]===i){20=8+a;8=d;}}c(8>d)}2d 21(8>-4.b)20=4.3m(i,4.b+8);e 20;}};21(!34.2w.3n){$f[$f.b]=\"3n\";34.2w.3n=2(3o,i){0 v=7,8=d,20=4.b;21(!i){c(8<20&&!v)v=!3o(4[8]||4.3p(8),8++,4)}2d{c(8<20&&!v)v=!3o.37(i,[4[8]||4.3p(8),8++,4]);}e!v;}};21(!34.2w.3q){$f[$f.b]=\"3q\";34.2w.3q=2(3o,i){0 14=[],8=d,20=4.b;21(!i){c(8<20){21(3o(4[8],8++,4))14.22(4[8-a]);}}2d{c(8<20){21(3o.37(i,[4[8],8++,4]))14.22(4[8-a]);}}e 14;}};21(!34.2w.3r){$f[$f.b]=\"3r\";34.2w.3r=2(3o,i){0 8=d,20=4.b;21(!i){c(8<20)3o(4[8],8++,4)}2d{c(8<20)3o.37(i,[4[8],8++,4]);}}};21(!34.2w.2m){$f[$f.b]=\"2m\";34.2w.2m=2(3o,i){0 14=[],8=d,20=4.b;21(!i){c(8<20)14.22(3o(4[8],8++,4))}2d{c(8<20)14.22(3o.37(i,[4[8],8++,4]));}e 14;}};21(!34.2w.3s){$f[$f.b]=\"3s\";34.2w.3s=2(3o,i){0 v=7,8=d,20=4.b;21(!i){c(8<20&&!v)v=3o(4[8],8++,4)}2d{c(8<20&&!v)v=3o.37(i,[4[8],8++,4]);}e v;}};21(!1x.2w.3m){21(!4.5(\"3m\",$f))$f[$f.b]=\"3m\";1x.2w.3m=2(i,8){0 g=$3.n(4),i=$3.n(i),14=g.3l(i,8);e 14<d?14:4.b-14;}};21(\"3t\".q(/\\1r/1e,2(){e 9[a]+\" \"})!==\"d a \"){$f[$f.b]=\"q\";1x.2w.q=2(q){e 2(3u,3v){0 14=\"\",6=$3.h(1x);1x.2w[6]=q;21(3v.1u!==33)14=4[6](3u,3v);2d{2 3w(3u,3x,1f){2 3y(){0 1f=3u.3l(\"(\",3x),v=1f;c(1f>d&&3u.3p(--1f)===\"\\\\\"){};3x=v!==-a?v+a:v;e(v-1f)%1o===a?a:d;};39{1f+=3y()}c(3x!==-a);e 1f;};2 $q(g){0 20=g.b-a;c(20>d)g[--20]=\'\"\'+g[20].2s(a,g[20--].b-1o)[6](/(\\\\|\")/1e,\'\\\\$a\')+\'\"\';				e g.p(\"\");			};			0 3z=-a,8=3w(\"\"+3u,d,d),40=[],$41=4.41(3u),i=$3.$h()[6](/\\./,\'42\');			c(4.3l(i)!==-a)i=$3.$h()[6](/\\./,\'42\');			c(8)40[--8]=[i,\'\"$\',(8+a),\'\"\',i].p(\"\");			21(!40.b)14=\"$41[8],(3z=4.3l($41[8++],3z+a)),4\";			2d		14=\"$41[8],\"+40.p(\",\")+\",(3z=4.3l($41[8++],3z+a)),4\";			14=3f(\'[\'+$q((i+(\'\"\'+4[6](3u,\'\"\'+i+\',3v(\'+14+\'),\'+i+\'\"\')+\'\"\')+i).o(i))[6](/\\y/1e,\'\\\\y\')[6](/\\14/1e,\'\\\\14\')+\'].p(\"\")\');		};		43 1x.2w[6];		e 14;	}}(1x.2w.q)};	21((1q 2x().44()).m().b===1j){$f[$f.b]=\"44\";2x.2w.44=2(){		e 4.45()-46;	}};};$3=1q $3();21(j(28)===\"1\"){2 28(g){	0 i=/([\\18-\\47]|[\\48|\\49|\\4a|\\4b|\\4c|\\4d|\\4e|\\1c]|[\\4f-\\4g]|[\\4h-\\1i])/1e;	e $3.28(g.m().q(i,$3.$2b));}};21(j(2b)===\"1\"){2 2b(g){	0 i=/([\\4i|\\4j|\\4k|\\4l|\\4m|\\4n|\\4o|\\4p|\\4q|\\4r|\\4s])/1e;	e $3.28(28(g).q(i,2(1f,v){e \"%\"+$3.r(v)}));}};21(j(2n)===\"1\"){2 2n(g){	0 i=/(%4t[d-4u-4t]%4v[d-4u-4t]%[4w-4x][d-4u-4t]%[u-4u-4x][d-4u-4t])|(%4v[d-4u-4t]%[4w-4x][d-4u-4t]%[u-4u-4x][d-4u-4t])|(%[4y-4z][d-4u-4t]%[u-4u-4x][d-4u-4t])|(%[d-4u-4t]{1o})/1e;	e g.m().q(i,$3.$2n);}};21(j(50)===\"1\"){2 50(g){	e 2n(g);}};21(!27.51){27.51=2(i){	e $3.$23($3.$1y(4)[i]);}};21(!27.1y){27.1y=2(i){	e $3.1y(4,d,i.1n(),\"52\");}};21(!27.23){27.23=2(i){	e $3.1y(4,d,i,\"53\");}};21(j(54)===\"1\"){54=2(){	0 6=1t,i=55.56;	21(i.1n().3l(\"57 1j\")<d&&58.59)		6=i.3l(\"57 5a\")<d?1q 59(\"5b.5c\"):1q 59(\"5d.5c\");	e 6;}};21(j(2z)===\"1\")2z=2(){};2z = 2(5e){e 2(30){	0 6=1q 5e();	6.30=30||\"\";	21(!6.31)		6.31=27.5f.5g;	21(!6.32)		6.32=d;	21(!6.5h)		6.5h=\"2z()@:d\\y(\\\"\"+4.30+\"\\\")@\"+6.31+\":\"+4.32+\"\\y@\"+6.31+\":\"+4.32;	21(!6.53)		6.53=\"2z\";	e 6;}}(2z);","var,undefined,function,JSL,this,inArray,tmp,false,i,arguments,1,length,while,0,return,has,str,random,elm,typeof,Math,1234567890,toString,reverse,split,join,replace,charCodeAt,switch,case,8,b,break,10,n,11,v,12,f,13,r,34,92,default,x00,x07,x0E,x1F,x7F,xFF,g,a,x,u0100,uFFFF,4,u0,u,16,toUpperCase,2,toSource,new,w,toInternalSource,null,constructor,Boolean,Number,String,getElementsByTagName,scope,j,if,push,getElementsByName,item,layers,all,document,encodeURI,22,5C,encodeURIComponent,128,else,2048,0xC0,6,0x3F,65536,0xE0,0xF0,18,map,decodeURIComponent,c,d,e,parseInt,substr,7,fromCharCode,Object,prototype,Date,getTime,Error,message,fileName,lineNumber,Function,Array,for,in,apply,unshift,do,__,concat,_,RegExp,test,eval,bthis,call,pop,shift,splice,indexOf,lastIndexOf,every,callback,charAt,filter,forEach,some,aa,reg,func,getMatches,pos,io,p,args,match,_AG_,delete,getYear,getFullYear,1900,x20,x25,x3C,x3E,x5B,x5D,x5E,x60,x7B,x7D,x80,x23,x24,x26,x2B,x2C,x2F,x3A,x3B,x3D,x3F,x40,F,9A,E,A,B,C,D,decodeURI,getElementById,tagName,name,XMLHttpRequest,navigator,userAgent,MSIE,window,ActiveXObject,5,Msxml2,XMLHTTP,Microsoft,base,location,href,stack".split(",")));


