//id of active editor
var active_rich = null;

//prevent error messaging
window.onerror = no_error;

//parses toolbar button press event
function do_action(action,value){
var mode;
var sel;
var r;
var is_control;
var found;
var button_object;

	eval('mode = '+active_rich.name+'_rich_mode;');

	active_rich.focus(); //set focus on active editor
	re_hide_lists(); //hide all dropdowns

	button_object = get_button_object(action);
	if(!active_button(button_object)){ //button is inactive
		return;
	}

	//check if any control element is active, e.g. image or table
	var container_type;

	//do try to prevent errors when the editor in source mode
	try{
		sel = active_rich.getSelection();
		r = sel.getRangeAt(0);
		container_type = r.startContainer.nodeType;
	}catch(error){
	}

	if (container_type == 1) is_control = true;
		else is_control = false;

	found = true;
	switch(action){
		case 'Cut':					//cut
		case 'Copy':				//copy
		case 'Paste':				//paste
		case 'Undo':				//undo previous action
		case 'Redo':				//redo last cancelled action
		case 'Unlink':
			break;
		case 'Bold':				//set/unset bold style
		case 'Italic':				//set/unset italic style
		case 'Underline':			//set/unset undeline style
		case 'Strikethrough':		//set/unset strikethrough style
		case 'SuperScript':			//set/unset superscript style
		case 'SubScript':			//set/unset subscript style
		case 'JustifyFull':			//justify full
		case 'InsertOrderedList':	//insert ordered list
		case 'InsertUnorderedList':	//insert unordered list
		case 'Outdent':				//decrease indention
		case 'Indent':				//increase indention
		case 'InsertHorizontalRule'://insert horizontal line
		case 'RemoveFormat':		//remove text formatting
			if(is_control) found = false;
			break;
		case 'JustifyLeft':			//justify left
		case 'JustifyCenter':		//justify center
		case 'JustifyRight':		//justify right
			break;
		case 'FormatBlock':			//set paragraph style
		case 'FontName':			//set font
		case 'FontSize':			//set font size
			if(is_control || !value) found = false;
			break;
		case 'ClassName':			//set class
		set_class(value);
		found = false;
		break;
		case 'ForeColor':			//set foreground color
		case 'HiliteColor':			//set background color
			if(is_control){
				found = false;
				break;
			}
			if(!value) {
				pick_color(null, action, active_rich.document.queryCommandValue(action));
			}
			if (value == '') value = 'rgb(0, 0, 1)';
			break;
		case 'InsertRow':			//insert row in table
			found = false;
			if(is_control) break;

			if (value != null) {
				insert_row(value);
				switch_borders(false);//redraw borders under current border mode
			} else {
				insert_to('insert_row');
			}
			break;
		case 'DeleteRow':			//delete row from table
			found = false;
			if(is_control) break;
			delete_row();
		break;
		case 'InsertColumn':		//insert column in table
			found = false;
			if(is_control) break;

			if (value != null) {
				insert_column(value);
				switch_borders(false);//redraw borders under current border mode
			} else {
				insert_to('insert_column');
			}
		break;
		case 'DeleteColumn':		//delete column from table
			found = false;
			if(is_control) break;
			delete_column();
			break;
		case 'PasteWord':			//paste text from MSWord
			show_dialog('PasteWord');
			found = false;
			break;
		case 'SwitchBorders':		//show invisible table borders
			switch_borders(true);
			found = false;
			break;
		case 'InsertChar':			//insert a special character
			found = false;
			if (is_control) {
				var element = r.startContainer.childNodes[r.startOffset];
				if (!element || element.tagName != 'BR') break;
			}
			insert_char();
			break;
		case 'InsertCell':			//insert cell
			found = false;
			if(is_control) break;
			insert_cell();
			switch_borders(false);	//redraw borders under current border mode
			break;
		case 'DeleteCell':			//delete cell
			found = false;
			if(is_control) break;
			delete_cell();
			break;
		case 'MergeCells':			//merge cells
			found = false;
			if(is_control) break;
			merge_cells();
			break;
		case 'MergeCellsDown':		//merge cells vert
			found = false;
			if(is_control) break;
			merge_cells_down();
			break;
		case 'SplitCell':			//split cell
			found = false;
			if(is_control) break;
			split_cell();
			switch_borders(false);	//redraw borders under current border mode
			break;
		case 'SplitCellDown':		//split cell vert
			found = false;
			if(is_control) break;
			merge_cells_down(true);
			break;
		case 'FullScreen':			//switch on/off fullscreen mode
			full_screen(get_editor_name(button_object));
			found = false;
			break;
		case 'InsertSnippet':		//show snippet popup menu/insert a snippet
			if(value!=null) insert_snippet(value);
			found = false;
			break;
	case 'SpellCheck':			//call spell checker if exists
		if (openspell) {
			eval('var textarea = document.getElementById("'+active_rich.name+'_area_id");');
			textarea.value = get_rich(textarea.name);
			openspell(rich_path+'spelling/', textarea.id);
		}
		found = false;
		break;
	default:
			found = false;
			break;
	}

	if (action != 'HiliteColor') active_rich.document.execCommand('useCSS', false, true);
	if(found) active_rich.document.execCommand(action, false, value);

	if (action == 'ForeColor' || action == 'HiliteColor') {
		//change all span tags with fore or back color set to font tags
		var i;
		var spans = active_rich.document.getElementsByTagName('SPAN');

		for (i=0;i<spans.length;i++) {
			if (spans[i].style.color || spans[i].style.backgroundColor) {
				span2font(spans[i]);
			}
		}

		var fonts = active_rich.document.getElementsByTagName('FONT');
		for (i=0;i<fonts.length;i++) {
			var el = fonts[i];
			fix_font_style(fonts[i]);
		}
	}

	change_toolbar_state(); //set new states of toolbar buttons

}

//check if button 'element' is active
function active_button(element){
	if(element && element.className != 're_img_off') return true;
	return false;
}

//get object of button 'what'
function get_button_object(what){
var obj;

	//get button element
	eval('obj = document.getElementById("'+what+'_'+active_rich.name+'")');
	return obj;
}

//switch on/off fullscreen mode
function full_screen(editor_name){
var full_screen_mode;
var table_obj = document.getElementById(editor_name+'_table_id');
var div_obj = document.getElementById(editor_name+'_div_id');
var action;

	eval('full_screen_mode = '+active_rich.name+'_rich_full_screen_mode;');

	if(!full_screen_mode && rich_fs_mode_on){
		return;
	}

	full_screen_mode = full_screen_mode==true?false:true;
	set_state('FullScreen', full_screen_mode);
	eval(active_rich.name+'_rich_full_screen_mode = full_screen_mode;');

	if(full_screen_mode){
		div_obj.style.position = "Absolute";
		div_obj.style.zIndex = "999";
		div_obj.style.top = 0;
		div_obj.style.left = 0;

		var win_size = re_get_window_size();
		var width = win_size[0];
		var height = win_size[1];

		div_obj.style.width = String(width)+'px';
		div_obj.style.height = String(height)+'px';

		table_obj.style.position = "Absolute";
		table_obj.style.zIndex = "999";
		table_obj.style.top = 0;
		table_obj.style.left = 0;
		table_obj.style.width = String(width)+'px';
		table_obj.style.height = String(height)+'px';

		action = 'none';
	}else{
		table_obj.style.cssText = "";
		div_obj.style.cssText = "";

		action = '';
	}

	//hide wysiwyg areas of all other editors on the page as they do no let
	//cursor to be shown in source mode properly
	var editor = document.getElementsByTagName('IFRAME');
	var i;
	for(i=0;i<editor.length;i++){
		if(editor[i].className == 're_editor' && editor[i].name != editor_name){
			//do nothing if the editor in source mode
			eval('var mode = '+editor[i].name+'_rich_mode;');
			if (mode) {
				editor[i].style.display = action;

				if (action == '') { //restore designMode
					//do try to prevent error messages in source mode
					try{
						eval(editor[i].name + '_id.document.designMode = "On";');
					}catch(error){
					}
				}

			}

		}
	}

	//do try to prevent error messages in source mode
	try{
		eval(editor_name + '_id.document.designMode = "On";');
	}catch(error){
	}

	rich_fs_mode_on = full_screen_mode;

	active_rich.focus();

}

//changes states of toolbar buttons, when they are pressed/released
function mouse_down(down, element){
var mode;
var name;
var obj;

	if(element && element.tagName=='IMG'){
		name = get_editor_name(element);
		eval('mode = '+name+'_rich_mode;');

		if(!active_button(element)){ //button is inactive
			eval('obj = '+name+'_id;'); //editor of the current button
			if(obj) obj.focus();
			return;
		}

		if(down){ //pressed
			element.className = 're_mouse_down';
		}else{ //released
			element.className = 're_mouse_up';
		}

	}

}

//get width and height of current frame where editor is placed
function re_get_window_size(){
var width = Math.min(document.documentElement.offsetWidth, window.innerWidth);
	if (window.scrollMaxY &&
		width != document.documentElement.offsetWidth) width -= 16;
var height = window.innerHeight;
	if (window.scrollMaxX) height -= 16;

	return Array(width, height);
}

//changes state of toolbar button, when mouse is over it
function mouse_over(over, element){
var element;
var name;
var mode;
var obj;
var id_name;
var acrion_name;
var old_active_rich;
var button_name;
var changing_button;
var mode_name;

	if(element && element.tagName=='IMG'){
		name = get_editor_name(element);

		eval('mode = '+name+'_rich_mode;');

		eval('obj = '+name+'_id;'); //editor of the current button
		if(!obj) return;

		if(!active_button(element)) return; //button is inactive

		if(over){	//mouse is over button
			element.className = 're_mouse_over';
		}else{		//mouse is moved from the button
			id_name = String(element.id);
			action_name = id_name.substring(0,id_name.length-name.length-1);

			if(action_name == 'SwitchBorders' ||
				action_name == 'FullScreen'){//switch borders button

				if(action_name == 'SwitchBorders') mode_name = 'border';
					else mode_name = 'full_screen';

				eval('border_mode = '+obj.name+'_rich_'+mode_name+'_mode;');
				old_active_rich = active_rich;
				active_rich = obj;
				set_state(action_name, border_mode);
				active_rich = old_active_rich;
			}else{//common buttons

				button_name = (id_name.split('_'))[0];
				if(button_name == 'Bold' || button_name == 'Italic' ||
				button_name == 'Underline'|| button_name == 'Strikethrough' ||
				button_name == 'SuperScript' || button_name == 'SubScript' ||
				button_name == 'JustifyLeft' || button_name == 'JustifyCenter' ||
				button_name == 'JustifyRight' || button_name == 'JustifyFull' ||
				button_name == 'InsertOrderedList' ||
				button_name == 'InsertUnorderedList'){
					//button changing its state accordingly to text formatting
					changing_button = true;
				}else{
					changing_button = false;
				}

				var rich_doc = re_rich_doc();

				try{
					if(!changing_button ||
						!rich_doc.queryCommandState(action_name)){
						element.className = 're_mouse_out';
					}else{ //do button pressed
						element.className = 're_mouse_down';
					}
				} catch (e) {
					element.className = 're_mouse_out';
				}

			}

		}

	}

}

//get editor name of button 'element'
function get_editor_name(element){
var pos;
var button_id_parts;

	if(!element) return '';

	button_id_parts = element.id.match(/([^_]+)_(.+)$/);
	if(button_id_parts) return button_id_parts[2];
	return '';
}

