text: /******
   *
   *	EditArea 
   * 	Developped by Christophe Dolivet
   *	Released under LGPL, Apache and BSD licenses (use the one you want)
   *
  ******/
  
  	function EditArea(){
  		var t=this;
  		t.error= false;	// to know if load is interrrupt
  		
  		t.inlinePopup= [{popup_id: "area_search_replace", icon_id: "search"},
  									{popup_id: "edit_area_help", icon_id: "help"}];
  		t.plugins= {};
  	
  		t.line_number=0;
  		
  		parent.editAreaLoader.set_browser_infos(t); 	// navigator identification
  		// fix IE8 detection as we run in IE7 emulate mode through X-UA <meta> tag
  		if( t.isIE == 8 )
  			t.isIE	= 7;
  		if( t.isIE == 9 )
  			t.isIE = false;
  		
  		t.last_selection={};		
  		t.last_text_to_highlight="";
  		t.last_hightlighted_text= "";
  		t.syntax_list= [];
  		t.allready_used_syntax= {};
  		t.check_line_selection_timer= 50;	// the timer delay for modification and/or selection change detection
  		
  		t.textareaFocused= false;
  		t.highlight_selection_line= null;
  		t.previous= [];
  		t.next= [];
  		t.last_undo="";
  		t.files= {};
  		t.filesIdAssoc= {};
  		t.curr_file= '';
  		//t.loaded= false;
  		t.assocBracket={};
  		t.revertAssocBracket= {};		
  		// bracket selection init 
  		t.assocBracket["("]=")";
  		t.assocBracket["{"]="}";
  		t.assocBracket["["]="]";		
  		for(var index in t.assocBracket){
  			t.revertAssocBracket[t.assocBracket[index]]=index;
  		}
  		t.is_editable= true;
  		
  		
  		/*t.textarea="";	
  		
  		t.state="declare";
  		t.code = []; // store highlight syntax for languagues*/
  		// font datas
  		t.lineHeight= 16;
  		/*t.default_font_family= "monospace";
  		t.default_font_size= 10;*/
  		t.tab_nb_char= 8;	//nb of white spaces corresponding to a tabulation
  		if(t.isOpera)
  			t.tab_nb_char= 6;
  
  		t.is_tabbing= false;
  		
  		t.fullscreen= {'isFull': false};
  		
  		t.isResizing=false;	// resize var
  		
  		// init with settings and ID (area_id is a global var defined by editAreaLoader on iframe creation
  		t.id= area_id;
  		t.settings= editAreas[t.id]["settings"];
  		
  		if((""+t.settings['replace_tab_by_spaces']).match(/^[0-9]+$/))
  		{
  			t.tab_nb_char= t.settings['replace_tab_by_spaces'];
  			t.tabulation="";
  			for(var i=0; i<t.tab_nb_char; i++)
  				t.tabulation+=" ";
  		}else{
  			t.tabulation="\t";
  		}
  			
  		// retrieve the init parameter for syntax
  		if(t.settings["syntax_selection_allow"] && t.settings["syntax_selection_allow"].length>0)
  			t.syntax_list= t.settings["syntax_selection_allow"].replace(/ /g,"").split(",");
  		
  		if(t.settings['syntax'])
  			t.allready_used_syntax[t.settings['syntax']]=true;
  		
  		
  	};
  	EditArea.prototype.init= function(){
  		var t=this, a, s=t.settings;
  		t.textarea			= _$("textarea");
  		t.container			= _$("container");
  		t.result			= _$("result");
  		t.content_highlight	= _$("content_highlight");
  		t.selection_field	= _$("selection_field");
  		t.selection_field_text= _$("selection_field_text");
  		t.processing_screen	= _$("processing");
  		t.editor_area		= _$("editor");
  		t.tab_browsing_area	= _$("tab_browsing_area");
  		t.test_font_size	= _$("test_font_size");
  		a = t.textarea;
  		
  		if(!s['is_editable'])
  			t.set_editable(false);
  		
  		t.set_show_line_colors( s['show_line_colors'] );
  		
  		if(syntax_selec= _$("syntax_selection"))
  		{
  			// set up syntax selection lsit in the toolbar
  			for(var i=0; i<t.syntax_list.length; i++) {
  				var syntax= t.syntax_list[i];
  				var option= document.createElement("option");
  				option.value= syntax;
  				if(syntax==s['syntax'])
  					option.selected= "selected";
  				dispSyntax	= parent.editAreaLoader.syntax_display_name[ syntax ];
  				option.innerHTML= typeof( dispSyntax ) == 'undefined' ? syntax.substring( 0, 1 ).toUpperCase() + syntax.substring( 1 ) : dispSyntax;//t.get_translation("syntax_" + syntax, "word");
  				syntax_selec.appendChild(option);
  			}
  		}
  		
  		// add plugins buttons in the toolbar
  		spans= parent.getChildren(_$("toolbar_1"), "span", "", "", "all", -1);
  		
  		for(var i=0; i<spans.length; i++){
  		
  			id=spans[i].id.replace(/tmp_tool_(.*)/, "$1");
  			if(id!= spans[i].id){
  				for(var j in t.plugins){
  					if(typeof(t.plugins[j].get_control_html)=="function" ){
  						html=t.plugins[j].get_control_html(id);
  						if(html!=false){
  							html= t.get_translation(html, "template");
  							var new_span= document.createElement("span");
  							new_span.innerHTML= html;				
  							var father= spans[i].parentNode;
  							spans[i].parentNode.replaceChild(new_span, spans[i]);	
  							break; // exit the for loop					
  						}
  					}
  				}
  			}
  		}
  		
  		// init datas
  		//a.value	= 'a';//editAreas[t.id]["textarea"].value;
  	
  		if(s["debug"])
  		{
  			t.debug=parent.document.getElementById("edit_area_debug_"+t.id);
  		}
  		// init size		
  		//this.update_size();
  		
  		if(_$("redo") != null)
  			t.switchClassSticky(_$("redo"), 'editAreaButtonDisabled', true);
  		
  		// insert css rules for highlight mode		
  		if(typeof(parent.editAreaLoader.syntax[s["syntax"]])!="undefined"){
  			for(var i in parent.editAreaLoader.syntax){
  				if (typeof(parent.editAreaLoader.syntax[i]["styles"]) != "undefined"){
  					t.add_style(parent.editAreaLoader.syntax[i]["styles"]);
  				}
  			}
  		}
  	
  		// init key events
  		if(t.isOpera)
  			_$("editor").onkeypress	= keyDown;
  		else
  			_$("editor").onkeydown	= keyDown;
  
  		for(var i=0; i<t.inlinePopup.length; i++){
  			if(t.isOpera)
  				_$(t.inlinePopup[i]["popup_id"]).onkeypress	= keyDown;
  			else
  				_$(t.inlinePopup[i]["popup_id"]).onkeydown	= keyDown;
  		}
  		
  		if(s["allow_resize"]=="both" || s["allow_resize"]=="x" || s["allow_resize"]=="y")
  			t.allow_resize(true);
  		
  		parent.editAreaLoader.toggle(t.id, "on");
  		//a.focus();
  		// line selection init
  		t.change_smooth_selection_mode(editArea.smooth_selection);
  		// highlight
  		t.execCommand("change_highlight", s["start_highlight"]);
  	
  		// get font size datas		
  		t.set_font(editArea.settings["font_family"], editArea.settings["font_size"]);
  		
  		// set unselectable text
  		children= parent.getChildren(document.body, "", "selec", "none", "all", -1);
  		for(var i=0; i<children.length; i++){
  			if(t.isIE)
  				children[i].unselectable = true; // IE
  			else
  				children[i].onmousedown= function(){return false};
  		/*	children[i].style.MozUserSelect = "none"; // Moz
  			children[i].style.KhtmlUserSelect = "none";  // Konqueror/Safari*/
  		}
  		
  		a.spellcheck= s["gecko_spellcheck"];
  	
  		/** Browser specific style fixes **/
  		
  		// fix rendering bug for highlighted lines beginning with no tabs
  		if( t.isFirefox >= '3' ) {
  			t.content_highlight.style.paddingLeft= "1px";
  			t.selection_field.style.paddingLeft= "1px";
  			t.selection_field_text.style.paddingLeft= "1px";
  		}
  		
  		if(t.isIE && t.isIE < 8 ){
  			a.style.marginTop= "-1px";
  		}
  		/*
  		if(t.isOpera){
  			t.editor_area.style.position= "absolute";
  		}*/
  		
  		if( t.isSafari && t.isSafari < 4.1 ){
  			t.editor_area.style.position	= "absolute";
  			a.style.marginLeft		="-3px";
  			if( t.isSafari < 3.2 ) // Safari 3.0 (3.1?)
  				a.style.marginTop	="1px";
  		}
  		
  		// si le textarea n'est pas grand, un click sous le textarea doit provoquer un focus sur le textarea
  		parent.editAreaLoader.add_event(t.result, "click", function(e){ if((e.target || e.srcElement)==editArea.result) { editArea.area_select(editArea.textarea.value.length, 0);}  });
  		
  		if(s['is_multi_files']!=false)
  			t.open_file({'id': t.curr_file, 'text': ''});
  	
  		t.set_word_wrap( s['word_wrap'] );
  		
  		setTimeout("editArea.focus();editArea.manage_size();editArea.execCommand('EA_load');", 10);		
  		//start checkup routine
  		t.check_undo();
  		t.check_line_selection(true);
  		t.scroll_to_view();
  		
  		for(var i in t.plugins){
  			if(typeof(t.plugins[i].onload)=="function")
  				t.plugins[i].onload();
  		}
  		if(s['fullscreen']==true)
  			t.toggle_full_screen(true);
  	
  		parent.editAreaLoader.add_event(window, "resize", editArea.update_size);
  		parent.editAreaLoader.add_event(parent.window, "resize", editArea.update_size);
  		parent.editAreaLoader.add_event(top.window, "resize", editArea.update_size);
  		parent.editAreaLoader.add_event(window, "unload", function(){
  			// in case where editAreaLoader have been already cleaned
  			if( parent.editAreaLoader )
  			{
  				parent.editAreaLoader.remove_event(parent.window, "resize", editArea.update_size);
  		  		parent.editAreaLoader.remove_event(top.window, "resize", editArea.update_size);
  			}
  			if(editAreas[editArea.id] && editAreas[editArea.id]["displayed"]){
  				editArea.execCommand("EA_unload");
  			}
  		});
  		
  		
  		/*date= new Date();
  		alert(date.getTime()- parent.editAreaLoader.start_time);*/
  	};
  	
  	
  	
  	//called by the toggle_on
  	EditArea.prototype.update_size= function(){
  		var d=document,pd=parent.document,height,width,popup,maxLeft,maxTop;
  		
  		if( typeof editAreas != 'undefined' && editAreas[editArea.id] && editAreas[editArea.id]["displayed"]==true){
  			if(editArea.fullscreen['isFull']){	
  				pd.getElementById("frame_"+editArea.id).style.width		= pd.getElementsByTagName("html")[0].clientWidth + "px";
  				pd.getElementById("frame_"+editArea.id).style.height	= pd.getElementsByTagName("html")[0].clientHeight + "px";
  			}
  			
  			if(editArea.tab_browsing_area.style.display=='block' && ( !editArea.isIE || editArea.isIE >= 8 ) )
  			{
  				editArea.tab_browsing_area.style.height	= "0px";
  				editArea.tab_browsing_area.style.height	= (editArea.result.offsetTop - editArea.tab_browsing_area.offsetTop -1)+"px";
  			}
  			
  			height	= d.body.offsetHeight - editArea.get_all_toolbar_height() - 4;
  			editArea.result.style.height	= height +"px";
  			
  			width	= d.body.offsetWidth -2;
  			editArea.result.style.width		= width+"px";
  			//alert("result h: "+ height+" w: "+width+"\ntoolbar h: "+this.get_all_toolbar_height()+"\nbody_h: "+document.body.offsetHeight);
  			
  			// check that the popups don't get out of the screen
  			for( i=0; i < editArea.inlinePopup.length; i++ )
  			{
  				popup	= _$(editArea.inlinePopup[i]["popup_id"]);
  				maxLeft	= d.body.offsetWidth - popup.offsetWidth;
  				maxTop	= d.body.offsetHeight - popup.offsetHeight;
  				if( popup.offsetTop > maxTop )
  					popup.style.top		= maxTop+"px";
  				if( popup.offsetLeft > maxLeft )
  					popup.style.left	= maxLeft+"px";
  			}
  			
  			editArea.manage_size( true );
  			editArea.fixLinesHeight( editArea.textarea.value, 0,-1);
  		}		
  	};
  	
  	
  	EditArea.prototype.manage_size= function(onlyOneTime){
  		if(!editAreas[this.id])
  			return false;
  			
  		if(editAreas[this.id]["displayed"]==true && this.textareaFocused)
  		{
  			var area_height,resized= false;
  			
  			//1) Manage display width
  			//1.1) Calc the new width to use for display
  			if( !this.settings['word_wrap'] )
  			{
  				var area_width= this.textarea.scrollWidth;
  				area_height= this.textarea.scrollHeight;
  				// bug on old opera versions
  				if(this.isOpera && this.isOpera < 9.6 ){
  					area_width=10000; 								
  				}
  				//1.2) the width is not the same, we must resize elements
  				if(this.textarea.previous_scrollWidth!=area_width)
  				{	
  					this.container.style.width= area_width+"px";
  					this.textarea.style.width= area_width+"px";
  					this.content_highlight.style.width= area_width+"px";	
  					this.textarea.previous_scrollWidth=area_width;
  					resized=true;
  				}
  			}
  			// manage wrap width
  			if( this.settings['word_wrap'] )
  			{
  				newW=this.textarea.offsetWidth;
  				if( this.isFirefox || this.isIE )
  					newW-=2;
  				if( this.isSafari )
  					newW-=6;
  				this.content_highlight.style.width=this.selection_field_text.style.width=this.selection_field.style.width=this.test_font_size.style.width=newW+"px";
  			}
  			
  			//2) Manage display height
  			//2.1) Calc the new height to use for display
  			if( this.isOpera || this.isFirefox || this.isSafari ) { 
  				area_height= this.getLinePosTop( this.last_selection["nb_line"] + 1 );
  			} else {
  				area_height = this.textarea.scrollHeight;
  			}	
  			//2.2) the width is not the same, we must resize elements 
  			if(this.textarea.previous_scrollHeight!=area_height)	
  			{	
  				this.container.style.height= (area_height+2)+"px";
  				this.textarea.style.height= area_height+"px";
  				this.content_highlight.style.height= area_height+"px";	
  				this.textarea.previous_scrollHeight= area_height;
  				resized=true;
  			}
  		
  			//3) if there is new lines, we add new line numbers in the line numeration area
  			if(this.last_selection["nb_line"] >= this.line_number)
  			{
  				var newLines= '', destDiv=_$("line_number"), start=this.line_number, end=this.last_selection["nb_line"]+100;
  				for( i = start+1; i < end; i++ )
  				{
  					newLines+='<div id="line_'+ i +'">'+i+"</div>";
  					this.line_number++;
  				}
  				destDiv.innerHTML= destDiv.innerHTML + newLines;
  				if(this.settings['word_wrap']){
  					this.fixLinesHeight( this.textarea.value, start, -1 );
  				}
  			}
  		
  			//4) be sure the text is well displayed
  			this.textarea.scrollTop="0px";
  			this.textarea.scrollLeft="0px";
  			if(resized==true){
  				this.scroll_to_view();
  			}
  		}
  		
  		if(!onlyOneTime)
  			setTimeout("editArea.manage_size();", 100);
  	};
  	
  	EditArea.prototype.execCommand= function(cmd, param){
  		
  		for(var i in this.plugins){
  			if(typeof(this.plugins[i].execCommand)=="function"){
  				if(!this.plugins[i].execCommand(cmd, param))
  					return;
  			}
  		}
  		switch(cmd){
  			case "save":
  				if(this.settings["save_callback"].length>0)
  					eval("parent."+this.settings["save_callback"]+"('"+ this.id +"', editArea.textarea.value);");
  				break;
  			case "load":
  				if(this.settings["load_callback"].length>0)
  					eval("parent."+this.settings["load_callback"]+"('"+ this.id +"');");
  				break;
  			case "onchange":
  				if(this.settings["change_callback"].length>0)
  					eval("parent."+this.settings["change_callback"]+"('"+ this.id +"');");
  				break;		
  			case "EA_load":
  				if(this.settings["EA_load_callback"].length>0)
  					eval("parent."+this.settings["EA_load_callback"]+"('"+ this.id +"');");
  				break;
  			case "EA_unload":
  				if(this.settings["EA_unload_callback"].length>0)
  					eval("parent."+this.settings["EA_unload_callback"]+"('"+ this.id +"');");
  				break;
  			case "toggle_on":
  				if(this.settings["EA_toggle_on_callback"].length>0)
  					eval("parent."+this.settings["EA_toggle_on_callback"]+"('"+ this.id +"');");
  				break;
  			case "toggle_off":
  				if(this.settings["EA_toggle_off_callback"].length>0)
  					eval("parent."+this.settings["EA_toggle_off_callback"]+"('"+ this.id +"');");
  				break;
  			case "re_sync":
  				if(!this.do_highlight)
  					break;
  			case "file_switch_on":
  				if(this.settings["EA_file_switch_on_callback"].length>0)
  					eval("parent."+this.settings["EA_file_switch_on_callback"]+"(param);");
  				break;
  			case "file_switch_off":
  				if(this.settings["EA_file_switch_off_callback"].length>0)
  					eval("parent."+this.settings["EA_file_switch_off_callback"]+"(param);");
  				break;
  			case "file_close":
  				if(this.settings["EA_file_close_callback"].length>0)
  					return eval("parent."+this.settings["EA_file_close_callback"]+"(param);");
  				break;
  			
  			default:
  				if(typeof(eval("editArea."+cmd))=="function")
  				{
  					if(this.settings["debug"])
  						eval("editArea."+ cmd +"(param);");
  					else
  						try{eval("editArea."+ cmd +"(param);");}catch(e){};
  				}
  		}
  	};
  	
  	EditArea.prototype.get_translation= function(word, mode){
  		if(mode=="template")
  			return parent.editAreaLoader.translate(word, this.settings["language"], mode);
  		else
  			return parent.editAreaLoader.get_word_translation(word, this.settings["language"]);
  	};
  	
  	EditArea.prototype.add_plugin= function(plug_name, plug_obj){
  		for(var i=0; i<this.settings["plugins"].length; i++){
  			if(this.settings["plugins"][i]==plug_name){
  				this.plugins[plug_name]=plug_obj;
  				plug_obj.baseURL=parent.editAreaLoader.baseURL + "plugins/" + plug_name + "/";
  				if( typeof(plug_obj.init)=="function" )
  					plug_obj.init();
  			}
  		}
  	};
  	
  	EditArea.prototype.load_css= function(url){
  		try{
  			link = document.createElement("link");
  			link.type = "text/css";
  			link.rel= "stylesheet";
  			link.media="all";
  			link.href = url;
  			head = document.getElementsByTagName("head");
  			head[0].appendChild(link);
  		}catch(e){
  			document.write("<link href='"+ url +"' rel='stylesheet' type='text/css' />");
  		}
  	};
  	
  	EditArea.prototype.load_script= function(url){
  		try{
  			script = document.createElement("script");
  			script.type = "text/javascript";
  			script.src  = url;
  			script.charset= "UTF-8";
  			head = document.getElementsByTagName("head");
  			head[0].appendChild(script);
  		}catch(e){
  			document.write("<script type='text/javascript' src='" + url + "' charset=\"UTF-8\"><"+"/script>");
  		}
  	};
  	
  	// add plugin translation to language translation array
  	EditArea.prototype.add_lang= function(language, values){
  		if(!parent.editAreaLoader.lang[language])
  			parent.editAreaLoader.lang[language]={};
  		for(var i in values)
  			parent.editAreaLoader.lang[language][i]= values[i];
  	};
  	
  	// short cut for document.getElementById()
  	function _$(id){return document.getElementById( id );};
  
  	var editArea = new EditArea();	
  	parent.editAreaLoader.add_event(window, "load", init);
  	
  	function init(){		
  		setTimeout("editArea.init();  ", 10);
  	};
  