(function(){
	var $=function(x){return document.getElementById(x)};
	var RAND=Math.random();

var get_style=(function(){
	if(window.getComputedStyle)
		return function(x){return window.getComputedStyle(x,"")}
	else
		return function(x){return x.runtimeStyle}
})();


var oOut=$("oOut");
var t0=0,timer=null;
var ECHO_TIMEOUT=2000;

/*
var echo=function(x){
	var t1=new Date;
	if(t1-t0>ECHO_TIMEOUT)oOut.value="";
	t0=t1;
	oOut.value+=x;
	oOut.style.color="#000";
	if(timer)window.clearTimeout(timer);
	timer=window.setTimeout(function(){oOut.style.color="#777"},ECHO_TIMEOUT);
}*/
var echo=function(){};

var keyname=(function(){
//	window.onkeydown=function(e){
//		var x=e.keyCode;
//		if((x>=112)&&(x<=123))
//			y="F"+(x-111);
//	}

	return function(x){
		switch(x){
			case 36:return "HOME";break;
			case 33:return "PGUP";break;
			case 34:return "PGDN";break;
			case 35:return "END";break;	
			case 37:return "LEFT";break;
			case 38:return "UP";break;
			case 39:return "RIGHT";break;
			case 40:return "DOWN";break;
			case 13:return "ENTER";break;
			case 32:return "SPACE";break;
			case  9:return "TAB";break;
			case  8:return "BS";break;
			case 27:return "ESC";break;
			case 46:return "DEL";break;
			case 45:return "INS";break;
		}
		if((x>=112)&&(x<=123))
			return "F"+(x-111);
			
		if (x>=48 && x<=57)
			return String.fromCharCode(x);
			
		if (x>=65 && x<=90)
			return String.fromCharCode(x);
			
//		if (x>=97 && x<=122)
//			return String.fromCharCode(x-32);
			
		if (x>=1040 && x<=1103) {
			if(x>=1072)
				x-=32;
			var LAT='QWERTYUIOP{}ASDFGHJKL:"ZXCVBNM<>';
			var RUS='ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ';
			return LAT.charCodeAt(RUS.indexOf(String.fromCharCode(x)));
		}		
		return "#"+x;
	}
})();




	code_editor=function(x){
		if(/\bcode-editor\b/.test(x.className))
			return;
		if(x.disabled)
			return;
		x.className+=" code-editor";
		var p1,p2,a,b,c,top,th;
		var clean=function(x){
			return x.replace(/\t/g,"    ");
		}

		var left, right, mid, top;

		var at=function(n){ x.setSelectionRange(n,n) };
		
		var s=get_style(x);
		
		var ret=function(v,_p){
			var n=0;
			left.replace(/\n/g,function(){++n});
			var line_height=parseInt(s.lineHeight);
			var m=Math.floor(x.scrollTop / line_height); //
			var _r=-1+Math.floor(x.offsetHeight / line_height); //
			if(n-m==_r)
				top+=line_height;
		
			x.value=v;
			at(_p?_p:p2);
			x.scrollTop=top;
		};
		

		var ins=function(v){
			return ret(left+v+right, p2+v.length);
		}
		
		
		var newline=function(){
			//if(right=="")
			//	return 1;
			c=left.match(/( *).*$/)[1];
			ins("\n"+c);
		};


		var escape2=function(x){
			return escape(x).replace(/%([0-9A-F]{2})/g, " [#$1] ");
		};
		
		var delete_line=function(){
			left=left.replace(/.*$/,"");
			_pos=left.length;
			//right=right.replace(/^[^\n]*\n?([^\n]*)/m,function($0,$1){_pos+=$1.length;return $1});
			right=right.replace(/^[^\n]*\n?/m,"");
			ret(left+right, _pos);
		}
		
		var map={
			CTRL_Y:	delete_line,
			F8:		delete_line,
			ENTER:	newline
		};

		var keydown_keycode;
		x.onkeydown=function(e){
			keydown_keycode=e.which;
			//window.status="onkeydown: "+e.keyCode;
		};
		
		x.onkeypress=function(e){
			th=this;
			e=e?e:window.event;
			p1=th.selectionStart;
			p2=th.selectionEnd;
			keyp_code=e.keyCode;
			top=th.scrollTop;
			var v=th.value;
			top = th.scrollTop;
			
			left=v.slice(0,p1);
			mid=v.slice(p1,p2);
			right=v.slice(p2);
			
			//var k=e.keyCode;
			var k=keydown_keycode;
			if(!k)k=e.which;
//			if(!k)k=keydown_keycode;
			keydown_keycode=null;
			//alert(k);
			
			if(!k)k=e.charCode;
			var shift=e.shiftKey;
			var ctrl=e.ctrlKey;
			var alt=e.altKey;
	
			if (k>=97 && k<=122)
				return k-=32;

			k=(ctrl?"CTRL_":"")+(alt?"ALT_":"")+(shift?"SHIFT_":"")+keyname(k);

			window.status="onkeypress: "+k+"  e.keyCode="+e.keyCode+"  e.charCode="+e.charCode;
			
			if(k in map)
				return map[k]() || !1;
			
						
			try{
			if(e.keyCode==120 && !e.ctrlKey && !e.shiftKey && !e.altKey){
					var x=v.slice(p1,p2);
					try{
						eval(x,window);
					}catch(e){
						window.status="ERROR: "+e.message;
					}
				}
//			else if(e.keyCode==13 && !e.ctrlKey && !e.shiftKey && !e.altKey) newline();
//			else if(e.keyCode==37 && !e.ctrlKey && !e.shiftKey && !e.altKey) {
			else if(e.keyCode==37 && !e.ctrlKey && !e.altKey) {
						if((p1>=4) && (v.slice(p1-4,p1)=='    ')) {
							th.setSelectionRange(p1-4,p1-4);
							return !1;
						}
						return;
				}
//			else if(e.keyCode==39 && !e.ctrlKey && !e.shiftKey && !e.altKey){
			else if(e.keyCode==39 && !e.ctrlKey && !e.altKey){
						if (v.slice(p1,p1+4) == '    ') {
							th.setSelectionRange(p1+4,p1+4);
							th.scrollTop=top;				
							return !1;
						}
						return;
				}
			else if(e.keyCode==9 && !e.ctrlKey && !e.altKey){
					//left=v.slice(0,p1);
					var sel=v.slice(p1,p2-1);
					//var right=v.substr(p2-1);
					if(p1!=p2){
						if(e.shiftKey)
							sel=sel.replace(/^    /gm,"");
						else
							sel=sel.replace(/^/gm,"    ");
						th.value=left+sel+right;
						th.setSelectionRange(p1,p1+sel.length+1);
						th.scrollTop=top;				
						return !1;
					}
					th.value=v.slice(0,p1)+'    '+v.substr(p2);
					th.setSelectionRange(p1+4,p1+4);
					th.scrollTop=top;
					return !1;
				}
			else if(e.keyCode==8 && !e.ctrlKey && !e.shiftKey && !e.altKey) {
					if((p1>=4) && (v.slice(p1-4,p1)=='    ')) {
						th.value=v.slice(0,p1-4)+v.substr(p2);
						th.setSelectionRange(p1-4,p1-4);
						th.scrollTop=top;
						return false;
					}
					return;
				}
			else if(e.keyCode==46 && !e.ctrlKey && !e.shiftKey && !e.altKey && p1==p2) {
					if(v.slice(p1,p1+4)=='    ') {
						th.value=v.slice(0,p1)+v.substr(p1+4);
						th.setSelectionRange(p1,p1);
						th.scrollTop=top;				
						return false;
					}
					return;
				}
			else
				return;
			}catch(e){return};
				
			return !1;
		}
	}
	
	var init_editors=function(){
		var i, s, x, xx=document.getElementsByTagName("TEXTAREA");
		
		
		for(i=0;xx[i];++i){
			x=xx[i];
			s=get_style(x);
			if(/courier|mono|lucida/i.test(s.fontFamily))
				code_editor(x);
		}
	}
	
	window.setTimeout(function(){init_editors()},200);
	window.setInterval(function(){init_editors()},3000);

})();