//show/hide buttons depending on the current cursor position
function show_active_buttons(){
	try{
		var sel = active_rich.getSelection();
		var range = sel.getRangeAt(0);
		var is_control = range.startContainer.nodeType==1?true:false;
		var container = range.startContainer;
		var parent = container.parentNode;
		var container_type = container.nodeType;
	}catch(error){
		return;
	}

var i;
var text_button = Array('Bold', 'Italic', 'Underline', 'Strikethrough',
						'SuperScript', 'SubScript', 'JustifyLeft',
						'JustifyCenter', 'JustifyRight', 'JustifyFull',
						'InsertOrderedList', 'InsertUnorderedList',
						'Indent', 'Outdent', 'RemoveFormat',
						'ForeColor', 'HiliteColor', 'PasteWord', 'InsertChar');
var button_length = text_button.length;
var text_select = Array('FormatBlock', 'FontName', 'FontSize');
var select_length = text_select.length;
var td;
var tr;
var table;
var table_button = Array('InsertRow', 'DeleteRow', 'InsertColumn',
						'DeleteColumn', 'InsertCell', 'DeleteCell',
						'EditTable', 'EditCell');
var table_length = table_button.length;
var form_button = Array('CreateText', 'CreateTextArea', 'CreateButton', 'CreateSelect',
						'CreateHidden', 'CreateCheckBox', 'CreateRadio');
var form_length = form_button.length;
var visible;
var element;

var create_table = false;
var create_image = false;

var create_textfield = false;
var create_textarea = false;
var create_button = false;
var create_select = false;
var create_hidden = false;
var create_checkbox = false;
var create_radio = false;

	if(!active_rich) return;

	//if previous selection was a control
	eval('var prev_is_control = '+active_rich.name+'_prev_is_control;');
	//store current is_control value
	eval(active_rich.name+'_prev_is_control = '+is_control+';');

	if (is_control) element = container.childNodes[range.startOffset];
	if (element && element.tagName == "BR") var is_control = false;

	if(!is_control){ //no controls are selected
		show_button('CreateLink', range!=''?true:false);

		td = get_previous_object(parent,'TD');
		tr = get_previous_object(td,'TR');
		table = get_previous_object(td,'TABLE');

		//do cell buttons active/inactive
		for(i=0;i<table_length;i++){
			show_button(table_button[i], td?true:false);
		}

		//do MergeCells button active/inactive
		visible = tr && td.cellIndex<tr.cells.length-1;
		show_button('MergeCells', visible);
		//do SplitCell button active/inactive
		visible = tr && td.colSpan > 1;
		show_button('SplitCell', visible);

		//merge/split down
		show_button('MergeCellsDown',table&&tr.rowIndex+td.rowSpan<table.rows.length);
		show_button('SplitCellDown', td && td.rowSpan > 1);

		//redraw 'create control' buttons only if they actually changed
		//to accelerate editor
		if(prev_is_control != is_control){
			show_button('CreateTable', true);
			show_button('CreateImage', true);
			show_button('InsertHorizontalRule', true);
			show_button('CreateForm', true);
			show_button('InsertSnippet', true);

			//do form controls active
			for(i=0;i<form_length;i++){
				show_button(form_button[i], true);
			}
		}

	}else{ //a control element selected

		//do cell buttons inactive
		for(i=0;i<table_length;i++){
			show_button(table_button[i], false);
		}
		//do MergeCells button inactive
		show_button('MergeCells', false);
		show_button('SplitCell', false);
		show_button('MergeCellsDown', false);
		show_button('SplitCellDown', false);
 
		if(element){
			switch(element.tagName){
				case 'TABLE':
					create_table = true;
					break;
				case 'IMG':
					create_image = true;
					break;
				case 'INPUT':
					switch(element.type.toUpperCase()){
						case 'HIDDEN':
							create_hidden = true;
							break;
						case 'TEXT':
						case 'PASSWORD':
							create_textfield = true;
							break;
						case 'BUTTON':
						case 'RESET':
						case 'SUBMIT':
							create_button = true;
							break;
						case 'CHECKBOX':
							create_checkbox = true;
							break;
						case 'RADIO':
							create_radio = true;
							break;
						default:
						break;
					}
					break;
				case 'TEXTAREA':
					create_textarea = true;
					break;
				case 'SELECT':
					create_select = true;
					break;
				default:
					break;
			}
			show_button('CreateTable', create_table);
			show_button('CreateImage', create_image);
			show_button('CreateLink', true);
			show_button('InsertHorizontalRule', false);
			show_button('InsertSnippet', false);

			//change states of form buttons
			show_button('CreateForm', false);
			show_button('CreateHidden', create_hidden);
			show_button('CreateText', create_textfield);
			show_button('CreateTextArea', create_textarea);
			show_button('CreateButton', create_button);
			show_button('CreateSelect', create_select);
			show_button('CreateCheckBox', create_checkbox);
			show_button('CreateRadio', create_radio);

		}

	}

	//redraw text buttons and selects only if they actually changed
	//to accelerate editor
	if(prev_is_control != is_control){
	//do text buttons active/inactive
		for(i=0;i<button_length;i++){
			show_button(text_button[i], !is_control);
		}

		//do selects active/inactive
		for(i=0;i<select_length;i++){
			show_select(text_select[i], !is_control);
		}

	}

	var rich_doc = re_rich_doc();

	//undo and redo buttons
	visible = rich_doc.queryCommandEnabled('Undo');
	show_button('Undo', visible);
	visible = rich_doc.queryCommandEnabled('Redo');
	show_button('Redo', visible);

}

//change current editor mode
function change_mode(){
var mode;
var i;
var text;
var button_id_parts;
var button_name;
var text_area;
var rich_obj;
var border_mode;
var full_screen_mode;

	eval('mode = '+active_rich.name+'_rich_mode;');
	eval('border_mode = '+active_rich.name+'_rich_border_mode;');
	//text area
	eval('text_area = document.getElementById("'+active_rich.name+'_area_id");');
	//editor body
	eval('rich_obj = document.getElementById("'+active_rich.name+'_id");');
	//direction of language
	eval('var dir = '+active_rich.name+'_rich_dir;');
	eval('full_screen_mode = '+active_rich.name+'_rich_full_screen_mode;');

	text = get_rich_content(active_rich, true);

	if(mode){ //switch in source mode

		rich_obj.style.display = 'none';
		text_area.style.display = '';

		text_area.focus();

		//do toolbar buttons inactive
		for(i=0;i<document.images.length;i++){

			button_id_parts = document.images[i].id.match(/([^_]+)_(.+)$/);
			if(button_id_parts){
				button_name = button_id_parts[1];
				editor_name = button_id_parts[2];
				if(editor_name == active_rich.name){
					if(button_name != 'Help' && button_name != 'Preview' &&
						button_name != 'Save'){
						show_button(button_name, false);
					}
				}
			}

		}

		//do all select elements inactive
		show_select('FormatBlock', false);
		show_select('FontName', false);
		show_select('FontSize', false);
		show_select('ClassName', false);

		eval(active_rich.name+'_rich_mode = false;');

	}else{ //switch in wysiwyg mode

		rich_obj.style.display = '';
		text_area.style.display = 'none';

		rich_obj.contentWindow.document.designMode = "On";

		rich_obj.contentWindow.document.dir = dir;

		for(i=0;i<document.images.length;i++){

			button_id_parts = document.images[i].id.match(/([^_]+)_(.+)$/);
			if(button_id_parts){
				button_name = button_id_parts[1];
				editor_name = button_id_parts[2];
				if(editor_name == active_rich.name){
					show_button(button_name, true);
				}
			}

		}

		//do all select elements inactive
		show_select('FormatBlock', true);
		show_select('FontName', true);
		show_select('FontSize', true);
		show_select('ClassName', true);

		//redraw 'show borders' button
		set_state('SwitchBorders', border_mode);

		eval(active_rich.name+'_rich_mode = true;');

		active_rich.focus();
	}

	set_rich_content(active_rich, text); //set new content

	//do fullscreen mode button active/inactive
	show_button('FullScreen', full_screen_mode || !rich_fs_mode_on);
	set_state('FullScreen', full_screen_mode);

}

//delete base url from link
//if urls_only is set then delete base url from urls only not the whole text
function del_base_url(text, urls_only){
	var re_text = rich_base_url;
	var new_text = "";
	if (urls_only) {
		re_text = '((src|href|background)="?)' + re_text;
		new_text = "$1";
	}

var re = new RegExp(re_text, 'gi');
	RegExp.multiline = true;

	return text.replace(re, new_text);
}

//show/hide button 'what'
function show_button(what, show){
var element;

	//get button element
	eval('element = document.getElementById("'+what+'_'+active_rich.name+'")');

	if(!element) return; //the button is absent

	if(show){
		element.className = '';
	}else{
		element.className = 're_mouse_over';

		element.className = 're_img_off';
	}

}

//show/hide select control 'what'
function show_select(what, show){
var element;

	eval('element = document.getElementById("'+what+'_'+active_rich.name+'")');

	if(!element) return; //the element is absent
	element.disabled=!show;

}

//saves text of all editors in textarea objects (for form submit)
function save_in_textarea_all(){
var i;
var mode;
var name;
var text;
var text_area;
var i;
var editor = document.getElementsByTagName('IFRAME');

	for(i=0;i<editor.length;i++){
		if(editor[i].className == 're_editor'){
			eval('mode = '+editor[i].name+'_rich_mode;');
			
			if(!mode) continue;

			name = editor[i].name;
			eval("text=get_rich_content("+name+"_id)");
			//text area
			eval('text_area = document.getElementById("'+name+'_area_id");');
			text_area.value = text;

		}
	}
}

//find all document stylesheet rules and add their names to select object
function set_stylesheet_rules(){
var rule_values = new Array();
var rule_found = false;
var sheets;
var sheets_num;
var i,j,k;
var rules;
var rules_num;
var rule_value;
var rule_found;
var rules_select;
var option;
var old_rule_value;

	sheets = active_rich.document.styleSheets;
	sheets_num = sheets.length;

	//select object
	eval('rules_select = document.getElementById("ClassName_'+active_rich.name+'")');

	//there are some stylesheets
	if(sheets_num > 0){

		for(i=0;i<sheets_num;i++){
			if(!sheets[i]) continue;

			try {
				rules = sheets[i].cssRules;
			} catch(error) {
				continue;
			}
			if(rules == null) continue;
			rules_num = rules.length;

			for(j=0;j<rules_num;j++){
				rule_value = rules[j].selectorText;
				//in rules of the type 'td.toolbar span.delimiter{...}'
				//ignore all chars after space char
				rule_value = (rule_value.split(' '))[0];

				//rules MUST have '.' in their names, as it is user defined rules
				if(rule_value.indexOf(".") >= 0){

					//there is ':' char found in the rule name
					if(rule_value.indexOf(":") >= 0){

						//there are both '.' and ':' chars in the rule name
						rule_value = rule_value.substring(rule_value.indexOf(".")+1,rule_value.indexOf(":"));

					}else{

						//name begins with '.'
						if(rule_value.indexOf(".") == 0){
							rule_value = rule_value.substring(1,rule_value.length);
						}else{
							//name do not begins with '.'
							if(rule_value.indexOf(".") > 0){
								rule_value = rule_value.substring(rule_value.indexOf(".")+1,rule_value.length);
							}
						}

					}

					//prevent adding the the same rule names
					for(k=0;k<rule_values.length;k++){
						if(rule_value == rule_values[k]){
							rule_found = true;
							break;
						}
					}

					//new rule
					if(rule_found != true){
						rule_values[rule_values.length] = rule_value;
					}
					rule_found = false;

				}

			}

		}

		if(rules_select){

			//store selecter rule name
			old_rule_value = rules_select[rules_select.selectedIndex].value;

			//delete old classes from the select object, except first
			while(rules_select.options[1] != null){
				rules_select.options[1].parentNode.removeChild(rules_select.options[1]);
			}

			for(i=0;i<rule_values.length;i++){
				if(rule_values[i] != ''){
					option = document.createElement("option");
					option.value = rule_values[i];
					option.text = rule_values[i];
					rules_select.appendChild(option);
				}
			}

			rules_select.value = old_rule_value;

		}

	} else {
		//delete old classes from the select object, except first
		while(rules_select.options[1] != null){
			rules_select.options[1].parentNode.removeChild(rules_select.options[1]);
		}
	}

}

//set class attribute for current text or control element
function set_class(rule_value){
var sel = active_rich.getSelection();
var range = sel.getRangeAt(0);
var is_set;
var object;
var parentTagName;
var container = range.startContainer;
var parent = container.parentNode;
var container_type = container.nodeType;
var text;

	if(container_type == 1){
		object = container.childNodes[range.startOffset];
	}else{

		if(parent){

			parentTagName = parent.tagName.toUpperCase();

			text = String(range);
			if(text == ""){
				object = parent;
			}else{
				if(parentTagName=="SPAN" || parentTagName=="A"){

					object = parent;

				}else{
					if(rule_value != ""){
						try{
							var span = document.createElement("span");
							span.className = rule_value;
							span.innerHTML = text;
							paste_node(span);
						}catch(error){
							//do nothing on error, just prevent error message to user
						}
					}
					is_set = true
				}

			}

			if(0 && rule_value == "" && parentTagName == "SPAN"){
				object.removeNode(false);
				is_set = true;
			}

		}

	}

	if(object != null && is_set != true && object.tagName != 'BODY'){
		object.className = rule_value;
	}

}

//get class attribute for current text cursor position
function get_class(){
	try{
		var sel = active_rich.getSelection();
		var range = sel.getRangeAt(0);
		var container = range.startContainer;
		var container_type = range.startContainer.nodeType;
		var parent = container.parentNode;
	}catch(error){
		return "";
	}

var object = null;

	if (container_type == 1) {
		object = container.childNodes[range.startOffset];
	} else {
		object = parent;
	}

	if (object != null) {

		//to prevent search outside editor
		if (object.className == "re_editor") return "";

		//search class name among parents
		while (!object.className) {
			object = object.parentNode;
			if (object == null) return "";
		}

		return object.className;
	}
	return "";
}

//insert a node in the current editor
function paste_node(node, range_on_node) {
var sel = active_rich.getSelection();
var range = sel.getRangeAt(0);
var container = range.startContainer;
var container_type = container.nodeType;
var parent = container.parentNode;
	range.deleteContents(); //remove content selected
var start_pos = range.startOffset;
var end_pos = range.endOffset;

	if (container_type == 3) { //insert inside text

		sel.removeAllRanges();
		range=document.createRange();

		//text of the current container
		var text_node = document.createTextNode(container.nodeValue);

		//text before selection
		var prev_text = text_node.nodeValue.substr(0, start_pos);
		//text after selection
		var post_text = text_node.nodeValue.substr(end_pos);

		//make nodes from texts
		var prev_node = document.createTextNode(prev_text);
		var post_node = document.createTextNode(post_text);

		//insert nodes before existing
		parent.insertBefore(post_node, container);
		parent.insertBefore(node, post_node);
		parent.insertBefore(prev_node, node);

		parent.removeChild(container); //delete old container

		if (range_on_node) var r_node = node;
			else var r_node = post_node;
		range.setStart(r_node, 0);
		range.setEnd(r_node, 0);

		//move cursor at end of text changed
		sel.addRange(range);

	} else {
		container.insertBefore(node, container.childNodes[start_pos]);
	}

}

//show/hide borders of invisible objects
function set_borders(border_mode){
var tables = active_rich.document.getElementsByTagName("TABLE");
var forms = active_rich.document.getElementsByTagName("FORM");
var anchors = active_rich.document.getElementsByTagName("A");
var inputs = active_rich.document.getElementsByTagName("INPUT");
var page_mode;
var i,j,k;
var width;
var height;
var rows;
var cells;

	eval('page_mode = active_rich.window.'+active_rich.name+'_rich_page_mode;');

	for(i=0;i<tables.length;i++){

		if(border_mode){
			tables[i].style.border = '1px dashed #CCCCCC';
		}else{

			width = tables[i].style.width;
			height = tables[i].style.height;

			new_css = re_remove_border_style(tables[i].style.cssText);
			if (new_css != '') tables[i].style.cssText = new_css;
				else tables[i].removeAttribute("style");

			if(width) tables[i].style.width = width;
			if(height) tables[i].style.height = height;

		}

		rows = tables[i].rows;
		for(j=0;j<rows.length;j++){
			cells = rows[j].cells;
			for(k=0;k<cells.length;k++){
				if(border_mode){
					cells[k].style.border = '1px dashed #CCCCCC';
				}else{
					new_css = re_remove_border_style(cells[k].style.cssText);
					if (new_css != '') cells[k].style.cssText = new_css;
						else cells[k].removeAttribute("style");
				}
			}
		}

	}

	//show form borders
	for(i=0;i<forms.length;i++){
		if(border_mode){
			forms[i].style.border = '1px dotted #FF0000';
		}else{
			new_css = re_remove_border_style(forms[i].style.cssText);
			if (new_css != '') forms[i].style.cssText = new_css;
				else forms[i].removeAttribute("style");
		}
	}

	//show anchors
	for(i=0;i<anchors.length;i++){
		if(border_mode){
				if (anchors[i].href == "") {
					anchors[i].style.borderRight = '20px solid transparent';
					anchors[i].style.width = '20px';
					anchors[i].style.height = '20px';
					anchors[i].style.backgroundRepeat = 'no-repeat';
					anchors[i].style.backgroundImage = 'url('+rich_path+'images/anchor.gif)';
				}
		}else{
			anchors[i].removeAttribute("style");
		}
	}

	//show hidden fields
	for(i=0;i<inputs.length;i++){
		var type = String(inputs[i].type).toLowerCase();
		var tag_name2 = inputs[i].getAttribute('type2');
		if (tag_name2 && String(tag_name2).toLowerCase() == 'hidden') type = 'hidden';

		if (type != "hidden" && type != "hidden_field") continue;
		if(border_mode){
			inputs[i].type = "hidden_field";
			inputs[i].setAttribute('type2', 'hidden');
			inputs[i].style.border = '0px';
			inputs[i].style.borderRight = '20px solid transparent';
			inputs[i].style.width = '20px';
			inputs[i].style.height = '20px';
			inputs[i].style.backgroundRepeat = 'no-repeat';
			inputs[i].style.backgroundImage = 'url('+rich_path+'images/hidden.gif)';
		}else{
			inputs[i].type = "hidden";
			inputs[i].removeAttribute("style");
			inputs[i].removeAttribute("type2");
		}
	}

	active_rich.document.body.innerHTML = active_rich.document.body.innerHTML;

}

function re_remove_border_style(text) {
var parts = text.split(';');
var part_length = parts.length;
var attr_parts;
var new_text = '';

	for (var i=0; i<part_length; i++) {
		attr_parts = parts[i].split(':');
		if (attr_parts.length == 2 && (attr_parts[0] != 'border' ||
			attr_parts[1] != ' 1px dashed rgb(204, 204, 204)' &&
			attr_parts[1] != ' 1px dotted rgb(255, 0, 0)')) {
			new_text += attr_parts[0]+':'+attr_parts[1]+';';
			}
	}

	return new_text;
}

//change border mode
function switch_borders(change){
var border_mode;

	eval('border_mode = '+active_rich.name+'_rich_border_mode;');

	if(change){//change border visibility
		border_mode = border_mode==true?false:true;
		set_state('SwitchBorders', border_mode);
		eval(active_rich.name+'_rich_border_mode = border_mode;');
	}
	
	set_borders(border_mode);

}

//insert a special character
function insert_char(){
var w = 450;
var h = 300;

var win = window.open(rich_path+"dialog_char"+rich_dialog_ext+"?lang="+eval(active_rich.name+"_lang")+"&browser=ns&110903u",
		"dialog_char"+eval(active_rich.name+"_lang"),
		"modal=yes,width="+w+",height="+h+",left="+((screen.width-w)/2)+",top="+((screen.height-h)/2)+"\"");
	win.focus();
}

//changes current states of toolbar buttons
//according to style of text in current position of cursor
function change_toolbar_state(what){
var mode;
var active_mode;
var full_screen_mode;

	eval('active_mode = '+active_rich.name+'_rich_active_mode;');
	eval('full_screen_mode = '+active_rich.name+'_rich_full_screen_mode;');

	set_state('FullScreen', full_screen_mode);

	var is_control = false;
	try{
		var sel = active_rich.getSelection();
		var r = sel.getRangeAt(0);
		if (r.startContainer.nodeType==1) is_control = true;
	}catch(error){
		return;
	}

	if(!what || what == "ClassName")				set_style("ClassName", get_class());

	if (!is_control) {
	var rich_doc = re_rich_doc();

		if(!what || what == "FontName")				set_style("FontName", rich_doc.queryCommandValue('FontName'));
		if(!what || what == "FontSize")				set_style("FontSize", rich_doc.queryCommandValue('FontSize'));

		if(!what || what == "Bold")					set_state("Bold", rich_doc.queryCommandState('Bold'));
		if(!what || what == "Italic")				set_state("Italic", rich_doc.queryCommandState('Italic'));
		if(!what || what == "Underline")			set_state("Underline", rich_doc.queryCommandState('Underline'));
		if(!what || what == "Strikethrough")		set_state("Strikethrough", rich_doc.queryCommandState('Strikethrough'));
		if(!what || what == "SuperScript")			set_state("SuperScript", rich_doc.queryCommandState('SuperScript'));
		if(!what || what == "SubScript")			set_state("SubScript", rich_doc.queryCommandState('SubScript'));
		if(!what || what == "JustifyLeft")			set_state("JustifyLeft", rich_doc.queryCommandState('JustifyLeft'));
		if(!what || what == "JustifyCenter")		set_state("JustifyCenter", rich_doc.queryCommandState('JustifyCenter'));
		if(!what || what == "JustifyRight")			set_state("JustifyRight", rich_doc.queryCommandState('JustifyRight'));
		if(!what || what == "JustifyFull")			set_state("JustifyFull", rich_doc.queryCommandState('JustifyFull'));
		if(!what || what == "InsertOrderedList")	set_state("InsertOrderedList", rich_doc.queryCommandState('InsertOrderedList'));
		if(!what || what == "InsertUnorderedList")	set_state("InsertUnorderedList", rich_doc.queryCommandState('InsertUnorderedList'));

		if(!what || what == "FormatBlock")
			var container = r.startContainer;
			set_style("FormatBlock", get_font_block(container.parentNode));
	}

	if(active_mode){
		show_active_buttons();//make all buttons active/inactive
	}

}

//changes state of button 'what' to value
function set_state(what, value){
var element;

	//object to change
	eval('element = document.getElementById("'+what+'_'+active_rich.name+'")');

	if(element){
		if(value){	//pressed
			element.className = 're_mouse_down';
		}else{		//released
			element.className = 're_mouse_out';
		}
	}

}

//changes state of select element 'what' in value
function set_style(what, value){
var param = null;

	//correct format block name
	param = String(value).match(/Heading (.+)/);
	if(param) value = '<H'+param[1]+'>';

	if(value == 'Normal') value = '<P>';
	if(value == 'Formatted') value = '<PRE>';

	//object to change
	var element = document.getElementById(what+'_'+active_rich.name);
	if(element) element.value = String(value).toLowerCase();
}

//search among parents for a font block tag
function get_font_block(obj) {
	if(obj){
		//to prevent search outside editor
		if(obj.className == "re_editor" || !obj.tagName) return '<p>';

		var tag_name = obj.tagName.toUpperCase();
		//if P tag is inside of one of H tags then current block is H not P
		if(re_font_blocks.indexOf(tag_name + ',') < 0 || tag_name == 'P'){
			return get_font_block(obj.parentNode);
		}
		return('<' + tag_name.toLowerCase() + '>');
	}
	return('<p>');
}

//show dialog window to create/edit objects (table, image, ets)
function show_dialog(action, object){
var mode;
var is_control;
var attrib;
var parameters;
var link_text;
var element;
var link;
var i;
var param;
var outerHTML = '';
var text_class;
var button_object;
var is_br = false;

	eval('mode = '+active_rich.name+'_rich_mode;');

	active_rich.focus(); //set focus on active editor

	//in source mode toolbar dialog buttons do not work
	if(!mode && !(action == 'Help' || action == 'Preview' ||
		action == 'Save')) return;

	if(mode){
		try{
var sel = active_rich.getSelection();
var r = sel.getRangeAt(0);
var container = r.startContainer;
var container_type = container.nodeType;
		}catch(error){
			return;
		}
	}

	//check, if any control element is active (i.e. image or table)
	if(container_type == 1){
		is_control = true;
		element = container.childNodes[r.startOffset];
		if (!element) return;
		if (element.tagName == 'BR') is_br = true;
	}else is_control = false;

	switch(action){
		case "CreateTable": //create table
			if (!is_control || is_br) show_table_dialog(null, true);
			break;

		case "EditTable": //edit table
			if (get_previous_object(container.parentNode,'TABLE')) {
				show_table_dialog();
			}
			break;

		case "EditCell": //edit table cell
			//no selected text or controls
			if(is_control) break;

			if(container.parentNode){ //check, if text is inside a reference
			var td = get_previous_object(container.parentNode,'TD');
				if(td){
				var w = 330;
				var h = 180;
				var win = window.open(rich_path+"dialog_cell_ns"+rich_dialog_ext+"?lang="+eval(active_rich.name+"_lang")+"&re_ext="+rich_dialog_ext+"&110903c","dialog_cell"+eval(active_rich.name+"_lang"),"modal=yes,width="+w+",height="+h+",left="+((screen.width-w)/2)+",top="+((screen.height-h)/2)+"\"");
					win.focus();
				}
			}

		break;

		case "CreateImage": //create image
			if (is_control && element.tagName != 'IMG' && !is_br) break;
			show_image_dialog();
			break;

		case "CreateLink": //create reference
			if (is_control) {
				link = get_previous_object(element,'A');
			} else {
				if(container.parentNode){ //check, if text is inside a reference
					link = get_previous_object(container.parentNode,'A');
				} else link = null;
			}

			//no selected text or controls
			if(!link && !is_control && container_type != 3) break;

			if(!link && !is_control){ //it is a reference yet - edit it
				if (is_a_inside() != 'no') break; //there is a link inside
			}

			if(!link || link.innerHTML != "") show_link_dialog("");
			break;

		case "CreateAnchor":
			if(!is_control && container.parentNode){ //check, if text is inside a reference
				link = get_previous_object(container.parentNode,'A');
				if (link && link.href != '') break; //cursor is inside a link
			}
			if (is_a_inside() == 'empty' || link ||
				is_control && element.tagName == 'A' &&
				element.href=='') show_object_dialog('anchor');
			break;

		case "Help": //show help window

		var name = active_rich.name;
		var lang = eval(name+"_lang");
			window.open(rich_path+"lang/help_"+lang+rich_dialog_ext+"?lang="+lang,"re_help_"+lang,
						"toolbar=0,scrollbars=yes,resizable=yes");
			break;

		case "Preview": //preview of the current editor content
		var pre_window;
		var editor_content;
		var page_mode;
		var border_mode;
		var name;
		var abs_path;
		var i;

			//get the current editor content
			name = active_rich.name;
			eval('var mode = '+active_rich.name+'_rich_mode;');
 
			//default stypesheets
			eval('var rich_css = '+name+'_rich_css;');
			editor_content = get_rich_content(active_rich);
			
			//Coment Angelos
			//editor_content += get_default_stylesheets();
			
			pre_window = window.open('/preview.php', '', 'toolbar=yes,location=yes,status=yes,menubar=yes,scrollbars=yes,resizable=yes,titlebar=1');
			/* Coment Angelos
			pre_window = window.open('', '', 'toolbar=yes,location=yes,status=yes,menubar=yes,scrollbars=yes,resizable=yes,titlebar=1');
			pre_window.document.write(editor_content);
			pre_window.document.close();
			*/
			break;

		case "CreateForm": //insert a form
			if(!is_control || is_br){
				show_form_dialog("form");
			}
			break;

		case "CreateText": //insert a text field
			if(!is_control || is_br ||
				is_control && element.tagName == 'INPUT'
				&& (element.type.toUpperCase() == 'TEXT' ||
				element.type.toUpperCase() == 'PASSWORD')){
				show_form_dialog("text");
			}
			break;

		case "CreateTextArea": //insert a text area
			if(!is_control || is_br ||
			is_control && element.tagName == 'TEXTAREA'){
				show_form_dialog("textarea");
			}
			break;

		case "CreateButton": //insert a button
			if (!is_control || is_br ||
			is_control && element.tagName == 'INPUT' &&
			(element.type.toUpperCase() == 'BUTTON' ||
			element.type.toUpperCase() == 'RESET' ||
			element.type.toUpperCase() == 'SUBMIT')) {
				show_form_dialog("button");
			}
			break;

		case "CreateHidden": //insert a hidden field
			if(!is_control || is_br ||
			is_control && element.tagName == 'INPUT'
			&& element.getAttribute('type2') &&
			element.getAttribute('type2').toUpperCase() == 'HIDDEN'){
				show_form_dialog("hidden");
			}
			break;

		case "CreateCheckBox": //insert a checkbox
		case "CreateRadio": //insert a radiobox
		var element_type;
			if(action == 'CreateCheckBox'){
				element_type = 'checkbox';
			}else{
				element_type = 'radio';
			}

			if(!is_control || is_br ||
			is_control && element.tagName == 'INPUT' &&
			element.type.toUpperCase() == element_type.toUpperCase()){
				show_form_dialog(element_type);
			}
			break;

		case "CreateSelect": //insert a list box
			if(!is_control || is_br ||
			is_control && element.tagName == 'SELECT'){
				show_form_dialog("select");
		}
		break;

		case "InsertSnippet": //insert a snippet
			if(!is_control || is_br){
				show_form_dialog("snippet");
			}
			break;

		case "PasteWord": //paste word formatted text
			if(!is_control || is_br){
				show_form_dialog("paste_word");
			}

			break;

		case "PageProperties": //page properties
			show_page_dialog();
			break;

		case "Find": //show find&replace dialog

		var name = active_rich.name;
		var lang = eval(name+"_lang");
		var w = 400;
		var h = 150;

		var win = window.open(rich_path+"dialog_find"+rich_dialog_ext+"?lang="+lang+"&browser=ns&110903b","dialog_find"+name,"modal=yes,width="+w+",height="+h+",left="+((screen.width-w)/2)+",top="+((screen.height-h)/2)+"\"");
			win.focus();
			break;

		default:
			break;
	}

}

//show dialog window to create/edit table
function show_table_dialog(name, create_mode){
	return show_object_dialog('table', name, create_mode);

}

//show dialog window to create/edit image
function show_image_dialog(attrib, name){
	return show_object_dialog('image', name);
}

//show dialog window to create/edit reference
function show_link_dialog(attrib, name){
	return show_object_dialog('link', name);
}

//show dialog window to edit page properties
function show_page_dialog(){
	return show_object_dialog('page');
}

//show dialog window to create/edit various objects
function show_object_dialog(object, name, create_mode){
var w;
var h;

	if (!object) return;
	if (!name) var name = active_rich.name; //name of current editor
	if (create_mode) var do_create = 'true';
		else var do_create = '';

	var suffix = "_ns";

	switch(object){
		case 'table':
			w = 350;
			h = 415;
			break;
		case 'image':
			w = 415;
			h = 435;
			break;
		case 'link':
			w = 610;
			//h = 440;
			h = 550;
			break;

		case 'page':
			w = 350;
			h = 430;
			break;
		case 'anchor':
			w = 200;
			h = 10;
			suffix = "";
			break;
		default:
			return;
	}

	var win = window.open(rich_path+"dialog_"+object+suffix+rich_dialog_ext+"?files_path="+eval(name+"_files_path")+"&files_url="+eval(name+"_files_url")+"&browser=ns&lang="+eval(name+"_lang")+"&name="+name+"&do_create="+do_create+"&re_ext="+rich_dialog_ext+"&"+rich_sess_param+"&110903jfffffffw","dialog_"+object+eval(name+"_lang"),"modal=yes,width="+w+",height="+h+",left="+((screen.width-w)/2)+",top="+((screen.height-h)/2)+"\"");
	win.focus();

}

//show dialog window to pick color
function pick_color(name, action, color){
var color_str = '';
	if(!name) var name = active_rich.name; //name of current editor

	if (color) {
		color = dec2hex(color);
		color_str = "&color=%23"+color;
	}

	var w = 445;
	var h = 140;
	var win = window.open(rich_path+"pick_color_ns"+rich_dialog_ext+"?lang="+eval(name+"_lang")+'&action='+action+"&name="+name+color_str+"&110903b","dialog_color","modal=yes,width="+w+",height="+h+",left="+((screen.width-w)/2)+",top="+((screen.height-h)/2)+"\"");
	win.focus();
}

//search among parents an object with tag tag_name
function get_previous_object(obj,tag_name) {
	if (obj) {

		//to prevent search outside editor
		if (obj.className == "re_editor") return null;

		if (obj.tagName != tag_name){
			obj = get_previous_object(obj.parentNode, tag_name);
		}
	}
	return(obj);
}

//inserts row into current table just after current row
function insert_row(ins_to){
var sel = active_rich.getSelection();
var range = sel.getRangeAt(0);
var container = range.startContainer;
var tr;
var table;
var row;
var i;
var curr_colspan;

	tr = get_previous_object(container.parentNode,'TR');
	table = get_previous_object(tr,'TABLE');

	if(table != null){

		var cell_width = 100/tr.cells.length+'%';

		row = table.insertRow(tr.rowIndex+ins_to); //create new row
		for(i=0;i<tr.cells.length;i++){ //fill the row with columns
			var cell = row.insertCell(i);
			cell.innerHTML = '&nbsp;';

			var attr = new Array('width', 'height', 'vAlign', 'bgColor');
			var j;
			for (j in attr) {
				var attr_value = eval('tr.cells[i].getAttribute("'+attr[j]+'")');
				eval('if(attr_value) cell.setAttribute("'+attr[j]+'", attr_value)');
			}

			//take colspan values from the previous row cells
			curr_colspan = tr.cells[i].colSpan;
			if(curr_colspan > 1){
				cell.colSpan = curr_colspan;
			}
		}

	}

}

//deletes current row from current table
function delete_row(){
var sel = active_rich.getSelection();
var range = sel.getRangeAt(0);
var container = range.startContainer;
var tr;
var table;

	tr = get_previous_object(container.parentNode,'TR');
	table = get_previous_object(tr,'TABLE');

	if(table != null){
		if(table.rows.length <= 1){
			table.parentNode.removeChild(table); //it is the last row - delete whole table
		}else{
			table.deleteRow(tr.rowIndex); //delete row
		}

	}

}

//insert column in current table just after current column
function insert_column(ins_to){
var sel = active_rich.getSelection();
var range = sel.getRangeAt(0);
var container = range.startContainer;
var td;
var table;
var i;
var curr_rowspan;
var cell_index;
var rowspan_index;
var curr_index;

	td = get_previous_object(container.parentNode,'TD');
	table = get_previous_object(td,'TABLE');

	if(table != null){

		curr_index = td.cellIndex;
		//insert new cells in each row
		for(i=0;i<table.rows.length;i++){

			if(curr_index+ins_to > table.rows[i].cells.length){
				cell_index = table.rows[i].cells.length;
			}else{
				cell_index = curr_index+ins_to;
			}

			if(curr_index < table.rows[i].cells.length){
				rowspan_index = curr_index;
			}else{
				rowspan_index = table.rows[i].cells.length-1;
			}

			var j = -1;
			var attr = new Array('width', 'height', 'vAlign', 'bgColor');

			//take rowspan values from current column cells
			if (rowspan_index<0) curr_rowspan = 1;
				else {
					var tr = table.rows[i].cells[rowspan_index];
					curr_rowspan = tr.rowSpan;

					for (j in attr) {
						eval('var '+attr[j]+'=tr.getAttribute("'+attr[j]+'")');
					}
				}

			var cell = table.rows[i].insertCell(cell_index);
			cell.innerHTML = '&nbsp;';

			if(j != -1){
				for (j in attr) {
					eval('if('+attr[j]+') cell.setAttribute("'+attr[j]+'", '+attr[j]+')');
				}
			}

			if(curr_rowspan > 1){
				cell.rowSpan = curr_rowspan;
				i += curr_rowspan-1; //next curr_rowspan-1 cells are from another column
			}
		}

	}

}

//delete current column from current table
function delete_column(){
var sel = active_rich.getSelection();
var range = sel.getRangeAt(0);
var container = range.startContainer;
var td;
var table;
var i;
var tr;
var cell_index;

	td = get_previous_object(container.parentNode,'TD');
	table = get_previous_object(td,'TABLE');

	if (table != null) {
		cell_index = td.cellIndex;

		//delete cells from each row
		for (i=0;i<table.rows.length;i++) {

			tr = table.rows[i];
			if (tr.cells.length<=1) {
				//last cell in a row -- delete the row
				table.deleteRow(i);
				i--;
			} else {
				if (cell_index < tr.cells.length) {
					if (tr.cells[cell_index].rowSpan>1) {
						i+=tr.cells[cell_index].rowSpan-1;
					}
					tr.deleteCell(cell_index);
				}
			}

		}

		if (table.rows.length == 0) {
			//there are no rows - delete table
			table.parentNode.removeChild(table);
		}

	}

}

//insert cell in current table just after current cell
function insert_cell(){
var sel = active_rich.getSelection();
var range = sel.getRangeAt(0);
var container = range.startContainer;
var td;
var tr;

	td = get_previous_object(container.parentNode,'TD');
	tr = get_previous_object(td,'TR');

	if(tr != null){
		//insert new cell after current one
		tr.insertCell(td.cellIndex+1);
		var new_td = tr.cells[td.cellIndex+1];
		new_td.innerHTML = '&nbsp;';
	}

}

//delete current cell from current table
function delete_cell(){
var sel = active_rich.getSelection();
var range = sel.getRangeAt(0);
var container = range.startContainer;
var td;
var table;
var tr;

	td = get_previous_object(container.parentNode,'TD');
	tr = get_previous_object(td,'TR');
	table = get_previous_object(tr,'TABLE');

	if(table != null){

		if(tr.cells.length<=1){
			//it is the last cell in the row - delete row
			table.deleteRow(tr.rowIndex); //delete row

			if(table.rows.length == 0){
				//there are no rows - delete table
				table.parentNode.removeChild(table);
			}
		}else{
			tr.deleteCell(td.cellIndex);
		}

	}

}

//merge cells
function merge_cells(){ 
var sel = active_rich.getSelection();
var range = sel.getRangeAt(0);
var container = range.startContainer;
var td;
var tr;
var next_td;

	td = get_previous_object(container.parentNode,'TD');
	tr = get_previous_object(td,'TR');

	//check if the current cell is not last in the row
	if(tr != null && td.cellIndex < tr.cells.length-1){ 
		next_td = tr.cells[td.cellIndex+1];
		td.innerHTML += next_td.innerHTML; 
		td.colSpan += next_td.colSpan;
		tr.deleteCell(td.cellIndex+1); 
	} 

} 

//split cell
function split_cell(){
var sel = active_rich.getSelection();
var range = sel.getRangeAt(0);
var container = range.startContainer;
var td;
var tr;

	td = get_previous_object(container.parentNode,'TD');
	tr = get_previous_object(td,'TR');

	if(tr != null && td.colSpan > 1){
		td.colSpan--;
		tr.insertCell(td.cellIndex+1);
		var new_td = tr.cells[td.cellIndex+1];
		new_td.rowSpan = td.rowSpan;
		new_td.innerHTML = '&nbsp;';
		var width = tr.cells[td.cellIndex].width;
		new_td.setAttribute("width", width);
	}

} 

//merge/split cells down
function merge_cells_down(split_cell){ 
var next_td;

var sel = active_rich.getSelection();
var r = sel.getRangeAt(0);
var container = r.startContainer;

var td = get_previous_object(container.parentNode,'TD');
var tr = get_previous_object(td,'TR');
var table = get_previous_object(tr,'TABLE');

	//check if the current cell is not last in the row
	if (!(tr != null && (td.rowSpan > 1 && split_cell ||
				tr.rowIndex+td.rowSpan < table.rows.length && !split_cell)))
		return;

	var split_inc = split_cell?1:0;

	//find index of current td calculated using colspan values
	var i;
	var real_cell = 0;
	var real_cell2 = 0;
	for (i=0; i<tr.cells.length&&i<td.cellIndex; i++) {
		real_cell += tr.cells[i].colSpan;
		var inc = tr.cells[i].rowSpan-td.rowSpan+split_inc;
		real_cell2 += inc>0?tr.cells[i].colSpan:0;
	}

	var tr2 = table.rows[tr.rowIndex+td.rowSpan-split_inc];
	if (!tr2) return;
	var tr2_cells = tr2.cells;

	//find td in the row below to merge with current one
	for (i=0; i<tr2_cells.length; i++) {
		if (real_cell2 >= real_cell) break;
		real_cell2 += tr2_cells[i].colSpan;
	}

	if (!split_cell) {
		try {
			var td2 = tr2_cells[i];
		} catch(e){
			return;
		}

		if (!td2) return;
		td.innerHTML += td2.innerHTML;
		td.rowSpan += td2.rowSpan;
		tr2.deleteCell(i);
	} else {
		td.rowSpan--;
		try {
			var cell = tr2.insertCell(i);
		} catch(e){
			return;
		}

		if (!cell) return;

		cell.colSpan = td.colSpan;
		cell.innerHTML = '&nbsp;';
		eval('var border_mode = '+active_rich.name+'_rich_border_mode;');
		if (border_mode) cell.style.border = '1px dashed #CCCCCC';
	}

} 

//show dialog window to create/edit form
function show_form_dialog(action){
var w;
var h;

	switch(action){
		case 'form':
			w = 351;
			h = 160;
			break;
		case 'text':
			w = 243;
			h = 300;
			break;
		case 'textarea':
			w = 250;
			h = 285;
			break;
		case 'button':
			w = 253;
			h = 200;
			break;
		case 'hidden':
			w = 300;
			h = 160;
			break;
		case 'checkbox':
			w = 283;
			h = 205;
			break;
		case 'radio':
			w = 253;
			h = 205;
			break;
		case 'select':
			w = 331;
			h = 310;
			break;

		case 'snippet':
			w = 305;
			h = 363;
			break;
		case 'paste_word':
			w = 305;
			h = 300;
			break;
		default:
			w = 331;
			h = 200;
			break;
	}
	var win = window.open(rich_path+"dialog_form"+rich_dialog_ext+"?action="+action+"&browser=ns&lang="+eval(active_rich.name+"_lang")+"&110903b","dialog_form"+action+eval(active_rich.name+"_lang"),"modal=yes,width="+w+",height="+h+",left="+((screen.width-w)/2)+",top="+((screen.height-h)/2)+"\"");
	win.focus();

}

//insert a snippet value in the editor
function insert_snippet(value){
var sel = active_rich.getSelection();
var range;
var snippets;


	if(sel) range = sel.getRangeAt(0);
		else return;

	var container = range.startContainer;
	var container_type = container.nodeType;
	var is_br = re_is_br(range, container);

	if(value!=null && range && (container_type != 1 || is_br)){

		var s_parts = String(value).match(/^([^_]*)_([0-9]+)$/);
		if(!s_parts) return;
		var s_group = s_parts[1];
		var s_value = s_parts[2];

		eval('snippets = '+active_rich.name+'_snippets;'); //array of snippets
		if(snippets && snippets[s_group] && snippets[s_group][s_value] &&
			snippets[s_group][s_value][1]){
			paste_html(snippets[s_group][s_value][1]);
		}

	}

}

var re_font_blocks = 'P,H1,H2,H3,H4,H5,H6,PRE,';

function add_handlers(editor){
	eval('var ed_regs = '+active_rich.name+'_editable_regions;');
	if (ed_regs) return;

var re_onkeydown = function(e) {

	if (e.ctrlKey && (e.which == 86 || e.which == 118)) {
		eval('var clean_paste = '+active_rich.name+'_clean_paste;');
		if (clean_paste) {
			e.preventDefault();
			e.stopPropagation();
			do_action('PasteWord');
		}
	}

	eval('var br_on_enter = '+active_rich.name+'_br_on_enter;');
	if (br_on_enter) br_on_enter = true;

	if (br_on_enter == e.shiftKey && e.which == 13) {

	var sel = active_rich.getSelection();
	var range = sel.getRangeAt(0);
	var container = range.startContainer;

		var li_el = get_previous_object(container, 'LI');
		if (li_el) return;

		range.deleteContents(); //remove content selected
		var parent = container.parentNode;
		var parent_parent = parent.parentNode;

		if(parent && parent_parent &&
			re_font_blocks.indexOf(parent.tagName + ',') != -1) {

			var p_tag = parent.tagName;

			var node = document.createElement('P');
			node.innerHTML = '&nbsp;';

			//text of the current container
			var text_node = document.createTextNode(container.nodeValue);

			var start_pos = range.startOffset;
			var end_pos = range.endOffset;

			//text before selection
			var prev_text = text_node.nodeValue.substr(0, start_pos);
			//text after selection
			var post_text = text_node.nodeValue.substr(end_pos);

			var prev_text_node = document.createTextNode(prev_text);
			var post_text_node = document.createTextNode(post_text);

			//place content before and after P pasted inside p_tag tags
			var prev_node = document.createElement(p_tag);
			prev_node.appendChild(prev_text_node);

			//avoid of creating empty tags
			var post_node = null;
			if (post_text != '') {
				post_node = document.createElement(p_tag);
				post_node.appendChild(post_text_node);
			}

			//insert nodes before existing only if they are not empty
			if (post_node) {
				parent_parent.insertBefore(post_node, parent);
			} else post_node = parent; //to place node before parent
			parent_parent.insertBefore(node, post_node);
			if (prev_text != '') parent_parent.insertBefore(prev_node, node);

			parent_parent.removeChild(parent); //delete old container

			range.setStart(node, 0);
			range.setEnd(node, 0);

		} else {

			var new_obj = document.createElement('P');
			new_obj.innerHTML = '&nbsp;';
			paste_node(new_obj, true);

		}

		e.preventDefault();
		e.stopPropagation();
	}

};

var re_onmouseup = function(e){
	re_hide_lists();

	active_rich=editor;

	re_hide_context();

	change_toolbar_state();
};

var re_mouse_down = function(e){
	//no action on right click as it interfers with context functions
	if (e.which == 3) return;

	active_rich=editor;

	eval('var first_click = '+active_rich.name+'_first_click;');
	if (first_click) {
//need this trick to make RE show cursor first time it loads on
//mouse click inside its editing area in case initial value is empty string
		try{
			eval(active_rich.name + '_id.document.designMode = "Off";');
			eval(active_rich.name + '_id.document.designMode = "On";');
		}catch(error){
		}
		eval(active_rich.name+'_first_click = 0;');
	}
};

var re_contextmenu = function(e){
	re_hide_lists();

	active_rich=editor;

	re_hide_context();
	change_toolbar_state();

	//the next line creates div where no events (eg onmouseover) raise inside!
//	re_show_context(e.clientX, e.clientY);
	window.setTimeout("re_show_context("+eval("e.clientX")+", "+eval("e.clientY")+")", 10);

	e.preventDefault();
	e.stopPropagation();
};

var re_doc_click = function(e){
	re_hide_lists();
};

var re_onkeyup = function(e){

	active_rich=editor;

	//change toolbar if move cursor using keyboard or press Del only
	if (e.which > 36 && e.which < 41 ||	e.which == 8 || e.which == 46) {
		change_toolbar_state();
	} else {
		eval('var active_mode = '+active_rich.name+'_rich_active_mode;');

		if (active_mode) {
			var rich_doc = re_rich_doc();
			//undo and redo buttons
			show_button('Undo', rich_doc.queryCommandEnabled('Undo'));
		}
	}

};

	editor.document.addEventListener('keypress', re_onkeydown, true);
	editor.document.addEventListener('click', re_onmouseup, true);
	editor.document.addEventListener('contextmenu', re_contextmenu, true);
	editor.document.addEventListener('mousedown', re_mouse_down, true);

	document.addEventListener('click', re_doc_click, true);

	editor.document.addEventListener('keyup', re_onkeyup, true);
}

//hide context menu
function re_hide_context(){
var cx_div = document.getElementById('re_context_div_id');

	cx_div.style.display = 'none';

}

//set timeout to hide context menu when clicking somewhere outside editor
function re_start_hide_context(){
	document.removeEventListener('mouseup', re_start_hide_context, true);
	//to hide context menu after click on its item has been parsed
	window.setTimeout('re_hide_context()', 10);
}

//prepare html code for context menu
function re_show_context(x, y){
var height = 4;
var td_height = 20;
var hr_height = 4;
var char_width = 8;//13
var max_chars = 0;
var do_hr = false;
var flag = false;
var flag2 = false;
var element;

var innerHTML = '';
var is_control = false;

	try {
var sel = active_rich.getSelection();
var r = sel.getRangeAt(0);
var container = r.startContainer;
var container_type = container.nodeType;
var parent = container.parentNode;
	} catch(error) {
		return false;
	}

	//check, if any control element is active (i.e. image or table)
	if (container_type == 1) {
		element = container.childNodes[r.startOffset];
		if (!element) return false;
		if (element.tagName != 'BR') is_control = true;
	}

	eval('var mode = '+active_rich.name+'_rich_mode;');
	eval('var lang = '+active_rich.name+'_lang;'); //language
	eval('var mb = '+active_rich.name+'_rich_mb;'); //if multibyte language
	if (mb != '') char_width = 13;

	eval('var rich_cx = rich_cx_'+lang);
	eval('var rich_cx_item = rich_cx_item_'+lang);
	eval('var rich_cx_name = rich_cx_name_'+lang);
	eval('var rich_cx_image = rich_cx_image_'+lang);
	eval('var rich_cx_length = rich_cx_length_'+lang);


	if (mode) { //show context menu in wysiwyg mode

		if (!is_control) { //no controls are selected
			var link = get_previous_object(parent,'A');

			var do_image = get_button_object('CreateImage');

			var do_link = (link || container_type == 3 && is_a_inside() == 'no') &&
							get_button_object('CreateLink');

			var do_table = get_button_object('CreateTable');
			var do_form = get_previous_object(parent,'FORM') &&
							get_button_object('CreateForm');

			//set flag that before next group a ht separator is necessary
			if (do_image || do_link || do_table || do_form) {
				do_hr = true;
			}

			if (do_image) {
				innerHTML += get_popup_menu_item(rich_cx['ADDIMAGE'], 'CreateImage', 'image', null, true);
				max_chars=Math.max(max_chars, rich_cx['ADDIMAGE'].length);
				height += td_height;
			}
			if (do_link) {
				if (link) {
					link_name = rich_cx['EDITLINK']; //if link exists - edit it
					chars = rich_cx['EDITLINK'].length;
				} else {
					link_name = rich_cx['ADDLINK'];
					chars = rich_cx['ADDLINK'].length;
				}
				innerHTML += get_popup_menu_item(link_name, 'CreateLink', 'link', null, true);
				max_chars=Math.max(max_chars, chars);
				height += td_height;
			}
			if (do_form) {
				innerHTML += get_popup_menu_item(rich_cx['EDITFORM'], 'CreateForm', 'form', null, true);
				max_chars=Math.max(max_chars, rich_cx['EDITFORM'].length);
				height += td_height;
			}

			if (do_table) {
				innerHTML += get_popup_menu_item(rich_cx['ADDTABLE'], 'CreateTable', 'table', null, true);
				max_chars=Math.max(max_chars, rich_cx['ADDTABLE'].length);
				height += td_height;

				var td = get_previous_object(parent,'TD');
				var tr = get_previous_object(td,'TR');
				var table = get_previous_object(tr,'TABLE');

				if (td) {
					innerHTML += get_popup_menu_item(rich_cx['TABLE'][0], 'EditTable', 'table_prop', null, true);
					max_chars=Math.max(max_chars, rich_cx['TABLE'][0].length);
					height += td_height;

					innerHTML += get_popup_menu_item(rich_cx['EDITCELL'], 'EditCell', 'cell_prop', null, true);
					max_chars=Math.max(max_chars, rich_cx['EDITCELL'].length);
					height += td_height;

					//add cell items
					for(i=0;i<rich_cx_length;i++){
						if(get_button_object(rich_cx_item[i])){
							//first common table button
							if(i<=3 && do_hr && !flag2){
								innerHTML += get_popup_menu_item('<HR>');
								height += hr_height;
								flag2 = true;
							}
							//common table buttons passed
							if(i>3 && do_hr && !flag){
								innerHTML += get_popup_menu_item('<HR>');
								height += hr_height;
								flag = true;
							}
							innerHTML += get_popup_menu_item(rich_cx_name[i],
										rich_cx_item[i], rich_cx_image[i]);
							max_chars=Math.max(max_chars, rich_cx_name[i].length);
							height += td_height;
							do_hr = true;
						}
					}

				}

				//add MergeCells item
				if(tr && td.cellIndex<tr.cells.length-1 &&
					get_button_object('MergeCells')){
					if(!flag){
						innerHTML += get_popup_menu_item('<HR>');
						height += hr_height;
						flag = true;
					}
					innerHTML += get_popup_menu_item(rich_cx['MERGE'], 'MergeCells', 'mergecells');
					max_chars=Math.max(max_chars, rich_cx['MERGE'].length);
					height += td_height;
				}
				//add SplitCell item
				if(tr && td.colSpan > 1 && get_button_object('SplitCell')){
					if(!flag){
						innerHTML += get_popup_menu_item('<HR>');
						height += hr_height;
					}
					innerHTML += get_popup_menu_item(rich_cx['SPLIT'], 'SplitCell', 'splitcell');
					max_chars=Math.max(max_chars, rich_cx['SPLIT'].length);
					height += td_height;
				}

				//add Merge/Split down items
				if(table && tr.rowIndex+td.rowSpan<table.rows.length &&
					get_button_object('MergeCellsDown')){
					if(!flag){
						innerHTML += get_popup_menu_item('<HR>');
						height += hr_height;
						flag = true;
					}
					innerHTML += get_popup_menu_item(rich_cx['MERGEDOWN'], 'MergeCellsDown', 'mergecellsdown');
					max_chars=Math.max(max_chars, rich_cx['MERGEDOWN'].length);
					height += td_height;
				}

				if(td && td.rowSpan > 1 && get_button_object('SplitCellDown')){
					if(!flag){
						innerHTML += get_popup_menu_item('<HR>');
						height += hr_height;
					}
					innerHTML += get_popup_menu_item(rich_cx['SPLITDOWN'], 'SplitCellDown', 'splitcelldown');
					max_chars=Math.max(max_chars, rich_cx['SPLITDOWN'].length);
					height += td_height;
				}

			}

		} else {
			var tag_name = element.tagName;
			if (tag_name == 'INPUT') {
				tag_name = element.type.toUpperCase();
				var tag_name2 = element.getAttribute('type2');
				if (tag_name2 && String(tag_name2).toUpperCase() == 'HIDDEN') tag_name = 'HIDDEN';
			}

			if (tag_name != 'HIDDEN' && get_button_object('CreateLink')) {

				if (do_hr) {
					innerHTML += get_popup_menu_item('<HR>');
					height += hr_height;
				}
				//check, if control is inside a reference
				var link=get_previous_object(element, 'A');
				var action = 'CreateLink';
				if (link) {
					if (link.href == "") {
						link_name = rich_cx['EDITANCHOR'];
						action = 'CreateAnchor';
					} else link_name = rich_cx['EDITLINK'];
				} else link_name = rich_cx['ADDLINK'];
				innerHTML += get_popup_menu_item(link_name, action, 'link', null, true);
				max_chars=Math.max(max_chars, link_name.length);
				height += td_height;
				do_hr = true;
			}

			//insert the control's 'Edit' item
			if (rich_cx[tag_name] && get_button_object(rich_cx[tag_name][1])) {
				if (do_hr) {
					innerHTML += get_popup_menu_item('<HR>');
					height += hr_height;
				}
				innerHTML += get_popup_menu_item(rich_cx[tag_name][0],
					rich_cx[tag_name][1], rich_cx[tag_name][2], null, true);
				max_chars=Math.max(max_chars, rich_cx[tag_name][0].length);
				height += td_height;
				do_hr = true;
			}

		}

	} else return false;

	if (innerHTML == '') return false;

	var width = max_chars*char_width+40;

	innerHTML = get_popup_menu_body(innerHTML);

	var cx_div = document.getElementById('re_context_div_id');
	var ed_pos = get_element_pos(active_rich.frameElement);

	//inner width and height of window
	var win_size = re_get_window_size();
	var check_left = x+ed_pos[0];
	var check_top = y+ed_pos[1];

	//move context div to make it fully visible
	if (check_left + width - document.documentElement.scrollLeft -
		document.body.scrollLeft>
		win_size[0]) check_left = win_size[0] - width +
			document.documentElement.scrollLeft + document.body.scrollLeft;
	if (check_top + height - document.documentElement.scrollTop -
		document.body.scrollTop >
		win_size[1]) check_top = win_size[1] - height +
			document.documentElement.scrollTop + document.body.scrollTop;
	check_left = Math.max(check_left, 0);
	check_top = Math.max(check_top, 0);

	cx_div.style.left = check_left+'px';
	cx_div.style.top = check_top+'px';

	cx_div.innerHTML = innerHTML;

	cx_div.style.display = '';

	//set handler to hide context div when click somewhere outside editor
	document.addEventListener('mouseup', re_start_hide_context, true);

	return innerHTML;
}

//get html code of popup item with name 'name'
//if the item is chosen, an event action is generated with value 'value'
//ie if is_dialog null or false do_action(action,value) called
//otherwise show_dialog(action) called
function get_popup_menu_item(name, action, img_name, value, is_dialog){
var code = '';

	code += '<tr>';
	if(name != '<HR>'){
		code += '<td id="rich_cx_'+action+'" onclick="';
		if(is_dialog){
			code += 'show_dialog(\''+action+'\');';
		}else{
			code += 'do_action(\''+action+'\'';
			if(value != null) code += ',\''+value+'\'';
			code += ');';
		}
		code += ' re_hide_context();" style="cursor:pointer; font-family:Courier; font-size:13px;"';
		code += ' onmouseover="context_over(this, true);"';
		code += ' onmouseout="context_over(this);">';
	}else{
		code += '<td height="4">';
	}

	code += '<nobr>';
	if(img_name){
		code += '<img src="'+rich_path+'images/'+img_name+'.gif" width="20" height="20" alt="'+name+'" align="absmiddle" hspace="4">';
	}else{
		code += '<img src="'+rich_path+'images/space.gif" width="20" height="1" hspace="4">';
	}

	if(name != '<HR>'){
		code += name;
	}else{
		code += '<br><img src="'+rich_path+'images/space.gif" width="100%" height="1" style="BACKGROUND-COLOR: buttonshadow"><br>';
		code += '<img src="'+rich_path+'images/space.gif" width="100%" height="1" style="BACKGROUND-COLOR: buttonhighlight"><br>';
	}

	code += '<img src="'+rich_path+'images/space.gif" width="8" height="1"></nobr>';
	code += '</td></tr>';

	return code;
}

//add to popup content innerHTML outer code
function get_popup_menu_body(innerHTML){
var code = '';

	code += '<table cellspacing="0" cellpadding="0" border="0" class="re_context">';
	code += '<tr><td>';
	code += '<table id="popup_table" cellspacing="0" cellpadding="0" border="0" class="re_context_inner" width="100%" height="100%">';
	code += innerHTML;
	code += '</table>';
	code += '</td></tr>';
	code += '</table>';

	return code;
}

//highlight context menu item
function context_over(obj, over){
	if(over){
		obj.style.backgroundColor = 'Highlight';
		obj.style.color = 'HighlightText';
	}else{
		obj.style.backgroundColor = '';
		obj.style.color = '';
	}
}

//get (left, top) coordinates of element obj
function get_element_pos(obj){
var pos = Array(0,0);
	while (obj) {

		//absolute positioned element => do not count its offset values
		if (document.defaultView.getComputedStyle(obj, '').getPropertyValue('position') == 'absolute') break;

		pos[0] += obj.offsetLeft;
		pos[1] += obj.offsetTop;
		obj = obj.offsetParent;
	}
	return pos;
}

function paste_html(html){
var border_mode;
var el = document.createElement("SPAN"); //create object - tag SPAN

	eval('border_mode = '+active_rich.name+'_rich_border_mode;');

	el.innerHTML = html;

	paste_node(el); //insert content in editor

	//delete outer span tag
	if (el.parentNode && el.childNodes) {
		var i;
		var child_nodes_length = el.childNodes.length;
		for (i=0;i<child_nodes_length;i++) {
			if (el.childNodes[i]) {
				var new_node = el.childNodes[i].cloneNode(el.childNodes[i]);
				el.parentNode.insertBefore(new_node, el);
			}
		}
		el.parentNode.removeChild(el);
	}

	//set/unset borders
	set_borders(border_mode);
}

//paste MSWord formatted text from clipboard
function paste_word(html){

	paste_html(clean_code(html));
	active_rich.focus(); //set focus on active editor

}

function clean_code(code) {
	// get rid of silly space tags
	code = code.replace(/&nbsp;/gi, "");
	// gets rid of all xml stuff... <xml>,<\xml>,<?xml> or <\?xml>
	code = code.replace(/<\\?\??xml[^>]*>/gi, "");
	// get rid of ugly colon tags <a:b> or </a:b>
	code = code.replace(/<\/?\w+:[^>]*>/gi, "");
	// removes all empty <p> tags
	code = code.replace(/<p([^>])*>(&nbsp;)*\s*<\/p>/gi,"");
	// removes all span tags
	code = code.replace(/<\/?span[^>]*>/gi,"");
	// removes all Class attributes on a tag eg. '<p class=asdasd>xxx</p>' returns '<p>xxx</p>'
	code = code.replace(/<([\w]+) class=([^ |>]*)([^>]*)/gi, "<$1$3");
	// removes all style attributes eg. '<tag style="asd asdfa aasdfasdf" something else>' returns '<tag something else>'
	code = code.replace(/<([^>]+) style="([^"]*)"([^>]*)/gi, "<$1$3");

	return code
}

//dont need to restore borders in change_mode - works faster
function get_rich_content(editor, dont_restore_borders) {

	if (!editor) return '';

var content;
var old_active_rich = active_rich;
var i;

	active_rich = editor;

	//get the current editor content
	var name = active_rich.name;
	eval('var mode = '+active_rich.name+'_rich_mode;');
	var xhtml_mode = get_xhtml_mode(); //must be after 'active_rich = editor;'

	if(!mode){ //source code mode
		//text area
		eval('var text_area = document.getElementById("'+active_rich.name+'_area_id");');

		content = text_area.value;

	}else{
		eval('var page_mode = '+name+'_rich_page_mode;');
		eval('var border_mode = '+name+'_rich_border_mode;');
		eval('var abs_path = '+name+'_rich_absolute_path;');

		if(border_mode){
			set_borders(false);
		}

		if (xhtml_mode) {

			//document lang
			eval('var doc_lang = '+active_rich.name+'_rich_doc_lang;');
			//document charset
			eval('var doc_charset = '+active_rich.name+'_rich_doc_charset;');

			if(!page_mode){
				content = get_xhtml(active_rich.document.documentElement,
											doc_lang, doc_charset);
			}else{
				content = get_xhtml(active_rich.document,
											doc_lang, doc_charset);
			}

		} else {

			content = active_rich.document.documentElement.innerHTML;

			if(!page_mode){
				content = content.replace(/<\/?head>/gi, "");
				content = content.replace(/<\/?body>/gi, "");
			}else{
				content = '<html>'+content+'</html>';
			}

		}

		content = delete_default_stylesheets(content);

		//convert &amp; to & otherwise src and href arributes could be spoiled
		var re = new RegExp('&amp;', 'gi');
		RegExp.multiline = true;
		content = content.replace(re, '&');

		//asp/php tags fix
		content = content.replace(/<!--re_php_tag_open/g, '<?php');
		content = content.replace(/re_php_tag_close-->/g, '?>');
		content = content.replace(/<!--re_asp_tag_open/g, '<%');
		content = content.replace(/re_asp_tag_close-->/g, '%>');

		content = format_content(content);

		if(!abs_path) content = del_base_url(content, 1);

		content = content.replace(/<b>/gi, '<strong>');
		content = content.replace(/<\/b>/gi, '</strong>');
		content = content.replace(/<b /gi, '<strong ');
		content = content.replace(/<i>/gi, '<em>');
		content = content.replace(/<\/i>/gi, '</em>');
		content = content.replace(/<i /gi, '<em ');

		if(border_mode && !dont_restore_borders){
			set_borders(true);
		}

	}

	active_rich = old_active_rich;

	return content;
}

//add default seylesheet tags
function get_default_stylesheets(){
var i;
var text = '';

	//default stylesheets
	eval('var rich_css = '+active_rich.name+'_rich_css;');

	//add links to default stylesheets
	for (i in rich_css) {
		var link_text = '<link rel="stylesheet" href="'+rich_css[i]+'" type="text/css">';
		text += link_text;
	}

	return text;
}

//remove all default stylesheet tags
function delete_default_stylesheets(editor_content){
var i;
var name = active_rich.name;
var xhtml_mode = get_xhtml_mode();

//remove default stylesheets' tags
eval('var rich_css = '+name+'_rich_css;');

	if (xhtml_mode) var ch = " /";
		else var ch = "";

	//remove links to default stylesheets
	for (i in rich_css) {
		var re = new RegExp('<link rel="stylesheet" href="'+rich_css[i]+'" type="text/css"'+ch+'>','gi');
		var re2 = new RegExp('<link type="text/css" href="'+rich_css[i]+'" rel="stylesheet"'+ch+'>','gi');
		RegExp.multiline = true;

		editor_content=editor_content.replace(re2,'');
		editor_content=editor_content.replace(re,'');
	}

	return editor_content;
}

//return content of editor with name 'name' - user javascript API function
function get_rich(name) {
	if (!name) return '';

	if (!active_rich) {
	var base_info = get_editor_base_info(name);

		eval('var text_area = document.getElementById("'+base_info['name']+'_ed'+base_info['id']+'_area_id");');
		return text_area.value;
	}

	return get_rich_content(get_editor_id(name));
}

//set content to editor with name 'name'
function set_rich(name, content) {
	if (!name) return '';

	if (!active_rich) {
	var base_info = get_editor_base_info(name);

		eval('var text_area = document.getElementById("'+base_info['name']+'_ed'+base_info['id']+'_area_id");');
		text_area.value = content;
		return true;
	}

	return set_rich_content(get_editor_id(name), content);
}

//get editor id by its name
function get_editor_id(name) {

	var base_info = get_editor_base_info(name);
	eval('var editor = '+base_info['name']+'_ed'+base_info['id']+'_id;'); //get editor's id

	return editor;
}

//get editor base info (common for iframe and textarea) by its name
function get_editor_base_info(name) {
var id;
var base_info = new Array();
	base_info['id'] = '';
	base_info['name'] = name;

	var ar_pos = name.indexOf("[");
	var id = '';
	if (ar_pos > 0) {
		var ar_end_pos;
		ar_end_pos = name.length-1;

		id = name.substring(ar_pos+1, ar_end_pos);
		base_info['name'] = name.substring(0, ar_pos);

		var parts = id.split('][');
		if (parts) {
			id = parts.join('_')
		} else id = '';

		base_info['id'] = id;
	}

	return base_info;
}

//write html text from variable content to editor
function set_rich_content(editor, content){
	if (!editor) return;

var mode;
var page_mode;
var border_mode;
var i;
var text;
var button_id_parts;
var button_name;
var editror_name;
var text_area;
var rich_obj;
var old_active_rich = active_rich;

	active_rich = editor;

	eval('mode = '+active_rich.name+'_rich_mode;');
	eval('page_mode = '+active_rich.name+'_rich_page_mode;');
	eval('border_mode = '+active_rich.name+'_rich_border_mode;');
	eval('text_area = document.getElementById("'+active_rich.name+'_area_id");');
	eval('rich_obj = document.getElementById("'+active_rich.name+'_id");');
	var xhtml_mode = get_xhtml_mode(); //must be after 'active_rich = editor;'

	text = content;

	if(!mode){ //source mode

		if(!page_mode || xhtml_mode){
		}else{
			text = '<html>'+text+'</html>';
		}

		text_area.value = text;

	}else{ //wysiwyg mode
		//asp/php tags fix
		text = text.replace(/<\?php/gi, '<!--re_php_tag_open');
		text = text.replace(/\?>/g, 're_php_tag_close-->');
		text = text.replace(/<%/g, '<!--re_asp_tag_open');
		text = text.replace(/%>/g, 're_asp_tag_close-->');

		if(!page_mode){

			if (!text) text = '<br>';

			text += get_default_stylesheets();

//		rich_obj.contentWindow.document.designMode = "On";
			var head_tag = active_rich.document.getElementsByTagName('HEAD')[0];
			head_tag.innerHTML = '';
			active_rich.document.body.innerHTML = text;
		}else{

			var head = '';
			var body = '<br>';

			if (text != '') {

				var head_parts = text.split(/<[\/]?head[^>]*>/);
				if (head_parts[1]) head = head_parts[1];

				var body_parts = text.split(/<[\/]?body[^>]*>/);
				if (body_parts[1]) body = body_parts[1];

				//parse body attributes
				var body_attr = null;
				var body_temp = text.split(/<body /);
				if (body_temp[1]) {
					body_attr = body_temp[1].split(/>/)[0];
				}
				var attribs;
				if(body_attr){
					attribs = body_attr.split(/[ \t]+/);
				}else attribs = null;

			}

			active_rich.document.body.innerHTML = '';
			active_rich.document.body.innerHTML = body;
			var head_tag = active_rich.document.getElementsByTagName('HEAD')[0];

			//delete old body tag attributes
			var old_attr = active_rich.document.body.attributes;
			var old_attr_length = old_attr.length;
			for (i=0;i<old_attr_length;i++) {
				active_rich.document.body.removeAttribute(old_attr.item(0).name);
			}

			//set new body tag attributes
			if (body_attr) {
				for (i in attribs){
					var value = attribs[i].match(/([^=]*)=(.*)/);
					if(value){
						if(value[1] == 'style'){
							active_rich.document.body.style = value[2];
						}else active_rich.document.body.setAttribute(value[1],value[2].replace(/\"/g,''));
					}
				}
			}

			head += get_default_stylesheets();

			head_tag.innerHTML = head;

		}

		//set borders
		if(border_mode){
			set_borders(true);
		}

		set_stylesheet_rules();//update class info

	}

	active_rich = old_active_rich;

	return true;
}

function get_xhtml_mode(){

	eval('var xhtml_mode = '+active_rich.name+'_rich_xhtml_mode;');

	try { //check if xhtml jscript function loaded
		var is_xhtml = get_xhtml?true:false;
	} catch(e) {
		var is_xhtml = false;
	}

	return xhtml_mode&&is_xhtml?true:false;
}

//convert span object el to font
function span2font(el){
	if (!el) return;

var i,j;

var child_spans = el.getElementsByTagName('SPAN');
var child_length = child_spans.length;

	//parse child span tags
	for (i=0;i<child_length;i++) {
		span2font(child_spans[i]);
	}

var new_node = document.createElement('FONT');
	new_node.innerHTML = el.innerHTML;

var attr = el.attributes;
var attr_length = attr.length;

	//copy attributes to font tag
	for (j=0;j<attr_length;j++) {
		if (!attr[j].specified) continue;

		var attr_name = attr[j].nodeName.toLowerCase();
		if (attr_name = 'style') {
			new_node.style.cssText = el.style.cssText;
		} else {
			if (attr_name == 'class') {
				new_node.className = el.className;
			} else {
				new_node.setAttribute(attr_name, el.getAttribute(attr_name, 2)); 
			}
		}

	}

	el.parentNode.insertBefore(new_node, el);
	el.parentNode.removeChild(el);

}

//fix font style attribute if fore or back color unset
function fix_font_style(el){
	var css_text = String(el.style.cssText);
	css_text = css_text.replace('background-color: rgb(0, 0, 1);', '');
	css_text = css_text.replace('color: rgb(0, 0, 1);', '');
	css_text = css_text.replace(/(^\s+)|(\s+$)/,'');
	if (css_text == '') el.removeAttribute('style');
		else el.style.cssText = css_text;
}

//convert color from decimal value 'rgb(n, n, n)' to heximal
function dec2hex(num) {
var colors = num.match(/rgb\(([0-9]+), ([0-9]+), ([0-9]+)\)/);
var i;
var hex_num = '';

	if (colors) {
		for (i=1;i<=3;i++) {
			var d1 = colors[i]>>4;
			var d2 = colors[i]&0x0f;

			hex_num += d1.toString(16)+d2.toString(16);
		}
		return hex_num;
	}
	return 'ffffff';
}

//determine where to insert row/column
function insert_to(action) {
var sel = active_rich.getSelection();
var range = sel.getRangeAt(0);
var container = range.startContainer;

	if(!get_previous_object(container.parentNode,'TABLE')) return;

	var lang = eval(active_rich.name+"_lang");

	var w = 300;
	var h = 100;
	var win = window.open(rich_path+"dialog_adv_table"+rich_dialog_ext+"?lang="+lang+"&action="+action+"&browser=ns&110903f","dialog_adv_table"+lang,"modal=yes,width="+w+",height="+h+",left="+((screen.width-w)/2)+",top="+((screen.height-h)/2)+"\"");
	win.focus();
}

//enable select control disabled earlier to prevent showing list items
function re_enable(id) {
var obj = document.getElementById(id);
	obj.disabled = false;
}

//show items of list sel_obj
//if h2content then make all items visible (no vertical scrollbar)
function re_show_list(sel_obj, h2content){
var i;
var j;

	re_hide_context();

var obj = document.getElementById(sel_obj.id + '_iframe');

	if (obj.style.display == '') {
		obj.style.display = 'none';
		return;
	}

	re_hide_lists();

	var obj_doc = obj.contentWindow.document;

	//type of dropdown list
	var parts = String(obj.id).split('_');
	var type = parts[0];

	var style_text = '';

	if (type == 'ClassName') {
		//take styles of the current window
		var styles = active_rich.document.styleSheets;
		var sheets_num = styles.length;
		for (i=0; i<sheets_num; i++) {

			var rules = null;
			try {
				rules = styles[i].cssRules;
			} catch(error) {
				continue;
			}

			if (rules != null) {
				rules_num = rules.length;

				for (j=0; j<rules_num; j++) {
					style_text += rules[j].cssText;
				}
			}

		}
	}

//form content of the list
var content = '<html>'+
'<head><style type="text/css">'+style_text+'.re_list_over{background-color:Highlight;color:HighlightText}.re_list_out{background-color:##ffffff;color:#000000}</style>'+
'<body topmargin=0 leftmargin=0 rightmargin=0 bottommargin=0 style="background:#ffffff">'+
'<div id="content_div" style="overflow:hidden; width=100%;">'+
'<table border="0" style="cursor:pointer" cellspacing="0" width="100%">';

	var sel_len = sel_obj.options.length;
	var sel_opt = sel_obj.options;

	if (!sel_len) return;

	for (i=0;i<sel_len;i++) {
		if (i == 0 && type != 'ClassName') continue;
		content += '<tr><td onClick="parent.do_action(\''+type+'\', \''+sel_opt[i].value+'\');" onmouseover="this.className = \'re_list_over\'" onmouseout="this.className=\'re_list_out\'">';
		switch (type) {
			case 'FormatBlock':
				content += sel_opt[i].value+String(sel_opt[i].text).replace(/ /g, '&nbsp;');
				break;
			case 'FontName':
				content += '<nobr><font face="'+sel_opt[i].value+'">'+sel_opt[i].text+'</font></nobr>';
				break;
			case 'FontSize':
				content += '&nbsp;&nbsp;&nbsp;&nbsp;<font size="'+sel_opt[i].value+'">'+sel_opt[i].text+'</font>&nbsp;&nbsp;&nbsp;&nbsp;';
				break;
			case 'ClassName':
				content += '<nobr><span class="'+sel_opt[i].value+'">'+(sel_opt[i].text!=''?sel_opt[i].text:'&nbsp;')+'</span></nobr>';
				break;
			default:
				break;
		}
		content += '</td></tr>';
	}

	content += '</table>'+
'</div>'+
'</body></html>';

	obj.style.display = ""; //cannot write to iframe if it is not displayed
	obj_doc.open();
	obj_doc.write(content);
	obj_doc.close();

var sel_pos = get_element_pos(sel_obj);
	obj.style.left = sel_pos[0] + 'px';
	obj.style.top = sel_pos[1] + sel_obj.offsetHeight + 'px';

	var new_height = obj_doc.getElementById('content_div').offsetHeight;
	if (h2content || new_height < obj.getAttribute('ini_height')) {
		obj.height = new_height;
	} else obj.height = obj.getAttribute('ini_height');

}

//hide all selection list open
function re_hide_lists(){
var iframes = document.body.getElementsByTagName("IFRAME");
var i;

	for (i=0; i<iframes.length; i++) {
		var obj = iframes[i];
		if (obj.className == 're_list_iframe')
			if (obj.style.display == '') {
				obj.style.display = 'none';
				//make enable the appropriate list
				var list_id = String(obj.id).replace(/_iframe$/,'');
				var list = document.getElementById(list_id);
				list.disabled = false;
			}
	}
}

//returns document object of current editor
function re_rich_doc(){
	return document.getElementById(active_rich.name+'_id').contentWindow.document;
}

var re_can_compare;

//check if a link inside
function is_a_inside(obj){
		try{
var sel = active_rich.getSelection();
var r = sel.getRangeAt(0);
var container = r.startContainer;
var container_type = container.nodeType;
		}catch(error){
			return false;
		}

	if(container_type == 1 && !re_is_br(r, container)) return 'no';

	if (String(r) == "") return 'empty'; //no text selected

	return 'no';
}

//check if current element is BR
function re_is_br(r, container) {
	if (container.nodeType != 1) return false;
	element = container.childNodes[r.startOffset];
	if (element && element.tagName == 'BR') return true;
	return false;
}

//adds new lines and indents to some tags to make code more neat
function format_content(code){
var i;
var xhtml_mode = get_xhtml_mode();

var need_nl_before = /\<(div|p|table|tbody|thead|tr|td|th|title|script|comment|li|meta|h1|h2|h3|h4|h5|h6|hr|ul|ol|option|link|pre)[^\>]*\>/gi;
var need_nl_after = /\<\/(div|p|table|tbody|thead|tr|td|th|title|script|comment|li|meta|h1|h2|h3|h4|h5|h6|hr|ul|ol|option|link|br|pre)[^\>]*\>/gi;
var need_nl_both = /\<[\/]?(style|head|body|html)[^\>]*\>/gi;

	eval('var indent_char = '+active_rich.name+'_indent;');
var indent_inc = new RegExp();
	indent_inc.compile("^\<(head|table|tbody|thead|tr|ul|ol)[^\>]*\>", "i");
var indent_dec = new RegExp();
	indent_dec.compile("^\<\/(head|table|tbody|thead|tr|ul|ol)[^\>]*\>", "i");

var nl = /\s*[\r|\n]+\s*/g;

	code = code.replace(need_nl_before, "\n$&");
	code = code.replace(need_nl_after, "$&\n");
	code = code.replace(need_nl_both, "\n$&\n");

	var code_lines = code.split(nl);
	var new_code = "";
	var indent = "";
	var no_indent = false;
	for (i=0; i<code_lines.length; i++) {
		if (code_lines[i] == "") continue;

		if (new_code != "") new_code += "\n";

		if (indent_dec.exec(code_lines[i])) indent = indent.replace(indent_char, "");

		var new_line = code_lines[i];
		if (typeof(fix_entities) == "function" && !xhtml_mode) new_line = fix_entities(new_line);

		if (!no_indent) new_code += indent;
		new_code += new_line;

		//content inside textarea and pre must stay intact
		var low_line = new_line.toLowerCase();
		var k = low_line.lastIndexOf("<textarea");
		var k2 = low_line.lastIndexOf("</textarea");
		if (k > 0 && (k2 < 0 || k > k2)) no_indent = true;
		if (!no_indent && low_line.match(/\<pre/i)) no_indent = true;
		if (k2 > 0 && (k < 0 || k2 > k)) no_indent = false;
		if (no_indent && low_line.match(/\<\/pre/i)) no_indent = false;

		if (indent_inc.exec(code_lines[i]) && !no_indent) indent += indent_char;
	}

	return new_code;
}

//error message handler
function no_error(){
	return true;
}
