// Name: Editor class
// Info: Contain all editors methonds for IE.

var cssloaded = 0;
var cached_Styles = null;
var cached_cssText = null;

var deEngine = new Replacer();
deEngine.addRule("(<script[^>]*?>[\\s\\S]*?</script>)");

// Save command

var Save = function()
{
	this.Name = 'save' ;
};

Save.prototype.execute = function(isUpdate)
{

	if (loading_in_progress && !isUpdate){
		parent.document.getElementById(E.InstanceName+"_html").value = parent.document.getElementById(E.InstanceName+"_input").value;
		parent.document.getElementById(E.InstanceName+"_save").click();
		loading_in_progress = false;
		return;
	}
//	try{

		aed = E._frame;
//		var div = aed.getElementById('anchor_div');
//		if(div) div.parentNode.removeChild(div);

		var code = "";
		if (E.mode=="source") {
			code = aed.body.innerText;
		} else {
			E.commands.getCommand("Paragraph").hideChar();
			code = E.HTMLTags[1]+img2embed(removeWrap(aed.documentElement.innerHTML))+E.HTMLTags[3];
			E.commands.getCommand("Paragraph").showChar();
			code = removeBase(code);
			code = removeSpellSpanIE(code);
		    code = code.replace(/de_href=\"[^\"]+\"/gi, "");
		    code = code.replace(/de_action=\"[^\"]+\"/gi, "");
		}

		if (useXHTML==1) {
			code = getXHTML(code);
		}

		re = /&amp;/g;
		code = code.replace(re,'&');

		if (pathType == "1") {
			replaceImage = 'src="';
			code = code.replace(re3,replaceImage);
		}
		var gtb = code.match(/(<span id="GTBSC_[^>]+>)([^\>]+)(<\/span>)/i);
		c=0;
		while(gtb){
	   		code = code.replace(gtb[0],gtb[2]);
			var gtb = code.match(/(<span id="GTBSC_[^>]+>)([^\>]+)(<\/span>)/i);
			c=1;
		}
		code = code.replace(/gtb_[^=]+=\"[^\"]+\"/gi, "");
		code = code.replace(/<span id=\"?anchor_div\"?[^>]+><\/span>/gi, "");

		code = ConvertSSLImages(code);
		code = convert_align_middle_to_center(code);
		if (deEngine)code = deEngine.restore(code);

		if (E.mode=="edit") {
			code = convert_param_tag_to_xhtml(code);
		}

		if (E.mode=="source") {
			code = _de_save_special_char2(code);
		} else {
			code = _de_save_special_char(code);
		}
		parent.document.getElementById(E.InstanceName+"_html2").value = code;

		if (docType!=1 && E.mode=="edit"){ // for snippet mode
			h = code.match(BodyContents);
			code = h[2];
		}

		code = formatSaveCode(code);

		var donotformat = 0;

// the following line seems to be reformatting snippets when you have editable regions
// finding the doctype seems to fix this problem
// fulvio
//	if (E.isbegin && E.isend) {
		if (E.isbegin && E.isend && docType==1) {
			code = replace_editable(code);
			donotformat=1;
		}
		parent.document.getElementById(E.InstanceName+"_html").value = code;
		if (isUpdate!=="no") {
			parent.document.getElementById(E.InstanceName+"_save").click();
		}
//	} catch(e){
//	}
};

Save.prototype.getMode = function()
{
	return OFF;
};
// ***** end of Save command *****


// Paste as Plain Text command
var PasteText = function()
{
	this.Name = "PasteText";
};

PasteText.prototype.execute = function()
{
	try {
		var s = clipboardData.getData("Text");
		s = s.replace( /\n/g, '<BR>' ) ;
		E._inserthtml(s) ;
	} catch(e){}
};

PasteText.prototype.getMode = function()
{
	try
	{
		if (!E._frame.queryCommandEnabled( "paste" ) ) {
			return DISABLED ;
		} else {
			return E._frame.queryCommandState( "paste" ) ? ON : OFF ;
		}
	}
	catch ( e )	{
		return OFF ;
	}
};

// Source mode class
var SourceCommand = function()
{
	this.Name = "SourceMode";
};

SourceCommand.prototype.getMode = function()
{
};

SourceCommand.prototype.execute = function()
{

	ToolbarSets.SwitchToolbarSet("_source");

	var e = E._frame;
	clearUrls();

	E.commands.getCommand("Spellcheck").off();
	E.commands.getCommand("Paragraph").hideChar();

	var fr = document.getElementById(E.InstanceName+"_frame");

	if (E.showborders==ON) {
		E.commands.getCommand("Showborders").reset(true);
	}

	document.getElementById("ePath").style.display="none";
	if (fr.style.display=="none") {
		var Ifr = document.getElementById(E.InstanceName+"_preview");
		fr.style.display="";
		Ifr.style.display="none";
	}

	if (E.mode=="edit") {
		if (docType==1) { // DE_DOC_TYPE_HTML_PAGE
			var c = E.HTMLTags[1] + E._frame.documentElement.innerHTML + E.HTMLTags[3];
			if (useXHTML==1) {
				iHTML = getXHTML(c);
			} else {
				iHTML = c;
			}
		} else{
			var c = E.HTMLTags[1] + E._frame.documentElement.innerHTML + E.HTMLTags[3];
			E.part = c.match(BodyContents);
			if (useXHTML==1) {
				iHTML = getXHTML(e.body.innerHTML);
			} else {
				iHTML = e.body.innerHTML;

			}
		}
		re = /&amp;/g;
//		iHTML = removeWrap(iHTML);
		iHTML = removeBase(iHTML);
		iHTML = removeBlock(iHTML);
		iHTML = iHTML.replace(re,'&');
		iHTML = convert_align_middle_to_center(iHTML);
		iHTML = convert_param_tag_to_xhtml(iHTML);
//	    iHTML = removeSpellSpan(iHTML);
		iHTML = deEngine.restore(iHTML);
		// for nice looking
		e.body.style.fontFamily = "monospace";
		e.body.style.fontSize = "12px";
		e.body.style.lineHeight = 1;
		e.body.style.color = "#000000";
		e.body.color = "#000000";
		e.body.bgColor = '#FFFFFF';
		e.body.style.text = '#000000';
		e.body.style.background = '';
		e.body.style.marginTop = '10px';
		e.body.style.marginLeft = '10px';
		e.body.style.textAlign = 'left';

		// switch to source view
		e.body.innerText = img2embed(iHTML) ;
		var c=e.body.innerHTML;
		c = _de_parse_special_char(c);
		html = convert_attr_name_to_lowercase(addEditTag(colourCode(formatCodeIE(c))));
		e.body.innerHTML = html;// + "<div style='width:5000px;height:0px'></div>";
	}

	E.mode="source";
	E.lastmode="source";
	E.calculateNewSize();

	buffer["source"].devhistory.position = 0;
	E.Focus();
	set_cursor_at_begin();
	move_cursor_right_and_left();
};

// Edit mode
var EditCommand = function()
{
	this.Name = "EditMode";
};

EditCommand.prototype.getMode = function()
{
};

EditCommand.prototype.execute = function()
{
	var e = E._frame;

	var fr = document.getElementById(E.InstanceName+"_frame");
	document.getElementById("ePath").style.display="block";

	if (fr.style.display=="none") {
		var Ifr = document.getElementById(E.InstanceName+"_preview");
		fr.style.display="";
		Ifr.style.display="none";
	}

	var headTag = /<head\s*>/i;

	var lastMode = E.mode;
	E.mode="edit";
	E.lastmode="edit";

	if (lastMode=="source") {
		//switch back to regular view
		iText = e.body.innerText;
   		var temp = iText.match(/(<a[^>]+\/>)/g);
		try{
		for (var i=0; i<temp.length;i++){
			iText = iText.replace(temp[i], temp[i].replace("/>","></a>"));
		}
		}catch(e){}

		var addbase="";
		add_to_head = "";
		if (docType==1) { // DE_DOC_TYPE_HTML_PAGE
			if (myBaseHref && E.useBase) {
				//add_to_head += '<base href="'+myBaseHref+'" />';
			}
			var html = iText.replace(headTag,'<head>'+add_to_head+'<style id="'+E.InstanceName+'bs">'+border_style+'<\/style>'+addbase);
			var rh = html.match(HeadContents);
			if (rh) {
				E.headhtml = rh[2];
			}
		} else {
			var html = E.part[1] + iText + E.part[3];

			var add_to_head = '<style id="'+E.InstanceName+'bs">'+border_style+'<\/style>'//'<link disabled href="'+E.skinPath+'borders.css" type="text/css" rel="stylesheet" />';
			if (E.snippetCSS) {
				add_to_head += '<link href="'+E.snippetCSS+'" type="text/css" rel="stylesheet" />';
			}
			if (myBaseHref) {
				//add_to_head += '<base href="'+myBaseHref+'" />';
			}

			newhtml = html.match(HeadContents);
			html = newhtml[1]+add_to_head+newhtml[2]+newhtml[3];
		}
		html = addBlock(html);
		E.writeC(deEngine.preserve(embed2img(removeEditTag(html))),1);
		E.testparam = "testparam";
		correctUrls();
	}
	E.calculateNewSize();
	if (E.showborders==ON){
		E.commands.getCommand("Showborders").set(false);
	} else {
		E.commands.getCommand("Showborders").reset(false);
	}
	E.commands.getCommand("Paragraph").showChar();
	ToolbarSets.SwitchToolbarSet(toolbarmode);
	E.doStyles();
	E.Focus();
	checkImgLoaded();
	setTimeout("_de_scroll_top()",300);
	_de_scroll_top();
};

// Preview mode class
var PreviewCommand = function()
{
	this.Name = "PreviewMode";
};

PreviewCommand.prototype.getMode = function()
{
};

PreviewCommand.prototype.execute = function()
{
	ToolbarSets.SwitchToolbarSet("_preview");

	var aed = E._frame;
	var e = document.getElementById(E.InstanceName+"_frame");
	if (E.showborders==ON) {
		E.commands.getCommand("Showborders").reset(false);
	}
	E.commands.getCommand("Paragraph").hideChar();

	document.getElementById("ePath").style.display="none";
	var Ifr = document.getElementById(E.InstanceName+"_preview");
	e.style.display="none";
	Ifr.style.display="";

	var addbase = "";
	if (myBaseHref && E.useBase) {
		addbase += '<base href="'+myBaseHref+'" />';
	}
	if (E.mode=="source"){
		if (docType==1){ // DE_DOC_TYPE_HTML_PAGE
			var c = addbase+aed.body.innerText;
		} else {
			var bodyhtml = addbase+aed.body.innerText;
			var c = E.part[1] + bodyhtml + E.part[3];
		}
		c = img2embed22(c);
	} else{
		var c = "<html>" + img2embed2(E._frame.documentElement.innerHTML)+"</html>";
		c = img2embed22(img2embed2(c));
		c = removeBlock(c);
	}

	window.frames[E.InstanceName+"_preview"].document.write("<html>"+c.replace(/(&lt;([\s\S]*?)borders.css([\s\S]*?)&gt;)/gi,'') + "</html>");
	checkImgLoaded(window.frames[E.InstanceName+"_preview"].document);
	window.frames[E.InstanceName+"_preview"].document.close();
	E.calculateNewSize("preview");
	E.lastmode="preview";
	window.frames[E.InstanceName+"_preview"].focus();
};


function clearCode(code)
{
	code = code.replace(/[”“]/gi,'"');
	code = code.replace(/[‘’]/gi,"'");
	code = code.replace(/<([\w]+) class=([^ |>]*)([^>]*)/gi, "<$1$3");
	code = code.replace(/<([\w]+) style="([^"]*)"([^>]*)/gi, "<$1$3");
	code = code.replace(/<\\?\??xml[^>]>/gi, "");
	code = code.replace(/<\/?\w+:[^>]*>/gi, "");
	code = code.replace(/<p([^>])*>(&nbsp;)*\s*<\/p>/gi,"");
	code = code.replace(/<span([^>])*>(&nbsp;)*\s*<\/span>/gi,"");
	code = code.replace(/<b([^>])*>(&nbsp;)*\s*<\/b>/gi,"");
	code = code.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3") ;
	code = code.replace( /\s*mso-[^:]+:[^;"]+;?/gi, "" ) ;
	code = code.replace(/<\\?\?xml[^>]*>/gi, "") ;
	code =  code.replace( /\s*style="\s*"/gi, '' ) ;
	code = code.replace( /<SPAN\s*[^>]*>\s*&nbsp;\s*<\/SPAN>/gi, '&nbsp;' ) ;
	code = code.replace( /<SPAN\s*[^>]*><\/SPAN>/gi, '' ) ;

	code = code.replace( /<([^\s>]+)[^>]*>\s*<\/\1>/g, '' ) ;
	code = code.replace( /<([^\s>]+)[^>]*>\s*<\/\1>/g, '' ) ;
	code = code.replace( /<([^\s>]+)[^>]*>\s*<\/\1>/g, '' ) ;

	return code;
}

// Clear Code command
var ClearCodeCommand = function()
{
	this.Name = 'ClearCode' ;
};

ClearCodeCommand.prototype.execute = function()
{
	if (confirm("Are you sure you want to clean your HTML code?")) {
		buffer[E.mode].saveHistory();
		code = E._frame.body.innerHTML;
		code = clearCode(code);
		E._frame.body.innerHTML = code;
		E._window.focus();
	}
};

ClearCodeCommand.prototype.getMode = function()
{
	if (E.isbegin && E.isend) {
		return DISABLED;
	}
	return OFF;
};


// Fullscreen class
var FullscreenCommand = function()
{
	this.Name = 'Fullscreen' ;
	e = parent.document.getElementById(E.InstanceName+"main");
	this.oldw = e.style.width;
	this.oldh = e.style.height;
	this.style = null;
	this.scrollXPos = 0;
	this.scrollXPos = 0;
};

FullscreenCommand.prototype.changemode = function(str,par, val)
{
	idx=str.indexOf(par+"=",1);
	idx2=str.indexOf("&",idx+1);
	if((idx>=0)&&(idx2==-1)) {
		idx2=str.length;
	}
	if (idx!=-1){
		str = str.substring(0,idx+par.length+1) + val + str.substring(idx2,str.length);
	} else {
		if (str.indexOf("?")!=-1){
			str = str + "&" + par + "=" + val;
		} else {
			str = str + "?"+par + "=" + val;
		}
	}

	return str;
};

function Resize_DE_Editor(){
	e = parent.document.getElementById(E.InstanceName+"main");
	e.style.width = Get_Window_Width();
	e.style.height = Get_Window_Height();

	E.calculateNewSize();
	try {E._frame.designMode = "On";}catch(e){}
	ToolbarSets.Redraw();
	try {E.Focus();}catch(e){}
}

function Get_Window_Height(){
	if (parent.document.documentElement && parent.document.documentElement.clientWidth) {
		x = parent.document.documentElement.clientHeight;
	} else {
		x = parent.document.body.clientHeight;
	}
	return x;
}

function Get_Window_Width(){
	if (parent.document.documentElement && parent.document.documentElement.clientWidth) {
		x = parent.document.documentElement.clientWidth;
	} else {
		x = parent.document.body.clientWidth;
	}
	return x;
}

FullscreenCommand.prototype.execute = function()
{
	e = parent.document.getElementById(E.InstanceName+"main");
	e1 = document.getElementById(E.InstanceName+"main1");

	if (E.fullscreen == OFF) {

		// hide sidebar
		this.style = SaveStyle(parent.document.body);
		parent.document.documentElement.style.overflow = "hidden";
		parent.document.body.style.overflow = "hidden";

		if (parent.document.documentElement && parent.document.documentElement.clientWidth) {
			sL = parent.document.documentElement.scrollLeft;
			sT = parent.document.documentElement.scrollTop;
		} else {
			sL = parent.document.body.scrollLeft;
			sT = parent.document.body.scrollTop;
		}
		w = Get_Window_Width();
		h = Get_Window_Height();
		this.scrollXPos = sL;
		this.scrollYPos = sT;

		e1.style.height = "100%";
		e.style.position = 'absolute';
		e.style.left = "0px";
		e.style.top = "0px";
		e.style.width = w+"px";
		e.style.height = h+"px";
		e.style.zIndex = 100;
		E.fullscreen = ON;

		E.href = this.changemode(E.href,"fullscreen","on");

		parent.document.documentElement.style.overflow = "hidden";
		parent.document.body.style.overflow = "hidden";
		parent.scrollTo(0,0);
		parent.attachEvent( 'onresize', Resize_DE_Editor) ;

	} else {
		parent.detachEvent( "onresize", Resize_DE_Editor ) ;
		e.style.position = '';
		e.style.left = 0;
		e.style.top = 0;
		e.style.width = E.oldw;
		e.style.height = E.oldh;
		E.fullscreen=OFF;
		RestoreStyle(parent.document.body,this.style);
		E.href = this.changemode(E.href,"fullscreen","off");
		parent.scrollTo(this.scrollXPos,this.scrollYPos);
		//move_cursor_right_and_left();
	}

	E.calculateNewSize();
	try {E._frame.designMode = "On";}catch(e){}
	ToolbarSets.Redraw();
	try {E.Focus();}catch(e){}
};

FullscreenCommand.prototype.getMode = function()
{
	if (E.fullscreen==ON) {
		return ON;
	} else {
		return OFF;
	}
};

SaveStyle = function(o)
{

	var expDate = new Date;
	expDate.setTime (expDate.getTime() + (24*60*60*1000));

	var oSavedStyles = new Object() ;

	if ( o.className.length > 0 )
	{
		oSavedStyles.Class = o.className ;
		o.className = '' ;
	}
	SetCookie("savedClass",oSavedStyles.Class,expDate);

	var sInlineStyle = o.style.cssText ;

	if ( sInlineStyle.length > 0 )
	{
		oSavedStyles.Inline = sInlineStyle ;
		o.style.cssText = '' ;
	}
	SetCookie("savedStyle",oSavedStyles.InLine,expDate);

	return oSavedStyles ;
}

RestoreStyle = function(o, savedStyles){
	o.className	= GetCookie("savedClass") || '' ;
	o.style.cssText	= GetCookie("savedStyle") || '' ;
}


// InsertTextBox class
var InsertTextBox = function()
{
	this.Name = 'Inserttextboxe' ;
};

InsertTextBox.prototype.execute = function()
{
	E._inserthtml("<table id=de_textBox style='position:absolute;'><tr><td>Text box</td></tr></table>");
	textBox = E._frame.getElementById("de_textBox");
	textBox.removeAttribute("id");
	E._window.focus();
};

InsertTextBox.prototype.getMode = function()
{
	return OFF;
};

// Show borders
var ShowBordersCommand = function()
{
	this.Name = 'Showborders' ;
};

// function for set style
var el = new Object;
el.id 		= [];
el.className= [];

function setClassForInput()
{
	var elements = E._frame.getElementsByTagName("INPUT");
	for(var i = 0; i < elements.length; i++) {
		if (elements.item(i).type.toUpperCase()!="HIDDEN") {
			continue;
		}
		el.id[el.id.length] = elements.item(i);
		el.className[el.className.length] = elements.item(i).getAttribute("className");
		elements.item(i).className = "de_style_input";
	}
}

function setClassForAnchor()
{
	var elements = E._frame.getElementsByTagName("A");
	for(var i = 0; i < elements.length; i++) {
		if (!elements.item(i).name) {
			continue;
		}
		el.id[el.id.length] = elements.item(i);
		el.className[el.className.length] = elements.item(i).getAttribute("className");
		elements.item(i).className = "de_style_anchor";
	}
}


function resetClassForAll()
{
	var elements = E._frame.getElementsByTagName("A");
	for (var i = 0; i < elements.length; i++) {
		if (!elements.item(i).name) {
			continue;
		}
		if(elements.item(i).className=="de_style_anchor"){
			elements.item(i).removeAttribute("className");
		}
	}

	for(var i = 0; i < el.id.length; i++) {
	 try {
		el.id[i].className = el.className[i];
		if (!el.className[i]) el.id[i].removeAttribute("className");
	 } catch(e){}
	}
	el.id.length=0;
	el.className.length=0;
}


ShowBordersCommand.prototype.switchCSS = function(on)
{
 try{
	E._frame.getElementById(E.InstanceName+"bs").disabled = on;
 }catch(e){}
};

ShowBordersCommand.prototype.set = function()
{
	var sheets = E._frame.styleSheets;
	if (el.id&&el.id.length>0){
		resetClassForAll();
	}
	setClassForInput();
	setClassForAnchor();
	this.switchCSS(false);
};

ShowBordersCommand.prototype.reset = function()
{
	var sheets = E._frame.styleSheets;
	this.switchCSS(true);
	resetClassForAll();
};

ShowBordersCommand.prototype.execute = function(ignore)
{
	if (E.showborders==OFF) {
		if(ignore!==true) {
			E.showborders=ON;
		}
		this.set();
	} else {
		this.reset();
		if (ignore!==true) {
			E.showborders=OFF;
		}
	}
};

ShowBordersCommand.prototype.getMode = function()
{
	return E.showborders;
};

// paste from MS Word
var PasteFromMSWord = function()
{
	this.Name = 'pastefrommsword' ;
	this.mode = OFF;
};

PasteFromMSWord.prototype.execute = function()
{
	E.Focus();
	var oDiv = document.getElementById( '__HiddenDiv' ) ;

	if ( !oDiv ) {
		// use temp div to paste
		var oDiv = document.createElement( 'DIV' ) ;
		oDiv.id = '__HiddenDiv' ;
		oDiv.style.visibility	= 'hidden' ;
		oDiv.style.overflow		= 'hidden' ;
		oDiv.style.position		= 'absolute' ;
		oDiv.style.width		= 1 ;
		oDiv.style.height		= 1 ;

		document.body.appendChild( oDiv ) ;
	}

	oDiv.innerHTML = '' ;
	var oTextRange = document.body.createTextRange() ;
	oTextRange.moveToElementText( oDiv ) ;
	oTextRange.execCommand( 'Paste' ) ;
	var sData = oDiv.innerHTML ;
	oDiv.innerHTML = '' ;
	code = clearCode(sData);
	E.insertHTML( code ) ;
};


PasteFromMSWord.prototype.getMode = function()
{
	try
	{
		if (!E._frame.queryCommandEnabled( "paste" ) ) {
			return DISABLED ;
		} else {
			return E._frame.queryCommandState( "paste" ) ? ON : OFF ;
		}
	}
	catch ( e ) {
		return OFF ;
	}
};
// ***** end of [paste from MS Word] ******


// Undo command
var Undo = function(modename)
{
	this.Name = 'undo';
	this.mode = modename;
};

Undo.prototype.execute = function()
{
	buffer[E.mode].goHistory(-1);
	E._window.focus();
};

Undo.prototype.getMode = function(){
	if ((buffer[E.mode].devhistory.data.length <= 0) || (buffer[E.mode].devhistory.position <= 0)) {
		return DISABLED;
	} else {
		return OFF;
	}
};

// Redo command
var Redo = function(modename)
{
	this.Name = 'undo';
	this.mode = modename;
};

Redo.prototype.execute = function()
{
	buffer[E.mode].goHistory(1);
	E._window.focus();
};

Redo.prototype.getMode = function()
{
	if ((buffer[E.mode].devhistory.position >= buffer[E.mode].devhistory.data.length-1) || (buffer[E.mode].devhistory.data.length == 1)) {
		return DISABLED;
	} else {
		return OFF;
	}
};

// Buffer class (buffer for undo/redo)

var URBuffer = function()
{
	var devhistory = new Object;
	devhistory.data = [];
	devhistory.position = 0;
	devhistory.bookmark = [];
	devhistory.offset = [];
	devhistory.max = _de_max_history_item;
	this.devhistory = devhistory;
};

URBuffer.prototype.saveHistory = function(kk)
{
	var recpos;

	try {
		recpos = this.devhistory.position;

		// new code
		oSel = E._frame.selection;
		range = oSel.createRange();
		switch (sel.type) {
			case "Control":
				p = range.item(0).parentNode;
				break;
			default:
				p = range.parentElement();
		}

		if (kk && kk==13)p=p.parentNode;

		// check if there is some changes
		if (p.innerHTML==this.devhistory.data[this.devhistory.length-1]){
			return;
		}
		if (this.devhistory.data.length >= this.devhistory.max) {
			if (this.devhistory.position==0){
				this.devhistory.data.length = 0;
				this.devhistory.bookmark.length = 0;
				this.devhistory.offset.length = 0;
			} else {
				this.devhistory.data.shift();
				this.devhistory.bookmark.shift();
				this.devhistory.offset.shift();
				this.devhistory.position--;
			}
		}
		this.devhistory.data.length = this.devhistory.position+1;
		if (p.tagName.toLowerCase() == "body"){
			this.devhistory.offset[recpos] = p;
			this.devhistory.data[recpos]  = p.innerHTML;
		}else{
			this.devhistory.offset[recpos] = p.parentNode;
			this.devhistory.data[recpos]  = p.parentNode.innerHTML;
		}
		this.devhistory.position++;

	} catch (e){}
};

URBuffer.prototype.goHistory = function(value)
{
	try{
	if (value == -1) {
		this.devhistory.position--;
	} else {
		this.devhistory.position++;
	}

	if (this.devhistory.position < 0)	{
		this.devhistory.position = 0;
	}

	if (this.devhistory.position == this.devhistory.data.length-1 && value==-1)	{
		this.devhistory.position++;
		this.saveHistory();
		this.devhistory.position -= 2;
	}

	rp = this.devhistory.position;
	p = this.devhistory.offset[rp];
	p.innerHTML=this.devhistory.data[rp];

	this.setHistoryCursor();

	if (E.showborders==ON) {
		E.commands.getCommand("Showborders").set(true);
	} else {
		E.commands.getCommand("Showborders").reset(true);
	}
	} catch(e){}
}

URBuffer.prototype.setHistoryCursor = function()
{
	aed = E._frame;

	var range;
	if (this.devhistory.bookmark[this.devhistory.position]) {
		range = aed.body.createTextRange();
		if (this.devhistory.bookmark[this.devhistory.position] != "[object]") {
			if (range.moveToBookmark(this.devhistory.bookmark[this.devhistory.position])) {
				doSave = 1;
				range.select();
				doSave = 0;

			}
		}
	}
};

// initialize buffer
var buffer = new Array();
buffer["edit"] = new URBuffer();
buffer["source"] = new URBuffer();

// main class- EDITOR
var Editor = function( instanceName, width, height, skinName)
{
	window.activeEditor	= this;

	// Properties
	this.InstanceName	= instanceName ;
	this.Value			= '' ;
	this.Width			= width;
	this.Height			= height;
	this.skinName		= skinName ;
	this.part			= null;

	// auxiliary properties
	this._frame			= false;
	this.mode			= "edit";
	this.lastmode		= "edit";
	this.showborders	= OFF;
	this.customLink		= CustomLink;
	this.tempWin		= null;
	this.tempEl;
	this.arr			= null;
	this.toolbarpos		= 0;
	this.unlock			= false;
	this.skinPath		= serverurl + deveditPath1 + '/'+skinPath;
	this.snippetCSS		= snippetCSS;
	this.selectedtag	= null;
	this.lastinsert	= null;
	this.editable		= true;
	this.href			= window.location.href;
	this.norefresh		= false;
	this.initHTML		= "";
	this.use_old_base	= false;
	this.disableTabs	= false;
	this.useBase		= false;
	this.isbegin		= false;
	this.isend			= false;
	this.lastOffset		= null;
	this.lastContainer	= null;
	this.siteUrl        = siteURL?siteURL:"http://"+location.host;

	if (this.snippetCSS && !this.snippetCSS.match(/http:\/\//)){
		if (this.snippetCSS.match(/^\/.+/)){
			this.snippetCSS = "http://"+parent.location.host+this.snippetCSS;
		}else{
			this.snippetCSS = parent.location.href.replace(/\/[^/]+$/,"/")+this.snippetCSS;
		}
	}

	if (this.getParameter("fullscreen")=="on") {
		this.fullscreen		= ON ;
	} else {
		this.fullscreen		= OFF ;
	}
	this.oldw=0;
	this.oldh=0;

	if (toolbarmode) {
		for (var i=0;i<DevEditToolbars.length;i++){
			if (DevEditToolbars[i]==toolbarmode) {
				this.toolbarpos = i;
				return;
			}
		}
	}
	toolbarmode = DevEditToolbars[0];
	this.toolbarpos = 0;
};

Editor.prototype.execCommand = function(name)
{
	if (this.commands.getCommand(name)) {
		this.commands.getCommand(name).execute();
		ToolbarSets.Redraw();
	}
};

Editor.prototype.switchModeTo = function(mode)
{
	if (!mode) return false;
	if (typeof(mode)!== "string") return false;
	if (mode.toLowerCase()==this.lastmode)return false;
	switch (mode.toLowerCase()){
		case "edit":
			this.execCommand("EditMode");
			this.sheet.Select("EditMode");
			break;
		case "source":
			this.execCommand("SourceMode");
			this.sheet.Select("SourceMode");
			break;
		case "preview":
			this.execCommand("PreviewMode");
			this.sheet.Select("PreviewMode");
	}
	return true;
};

Editor.prototype.getHTMLContent = function()
{
	return _de_getContent();
};

Editor.prototype.getTextContent = function()
{
	return _de_getTextContent();
};

Editor.prototype.setParameter = function(par, val)
{
	var str = this.href;
	idx=str.indexOf(par+"=",1);
	idx2=str.indexOf("&",idx+1);
	if((idx>=0)&&(idx2==-1)) {
		idx2=str.length;
	}
	if (idx!=-1){
		this.href = str.substring(0,idx+par.length+1) + val + str.substring(idx2,str.length);
	} else {
		if (str.indexOf("?")!=-1){
			this.href = str + "&" + par + "=" + val;
		} else {
			this.href = str + "?"+par + "=" + val;
		}
	}
};

Editor.prototype.getParameter = function(par)
{
	var str = this.href;
	idx=str.indexOf(par+"=",1);
	idx2=str.indexOf("&",idx+1);
	if((idx>=0)&&(idx2==-1)) {
		idx2=str.length;
	}
	if (idx!=-1){
		return str.substring(idx+par.length+1,idx2);
	} else {
		return "0";
	}
};

Editor.prototype.attachStyleSheet = function(name)
{
	this.addStyleSheet(this._frame, name);
}

// add StyleSheet (name) to document( d )
Editor.prototype.addStyleSheet = function(d,name)
{
	var e=d.createStyleSheet(name);
	return e;
};

Editor.prototype.setSize = function()
{
	var pDiv = parent.document.getElementById(E.InstanceName+"main");
	this.realHeight = pDiv.offsetHeight;
	var tDiv = document.getElementById(E.InstanceName+"main1");
	if (pDiv.offsetWidth<tDiv.offsetWidth) {
		pDiv.style.width = (tDiv.offsetWidth+10)+"px";
	}
	if (pDiv.offsetHeight<tDiv.offsetHeight) {
		pDiv.style.height = (tDiv.offsetHeight)+"px";
	}
	if (this.getParameter("oldw")=="0") {
		this.oldw = pDiv.offsetWidth;
		this.oldh = pDiv.offsetHeight;
		this.setParameter("oldw",this.oldw);
		this.setParameter("oldh",this.oldh);
	} else {
		this.oldw = this.getParameter("oldw")*1.0;
		this.oldh = this.getParameter("oldh")*1.0;
	}
};

Editor.prototype.checkLoad = function()
{
	if (hideitems["EditMode"]==1 && hideitems["SourceMode"]==1 && hideitems["PreviewMode"]==1) {
		this.disableTabs=true;
	}
	this.commands = new Commands();
	this.toolbaritems = new ToolbarItems();

	ToolbarSets.AddItem(toolbarmode,'eToolbar');

	this.setSize();

	ToolbarSets.AddItem("path",'ePath');
	if (!this.disableTabs) {
		ToolbarSets.AddItem("footer",'eFooter');
	}

	this.sheet = new Sheet();
	if (hideitems["EditMode"]==0) {
		this.sheet.AddItem("EditMode", "Edit mode", "status_edit", CHOOSE);
	}
	if (hideitems["SourceMode"]==0) {
		this.sheet.AddItem("SourceMode", "Source mode", "status_source", OFF);
	}
	if (hideitems["PreviewMode"]==0) {
		this.sheet.AddItem("PreviewMode", "Preview mode", "status_preview", OFF);
	}

};

Editor.prototype.calculateNewSize = function(mode)
{
	if (new_layout){
		H = parent.document.getElementById(this.InstanceName + 'main').style.pixelHeight;
		W = parent.document.getElementById(this.InstanceName + 'main').style.pixelWidth;

		if (mode && mode=="preview"){
			dH = 77;
			if (hideTagBar)dH = dH - 23;

			document.getElementById(this.InstanceName + "_preview").height = H-dH;
		} else {
			if (this.mode=="edit"){
				tlb_H = DevEditToolbarSets[toolbarmode].length * 27;
			} else {
				if ((E.isbegin && E.isend) || parent.document.getElementById(E.InstanceName+"_html").value.match(/xhtml/ig)){
					tlb_H = 31;
				}else{
					tlb_H = 2 * 27;
				}
			}

			dH = 51+tlb_H;
			if (hideTagBar)dH = dH - 23;

			if (this.mode=="edit"){
				document.getElementById(this.InstanceName + "_frame").height = H-dH;
			} else {
				document.getElementById(this.InstanceName + "_frame").height = H-(dH-3);
			}
			//document.getElementById(this.InstanceName + "_frame").width = W-10;
		}
	}
}

Editor.prototype.setInitialValue = function()
{
	findCustomTags();// ??

	if (this.init) {
		return;
	}

	// set default color
	if (E.toolbaritems&&E.toolbaritems.GetItem('Fontcolor')) {
		E.toolbaritems.GetItem('Fontcolor').SetButtonColor("#000000");
	}
	if (E.toolbaritems&&this.toolbaritems.GetItem('Highlight')) {
		this.toolbaritems.GetItem('Highlight').SetButtonColor("yellow");
	}
	if (hideitems["guidelinesOnByDefault"]==1 && !(E.lastmode=="source" && E.showborders==OFF)) {
		this.commands.getCommand('Showborders').execute();
	}
	if (hideitems["guidelinesOnByDefault"]==0) {
		this.commands.getCommand('Showborders').switchCSS(true);
	}

	PopupSet.CreatePopup("spellmenu");
	PopupSet.CreatePopup("sourcetag");

	ToolbarSets.Redraw();
	E.sheet.Redraw();
	E.checkEditArea();

	var y = GetCookie("scroll_top");
	if (y) {
		parent.scrollTo(0,y);
	}
	setTimeout("_de_initialize()",10);

	checkImgLoaded();

	if (hideitems["EditMode"]==1){
		if (hideitems["SourceMode"]==1){
			this.switchModeTo("preview");
		}else{
			this.switchModeTo("source");
		}
	}

	this.init = true;
	if (eventListener){
		for (var i = 0; i < eventListener.length; i++){
			if (eventListener[i][0].toLowerCase()=="onload"){
				eval("parent."+eventListener[i][1]+"()");
			}
		}
	}
	loading_in_progress = false;
	setTimeout("_de_scroll_top()",500);
};

function _de_scroll_top(){
 correctSkypeIE();
 correctUrls(true);
 try{
	if (E._frame.documentElement && E._frame.documentElement.clientWidth) {
		E._frame.documentElement.scrollTop = 0 ;
	} else {
		E._frame.body.scrollTop = 0;
	}
 } catch (e) {}

}

function _de_initialize(){
	try {
		move_cursor_right_and_left();
		E.doStyles();
		E.toolbaritems.GetItem('Styles').Redraw();
	} catch(e){}

}

setTimeout("_de_initialize2()","500");

function _de_initialize2(){
	try {
		if(loading_in_progress)E.commands.getCommand('Bold').execute();
		if(loading_in_progress)setTimeout("_de_initialize2()","500");
	} catch(e){}
}

Editor.prototype.writeC = function(data,ignore)
{
	try{
		aed = this._frame;
		aed.open();
		data = convert_attr_name_to_lowercase(data);
		if (ignore) {
			aed.write(data);
		} else {
			aed.write(embed2img(addWrap(data)));
		}
		aed.close();
	} catch(e){}
};

Editor.prototype.writeHTMLContent = function(data)
{
	data = data.replace(/<!doctype[^>]+>/gi,'');
	if (this.mode=="source"){
		data = data.replace(/</g,"&lt;");
		data = data.replace(/>/g,"&gt;");
	}
	this.writeContentWithCSS(data);
};

Editor.prototype.writeContentWithCSS = function(data)
{
	var html="";
	if (parent.document.getElementById(name+"_html2").value!="" && !data) {
		html = parent.document.getElementById(name+"_html2").value;
		html = html.replace(/&amp;/g,'&');
		if (html.toLowerCase().indexOf("<html")>=0){
			var add_to_head = '<style id="'+this.InstanceName+'bs">'+border_style+'<\/style>';
			if (this.snippetCSS) {
				add_to_head += '<link href="'+this.snippetCSS+'" type="text/css" rel="stylesheet" />';
			}
			newhtml = html.match(HeadContents);
			html = newhtml[1]+add_to_head+newhtml[2]+newhtml[3];
		}
	} else {
		var h = data ? data : parent.document.getElementById(name+"_input").value;
		if (h.toLowerCase().indexOf("<html")>=0) {
			var add_to_head = '<style id="'+this.InstanceName+'bs">'+border_style+'<\/style>';
			if (this.snippetCSS) {
				add_to_head += '<link href="'+this.snippetCSS+'" type="text/css" rel="stylesheet" />';
			}
			newhtml = h.match(HeadContents);
			if (newhtml!==null) {
				html = newhtml[1]+add_to_head+newhtml[2]+newhtml[3];
			} else {
				html = h;
			}
		} else {
			html = "<html><head>";
			html += '<style id="'+this.InstanceName+'bs">'+border_style+'<\/style>';
			this.use_old_base = true;
			if (this.snippetCSS) {
				html += '<link href="'+this.snippetCSS+'" type="text/css" rel="stylesheet" />';
			}
			html+="</head>" + h + "</html>";
		}
	}
	// set initial HTML code for restricted mode
	var h = data ? data : parent.document.getElementById(name+"_input").value;
	if (h.toLowerCase().indexOf("<html")>=0){
		if (!this.initHTML) {
			this.initHTML = h;
		}
	} else {
		if (!this.initHTML) {
			this.initHTML = "<html><head></head>"+h+"</html>";
		}
	}
	var temp = html.match(/(<a[^>]+\/>)/g);
	try{
		for (var i=0; i<temp.length;i++){
			html = html.replace(temp[i], temp[i].replace("/>","></a>"));
		}
	}catch(e){}

	this.HTMLTags=null;
	var pos = html.indexOf("<html");
	if (pos==-1) {
		pos=html.indexOf("<HTML");
	}
	if (pos>=0) {
		var pos1 = html.indexOf(">",pos+1);
		var pos2 = html.indexOf("</html",pos1+1);
		if (pos2==-1) {
			pos2 = html.indexOf("</HTML>",pos1+1);
		}
		if (pos2==-1) {
			pos2 = html.length;
		}
		this.HTMLTags = new Array();
		this.HTMLTags[0] = html;
		this.HTMLTags[1] = html.substring(0,pos1+1);
		this.HTMLTags[2] = html.substring(pos1+1,pos2);
		this.HTMLTags[3] = html.substring(pos2,html.length);
	}

	if (!this.HTMLTags) {
		this.HTMLTags = new Array();
		this.HTMLTags[0]=html;
		this.HTMLTags[1]="";
		this.HTMLTags[2]="";
		this.HTMLTags[3]="";

		var x = html.match(HtmlContents1);
		if (x) {
			this.HTMLTags[1]=x[1];
		}
		var y = html.match(HtmlContents2);
		if (y) {
			this.HTMLTags[3]=y[1];
		}
	}

	if ( html.toLowerCase().indexOf("<base")>=0){
		myBaseHref="base tag";
	}

	try{
		aed = this._frame;
		aed.open();
		var v = deEngine.preserve(embed2img(addWrap(html)));
		aed.write(v);
		aed.close();
	} catch(e){}
};


function setEvent () {
	if(E) {
		E.setEvent();
	}
}


Editor.prototype.setEvent = function()
{
	var wa = E._frame;
//	try {
		wa.attachEvent( 'oncontrolselect', this.CheckEditable );

		wa.attachEvent( 'onselectionchange', this.Redraw);
		wa.attachEvent( 'onkeydown', this.Redraw) ;
		wa.attachEvent( 'onkeypress', this.KeyPress ) ;
		wa.attachEvent( 'onkeyup', this.CheckUp ) ;
		wa.attachEvent( 'onclick', this.Focus) ;
		wa.attachEvent( 'onmousedown', this.setdown ) ;
		wa.attachEvent( 'onmouseup', this.setup ) ;
		wa.attachEvent( 'oncontextmenu', this.ContextMenu) ;
		wa.body.attachEvent( 'ondragstart', this.CheckEditable) ;
		wa.body.attachEvent( 'ondrop', this.CheckEditable) ;
		wa.attachEvent( 'onblur', updateValue ) ;
		element = parent.document.getElementById(E.InstanceName+"main");
		var el = element.parentNode ;
		while ( el ) {
			if (el.nodeName.toLowerCase() == "form") {
				break ;
			}
			el = el.parentNode ;
		}

		if (el){
			el.attachEvent( 'onsubmit', updateValue ) ;
		}

		ToolbarSets.Redraw();
		if (is_setCursor==1){
			E.Focus(true, true);
		} else {
			updateValue();
		}
//	} catch (e){}
};

function updateValue() {
	E.commands.getCommand('Save').execute("no");
	return true;
}

mouseisdown=false;

Editor.prototype.setdown = function()
{
	mouseisdown=true;
	return true;
};

Editor.prototype.setup = function(e)
{
	mouseisdown=false;
	if (e==null) {
		e = window.event;
	}
	if (!e) {
		return true;
	}

	if (e.srcElement && e.srcElement.tagName.toLowerCase()=="img" && e.srcElement.id ){
		if (e.srcElement.id.indexOf("de_add")>=0){
			addblock(e.srcElement, e);
			return false;
		} else if (e.srcElement.id.indexOf("de_del")>=0){
			delblock(e.srcElement, e);
			return false;
		}
	}

	PopupSet.Redraw();
	ToolbarSets.Redraw(e);

	return true;
};

// create Editor object
Editor.prototype.Create = function()
{
	// instanceName should not be empty
	if ( !this.InstanceName || this.InstanceName.length == 0 ) {
		this.throwError( 1, 'You must specify a instance name.' ) ;
		return ;
	}

	// check browser compatible
	if (!this.isCompatibleBrowser()) {
		this.throwError( 2, 'Browser is not compatible.' ) ;
		return ;
	}

	// instert editor into page
	var htmlstr="";
	htmlstr+= '<div id="'+this.InstanceName+'main1" style="background-color:gray;height:100%;width:100%;">'
	htmlstr+= '<table  width="100%" height="100%" class="de_container" border="0px" cellspacing="0" cellpadding="0" ><tr><td>';
	htmlstr+= '<div id="eToolbar"></div></td></tr><tr><td width="100%" height="100%" class="editcontainer2">';
	htmlstr+= '<table width="100%" height="100%" border="0" cellspacing="0" cellpadding="0"><tr><td valign=top id="leftPanel"><img src="images/1x1.gif" width="1px">&nbsp</td><td valign=top width="100%" height="100%">';
	htmlstr+= '<iframe src="empty.html" onBlur="updateValue();" width="100%" height="100%" class="de_editcontainer" id="' + this.InstanceName + '_frame'+'"'+' onLoad="setEvent()" scrolling="yes" frameborder="no"></iframe>';
	htmlstr+= '<iframe src="empty.html" id="' + this.InstanceName + '_preview'+'" width="100%" height="100%" scrolling="yes"  frameborder="0" class="de_editcontainer" style="display:none;"></iframe>';
	htmlstr+= '</td><td valign=top width="1px"><img src="images/1x1.gif" width="1px">&nbsp;</td></tr></table>';
	htmlstr+= '</td></tr>';
	htmlstr+= '<tr><td><img id="'+this.InstanceName+'fb01" src="images/1x1.gif" height=5px></td></tr>';
	htmlstr+= '<tr '+(hideTagBar?'style="display:none;"':'')+'><td class="de_TB_Toolbar" class="pathtext"><table width="100%" border="0" cellspacing="0" cellpadding="0" ><tr><td><span id="ePath"></span></td><td><span style="float:right" class="de_pathcontainer" id="eRemoveTag"></span></td></tr></table></td></tr>';

	if (!(hideitems["EditMode"]==1 && hideitems["SourceMode"]==1 && hideitems["PreviewMode"]==1)){
		htmlstr+= '<tr><td class="de_TB_Toolbar"><table border="0" cellspacing="0" cellpadding="0" ><tr><td><div id="footersheet"></div></td>';
		htmlstr+= '<td width="100%" valign=top  class="de_TB_Toolbar"><table cellspacing="0" cellpadding="0" border="0" width="100%" ><tr><td width="100%"><div class="de_sheetline1" width="100%" height="1px"></div></td></tr>';
		htmlstr+= '<tr><td width="100%"><div class="de_sheetline2" width="100%" height="1px"></div></td></tr>';
		htmlstr+= '<tr><td align="right"><div id="eFooter"></div></td></tr>';
		htmlstr+= '</table></td></table>';
	}

	htmlstr+= '</td></tr></table>';
	htmlstr+= '</table>';

	htmlstr+= '</div>';

	document.write(htmlstr);
	aID = this.InstanceName + '_frame';
	window.aID = aID;
	this._frame=document.frames[aID].document;
	this._window=document.frames[aID];
	window.fr = this._frame;

	this._frame.designMode = "on";
	this._frame=document.frames[aID].document;

	if (new_layout){
		tlb_H = DevEditToolbarSets[toolbarmode].length * 27;
		dH = 51+tlb_H;
		if (hideTagBar)dH = dH - 23;
		H = parent.document.getElementById(this.InstanceName + 'main').style.pixelHeight;
		W = parent.document.getElementById(this.InstanceName + 'main').style.pixelWidth;
		document.getElementById(this.InstanceName + "_frame").height = H-dH;
	}

	this.checkLoad();
};

Editor.prototype.ContextMenu = function(evt)
{
	evt = (evt)?evt:(window.event)?window.event:"";

	if (hideitems["ContextMenu"]){
		evt.cancelBubble=true;
		evt.returnValue=false;
	} else {

		Selection.set();

		if (!evt.ctrlKey) {
			if (!E.commands.getCommand("Contextmenu").isopening){
				E.commands.getCommand("Contextmenu").execute(null,evt.clientX,evt.clientY);
			}
			evt.cancelBubble=true;
			evt.returnValue=false;
		}
		evt.cancelBubble=true;
		x = E._frame.fireEvent("onselectionchange");
		PopupSet.Redraw();
	}
};

Editor.prototype.checkEditArea = function()
{
	check = false;
	findAllEditable(this._frame.body);
	E.isbegin = check;
	E.isend = check;
};

Editor.prototype.lockPage = function()
{
	E.unlock = false;
	E.checkEditArea();
	E.Editable();
};

Editor.prototype.unlockPage = function()
{
	E.unlock = true;
	E.isbegin = false;
	E.isend = false;
};

var lastTag = null;
var must_edit = false;
Editor.prototype.Editable = function(e)
{
	var selectedRange = E._frame.selection.createRange();
	var sel = E._frame.selection;
	var range = sel.createRange();
	switch (sel.type) {
		case "Text":
			oContainer = range.parentElement();
			break;
		case "None":
			oContainer = range.parentElement();
			break;
		case "Control":
			oContainer = range.item(0);
			break;
		default:
			oContainer = aed.body;
			break;
	}

	if (e && e.type && e.type=="controlselect"){
		E.editable = true;
		lastTag = oContainer.tagName;
		must_edit = false;
		return true;
	}

	var isEditable = E.unlock || E.walkDOM(oContainer);

	if (insideWrap) {
		oContainer=wrap;
	}

	try{
		if (oContainer && oContainer.id && oContainer.id.substr(0,7)=="de_wrap") {
			var cR = E._frame.body.createTextRange();
			cR.moveToElementText(oContainer);

			// The current selection<br>
			var r = E._frame.selection.createRange();
			// We'll use this as a 'dummy'<br>
			var stored_range = r.duplicate();
			// Select all text<br>
			stored_range.moveToElementText( oContainer );
			// Now move 'dummy' end point to end point of original range<br>
			stored_range.setEndPoint( 'EndToEnd', range );
			// Now we can calculate start and end points<br>
			sStart = stored_range.text.length - range.text.length;
			sEnd = sStart + range.text.length;

			//isEditable = true;
			if ( (sStart==0 && (e.keyCode==8 || e.keyCode==37 || e.keyCode==38) ) // start & backspace
				|| ((cR.text.length == sStart ) && (e.keyCode==46 || e.keyCode==39 || e.keyCode==40 || selectedRange.text ))//end & del
			) {
				isEditable=false;
			}
		}
	} catch(x){}

	if (e){
		if (E.walkDOM && isEditable) {
			E.editable = true;
			return true;
		} else {
			e.cancelBubble=true;
			e.returnValue=false;
			E.editable = false;
			return false;
		}

	} else {
		if (E.walkDOM && isEditable) {
			return true;
		} else {
			return false;
		}
	}
};

Editor.prototype.CheckEditable = function(evt)
{
	e = (evt)?evt:(window.event)?window.event:"";

	if (e.srcElement && e.srcElement.tagName.toLowerCase()=="img" && e.srcElement.id ){
		if (e.srcElement.id.indexOf("de_add")>=0 || e.srcElement.id.indexOf("de_del")>=0){
			return false;
		}
	}


	// 1 click for DIV
	if (e.srcElement && e.srcElement.tagName && (e.srcElement.tagName.toLowerCase() == "div" || e.srcElement.tagName.toLowerCase() == "span")){
		one_click = true;
	}
	// end 1 click

	return E.Editable(e);
};

var edt = false;
var lastedt = false;
one_click = false;

// source engine var's
context_str="";
tag_typing = false;
startBookmark = null;

// redraw
Editor.prototype.Redraw = function(e)
{
	Selection.set();
	loading_in_progress = false;
	var cShow = false;

	if(!e) {
		e = window.event;
	}
	if (!e) {
		return true;
	}

	var x = e.clientX;
	var y = e.clientY;

	lastedt = edt;
	edt = E.Editable(e);

	var se = E.GetSelectedElement();
	if (!edt && !(se && se.tagName && (se.tagName.toLowerCase()=="div" || se.tagName.toLowerCase()=="span"))) {
		PopupSet.Redraw();
		ToolbarSets.Redraw(e);
		return false;
	}

	// 1 click for DIV
	if (se && se.tagName && (se.tagName.toLowerCase()=="div" || se.tagName.toLowerCase()=="span")){
		try {
			var range = E._frame.body.createTextRange();
			range.moveToPoint(x,y);
			range.collapse();
			range.select();
			one_click = true;
		}catch(x){}
	}
	// end 1 click

//	try{
	// check spell words
	cancel_event = false;

	if (!e.ctrlKey && e.type=="keydown" && E.mode=="edit"){
		var specialchar = false;
		for (var i=0;i<specialKeyCode.length;i++){
			if (specialKeyCode[i]==e.keyCode){
				specialchar=true;
				break;
			}
		}

		;

		if ((e.keyCode && (e.keyCode>32 && e.keyCode<256) && !e.ctrlKey && !sKey[e.keyCode])
		&& (buffer[E.mode].devhistory.position==0 || E._frame.selection.createRange().parentElement()!==this.lastContainer || ( E._frame.selection.createRange().htmlText.length!==this.lastOffset && E._frame.selection.createRange().htmlText.length!==this.lastOffset+1))){
			buffer[E.mode].saveHistory();
			PopupSet.Redraw();
			ToolbarSets.Redraw(e);
			return true;
		}
		if (!specialchar) {
			return E.editable;
		}
	}

	var f=false;
	var shortcut=false;
	if (E.toolbaritems.GetItem('Path')) {
		E.toolbaritems.GetItem('Path').Redraw();
	}
	if (e.ctrlKey) {
		var key = String.fromCharCode(e.keyCode).toUpperCase();

		if (key=="X" || key=="V"){

			var div = E._frame.getElementById('anchor_div');
			if(!div){

				var anchor_div = "<span id='anchor_div' style='width:1px;height:1px;'> </span>";
				insertNodeAtSelectionIE(anchor_div);

				var div = E._frame.getElementById('anchor_div');
				var div_prop = getElemProp(div);
				var r = E._frame.selection.createRange();
				r.move("character",-2);
				r.collapse();
			    r.select();

				setTimeout("restoreUrls()",100);
				setTimeout("clearContentBlocks();",200);
				buffer[E.mode].saveHistory();
			}

		}
		for(var i=0; i < ShortCutKeys.length; i++){
			var k = ShortCutKeys[i][0];
			if (k.toUpperCase().indexOf("SHIFT")>=0 && e.shiftKey && key==k.substr(k.indexOf("+")+1,1)) {
				f=true;
			} else if (key == k) {
				f=true;
			}

			if (f) {
				if (E.commands.getCommand(ShortCutKeys[i][1]).getMode()==OFF){
					E.commands.getCommand(ShortCutKeys[i][1]).execute();
					shortcut = true;
					cShow = true;
				}
				f = false;
			}
		}
		PopupSet.Redraw();
		ToolbarSets.Redraw(e);
	}

	E.lastinsert = null;


	// Enter - if useBR=1 then use <br/>
	if(E.parentNode("LI") == null) {

	if (e.keyCode==13 && cancel_event==false) {
		if (useBR==1) {
			var sel = E._frame.selection;
			if (sel.type == "Control") {
				return;
			}

			if (!e.shiftKey) {
				buffer[E.mode].saveHistory(e.keyCode);
				var r = sel.createRange();
				r.pasteHTML("<BR/>");
				e.cancelBubble = true;
				e.returnValue = false;

				r.select();
				r.moveEnd("character", 1);
				r.moveStart("character", 1);
				r.collapse(false);
				return false;
			} else {

				if (E.parentNode("LI")) {
					//
				} else {
					buffer[E.mode].saveHistory(e.keyCode);
					var r = sel.createRange();
					if (r.parentElement() && r.parentElement().tagName && r.parentElement().tagName.toLowerCase()=="p"){
						p = r.parentElement();
						x = p.nextSibling;

						var range = E._frame.body.createTextRange();
						range.moveToElementText(p);
						ft = range.htmlText;
						range.setEndPoint("EndToStart", r);
						var rangeLength = range.htmlText.length;

						ft = ft.replace(/^[\r\n\f]+?<([^>]+)>/gi,"");
						ft = ft.replace(/<([^>]+)>$/gi,"");
						ft1 = ft.substr(0,rangeLength);
						ft1 = ft1.replace(/^[\r\n\f]+?<([^>]+)>/gi,"");
						ft1 = ft1.replace(/<([^>]+)>$/gi,"");

						var newP = E._frame.createElement("P");
						newP.innerHTML = ft1;
						var newP2 = E._frame.createElement("P");
						newP2.innerHTML = ft.substr(rangeLength,ft.length-rangeLength);

						if (x){
							p.parentNode.insertBefore(newP2,x);
						} else {

							if (newP2.innerHTML){
								p.parentNode.appendChild(newP2);
								newP2.id="temp_p";
								p.parentNode.appendChild(newP2);
								var x = E._frame.getElementById("temp_p");
								r.moveToElementText(x);
								x.removeAttribute("id");
								r.collapse(true);
								r.select();
							} else {
								newP2.innerHTML="&nbsp;";
								newP2.id="temp_p";
								p.parentNode.appendChild(newP2);
								var x = E._frame.getElementById("temp_p");
								r.moveToElementText(x);
								x.removeAttribute("id");
								r.select();
							}

						}
						p.parentNode.replaceChild(newP,p);
						return false;

					} else {
						if (r.parentElement() && r.parentElement().tagName){
							buffer[E.mode].saveHistory(e.keyCode);
							var range = E._frame.body.createTextRange();
							range.moveToElementText(r.parentElement());
							r.setEndPoint("EndToEnd", range);

							if (r.htmlText){
								if (r.parentElement().tagName.toLowerCase()!=="body"){
									r.moveEnd("character",-1);
								}
								r.select();

								r.pasteHTML("<p id='temp_p'>"+r.htmlText+"</p>");
								var p = E._frame.getElementById("temp_p");
								r.moveToElementText(p);
								p.removeAttribute("id");
								r.collapse(true);
								r.select();
							} else {
								r.select();
								r.pasteHTML("<p id='temp_p'>&nbsp;"+r.htmlText+"</p>");
								var p = E._frame.getElementById("temp_p");
								r.moveToElementText(p);
								p.removeAttribute("id");
								r.select();
							}

							e.cancelBubble = true;
							e.returnValue = false;

							return false;

						}
					}
				}
			}
		} else {

			var sel = E._frame.selection;
			if (!e.shiftKey && E.parentNode("DIV")) {
				buffer[E.mode].saveHistory(e.keyCode);
				var r = sel.createRange();
				r.pasteHTML("<p>");
				e.cancelBubble = true;
				e.returnValue = false;

				r.collapse(true);
				r.select();
				return false;
			}

			if (E.mode=="source") {
				buffer[E.mode].saveHistory();
				var r = sel.createRange();
				r.pasteHTML("<BR>");
				e.cancelBubble = true;
				e.returnValue = false;

				r.select();
				r.moveEnd("character", 1);
				r.moveStart("character", 1);
				r.collapse(false);

				return false;
			}
		}
		cShow = true;
	}
}

	if (!e.ctrlKey && (e.keyCode==0 && !mouseisdown && e.type!="keydown"&& e.type!="selectionchange")) {
		PopupSet.Redraw();
		ToolbarSets.Redraw(e);
		cShow = true;
	}
	if (shortcut || cancel_event) {
		e.cancelBubble = true;
		e.returnValue = false;
	}

	if (cShow){
		setTimeout("E.commands.getCommand('Paragraph').showChar()",20);
	}

	if(!e.ctrlKey && e.keyCode != 90 && e.keyCode != 89) {
		if (e.keyCode == 32 || e.keyCode == 13 || e.keyCode == 46) {
			buffer[E.mode].saveHistory(e.keyCode);
		}
	}

	e.cancelBubble=true;
//	} catch(e){}
	ToolbarSets.Redraw();
	E.commands.getCommand('Paragraph').showChar();
	return true;
};

Editor.prototype.KeyPress = function(e)
{
	try{
		this.lastContainer = E._frame.selection.createRange().parentElement();
		this.lastOffset = E._frame.selection.createRange().htmlText.length;
	} catch(e){}
}

Editor.prototype.CheckUp = function(e)
{
	e = (e)?e:(window.event)?window.event:"";

	if (e.keyCode >= 37 && e.keyCode <= 40) {
		PopupSet.Redraw();
		ToolbarSets.Redraw(e);
	}
	if (e.shiftKey && (e.keyCode==35 || e.keyCode==36)) {
		PopupSet.Redraw();
		ToolbarSets.Redraw(e);
	}

	if (edt && !lastedt){
		PopupSet.Redraw();
		ToolbarSets.Redraw(e);
	}
	if(!e.ctrlKey && e.keyCode != 90 && e.keyCode != 89) {
		if (e.keyCode == 32 || e.keyCode == 13 || e.keyCode == 46) {
			PopupSet.Redraw();
			ToolbarSets.Redraw(e);
		}
	}

	return true;
};

one_onclick = true;
Editor.prototype.Focus = function(set_focus,loaded_page){
	try{
		if (!one_onclick || set_focus==true)E._window.focus();
	} catch ( e ) {}
};

// this method check browser compatible
Editor.prototype.isCompatibleBrowser = function()
{
	if (browser.IE) {
		var sBrowserVersion = navigator.appVersion.match(/MSIE (.\..)/)[1] ;
		return ( sBrowserVersion >= 5.5 ) ;
	} else {
		return false ;
	}
};

// show errors
Editor.prototype.throwError = function( errorNumber, errorDescription )
{
	this.ErrorNumber		= errorNumber ;
	this.ErrorDescription	= errorDescription ;

	document.write( '<div style="COLOR: #ff0000">' ) ;
	document.write( '[ Editor Error ' + this.ErrorNumber + ': ' + this.ErrorDescription + ' ]' ) ;
	document.write( '</div>' ) ;
};

Editor.prototype.clearAll = function()
{
	var text = (browser.NS?'&nbsp;':'');
	this._frame.body.innerHTML = text;
};

Editor.prototype.clearContent = function()
{
	var text = (browser.NS?'&nbsp;':'');
	this._frame.body.innerHTML = text;
};

Editor.prototype._insert_into_span = function(text)
{
	sel = this._frame.selection;
	range = sel.createRange();
	oContainer = range.parentElement();
	if (oContainer)oContainer.outerHTML = text;
};

Editor.prototype._inserthtml = function(text, ignore)
{
	this.Focus(true);
	buffer[this.mode].saveHistory();
	var newNode = insertNodeAtSelectionIE(embed2img(addWrap(text,1),true),ignore);
	PopupSet.Redraw();
	ToolbarSets.Redraw();
	return newNode;
};

Editor.prototype._insertBefore = function(text)
{
	this.Focus(true);
	buffer[this.mode].saveHistory();

	var aed = E._frame;
	var sel = E._frame.selection;
	var newNode = sel.createRange();

	var range = aed.body.createTextRange();

	newNode.moveStart("character",-1);
	l = 100;
	while (newNode.text.substr(0,1)!=="<" && l){
		newNode.moveStart("character",-1);
		l--;
	}
	newNode.select();

	addText = newNode.text.replace(/([\/\n\f\r])/gi,"");
	addText = addText.replace(/</gi,"&lt;");
	addText = addText.replace(/>/gi,"&gt;");

	text = addText+text;

	if ( sel.type.toLowerCase() !== "none" ) {
		sel.clear() ;
	}

	text = colourCode(text);
	newNode.pasteHTML (text);
	newNode.moveEnd("character",-1);
	var x = newNode.parentElement();
	newNode.moveToElementText(x);
	newNode.collapse();
	newNode.select();

	PopupSet.Redraw();
	ToolbarSets.Redraw();
	return newNode;
};

Editor.prototype.insertHTML = function(text)
{
	E.Focus(true);
	buffer[this.mode].saveHistory();
	var newNode = insertNodeAtSelectionIE(embed2img(addWrap(text,1)),1,true);
	PopupSet.Redraw();
	ToolbarSets.Redraw();
	E.commands.getCommand('Save').execute("no");
	return newNode;
};

Editor.prototype.parentNode = function( nodeTagName )
{
	return this.parentNodeIE(nodeTagName);
};

Editor.prototype.GetType = function()
{
	return this.GetTypeIE();
};


Editor.prototype.getSelectedElement = function()
{
	return this.GetSelectedElementIE();
};

Editor.prototype.GetSelectedElement = function()
{
	return this.GetSelectedElementIE();
};

Editor.prototype.GetTypeIE = function()
{
	return this._frame.selection.type ;
};

Editor.prototype.GetSelectedElement2 = function() {
	sel = this._frame.selection;
	range = sel.createRange();
	var oContainer=null;
	switch (sel.type) {
		case "Text":
			oContainer = range.parentElement();
			break;
		case "None":
			oContainer = range.parentElement();
			break;
		case "Control":
			oContainer = range.item(0);
			break;
		}
		if (oContainer==this._frame.body) {
			oContainer=null;
		}
	return oContainer;
};

Editor.prototype.GetSelectedElementIE = function()
{
	if ( this.GetTypeIE() == 'Control' ) {
		var oRange = this._frame.selection.createRange() ;
		if ( oRange && oRange.item ) {
			return this._frame.selection.createRange().item(0) ;
		}
	}
};

Editor.prototype.parentNodeIE = function( nodeTagName )
{
	var oNode ;
	if ( E._frame.selection.type == "Control" ) {
		var oRange = E._frame.selection.createRange() ;
		for ( i = 0 ; i < oRange.length ; i++ ) {
			if (oRange(i).parentNode) {
				oNode = oRange(i).parentNode ;
				break ;
			}
		}
	} else {
		var oRange  = E._frame.selection.createRange() ;
		oNode = oRange.parentElement() ;
	}

	while ( oNode && oNode.nodeName != nodeTagName ) {
		oNode = oNode.parentNode ;
	}

	return oNode ;
};

Editor.prototype.firstParentNode = function()
{
	var oNode ;
	try {
		if ( E._frame.selection.type == "Control" ) {
			var oRange = E._frame.selection.createRange() ;
			for ( i = 0 ; i < oRange.length ; i++ ) {
				if (oRange(i).parentNode) {
					oNode = oRange(i).parentNode ;
					break ;
				}
			}
		} else {
			var oRange  = E._frame.selection.createRange() ;
			oNode = oRange.parentElement() ;
		}
	} catch (e) {}

	return oNode ;
};

Editor.prototype.selectNode = function(node){
	try	{
		var range = this._frame.body.createControlRange();
		range.add(node);
		range.select();
	} catch(e) {
		try	{
			var range = this._frame.body.createTextRange();
			range.moveToElementText(node);
			range.select();
		} catch(e){return;}
	}
};

Editor.prototype._inserthtml_and_select = function(text, select_id){
	var sel = this._frame.selection;
	if (sel!=null) {
		if ( sel.type.toLowerCase() != "none" ) {
			sel.clear() ;
		}
		var newNode = sel.createRange();
		newNode.pasteHTML (text);

		var node = aed.getElementById(select_id);
		if (node){
			newNode.moveToElementText(node);
			newNode.select();
		}
	}
	// end
}

function insertNodeAtSelectionIE (text, i, specialtag, before) {

	var aed = E._frame;
	var sel = E._frame.selection;
	if (sel!=null) {
		if ( sel.type.toLowerCase() != "none" ) {
			sel.clear() ;
		}
		var newNode = sel.createRange();

		var bm = null;
		var bm2 = null;
		var ti = false;

		if (specialtag && text.substr(0,1)=="<"){
			ti=true;
			text = "x"+text;
			bm = newNode.duplicate();
		}

		if (before){
			bm = newNode.duplicate();
		}
		newNode.pasteHTML (text);

		if (ti){
			bm2 = newNode.duplicate();
		}


		if (bm){
			newNode.setEndPoint("StartToStart",bm);
			newNode.select();
			newNode.collapse();
			newNode.select();
		}

		if (ti){
			newNode.moveEnd("character",1);
			newNode.text="";
			newNode.setEndPoint("StartToEnd",bm2);
			newNode.collapse(false);
			newNode.select();
		}

		var node = aed.getElementById("_de_temp_element");
		if (node){
			newNode.moveToElementText(node);
			newNode.select();
			node.removeAttribute("id");
			E.currentNode = node;
			this.selectedtag = node;
			E.lastinsert = node;
		}
		return newNode;
	}
}

Editor.prototype.GetSelection = function()
{
	return this.GetSelectionIE();
};

Editor.prototype.getSelectedText = function()
{
	return this.GetSelectionIE();
};

Editor.prototype.getSelectedHTML = function()
{
	var oRange = this._frame.selection.createRange();
	return oRange.htmlText;
};

Editor.prototype.GetSelectionIE = function()
{
	var oRange = this._frame.selection.createRange();
	return oRange.text;
};

Editor.prototype.replaceNodeByText = function(obj)
{
	obj.outerHTML = obj.innerText;
};

Editor.prototype.doStyles = function()
{
	this.Styles			= new Array();
	this.cssText		= new Array();
	var sheets = this._frame.styleSheets;
	var through = false;
	if (sheets.length > 0) {
		// loop over each sheet
		for (var x = 0; x < sheets.length; x++) {
			if (sheets[x] && sheets[x].href && sheets[x].href.indexOf(border_css_file)>=0) {
				continue;
			}
			// grab stylesheet rules
			try
			{
				var rules = sheets[x].rules;
			}
			catch (err)
			{
				through = true;
			}
			if (through)
			{
				this.Styles = cached_Styles;
				this.cssText = cached_cssText;
				return true;
			}
			if (rules.length > 0) {
				cssloaded = 1;
				// check each rule
				for(var y = 0; y < rules.length; y++) {
					sT = rules[y].selectorText;
					if (sT.substr(0,1)=="."){
						sT=sT.substr(1);
						if (sT.indexOf(" ")>0) {
							sT = sT.substring(0,sT.indexOf(" "));
						}
						if (sT.toLowerCase().indexOf("wep_")==0 || sT.toLowerCase().indexOf("de_")==0)continue;
						style_twice = false;
						for (var z = 0; z < this.Styles.length; z++){
							if (sT == this.Styles[z]){
								this.cssText[z] = this.cssText[z] + (this.cssText[z].lastIndexOf(";")==this.cssText[z].length ? "" : ";") +rules[y].style.cssText;
								style_twice = true;
								break;
							}
						}
						if (!style_twice){
							this.Styles[this.Styles.length] = sT;
							this.cssText[this.cssText.length] = rules[y].style.cssText;
						}
					}
				}
				cached_Styles = this.Styles;
				cached_cssText = this.cssText;
			}
		}
	}
};

Editor.prototype.isFlash = function(x)
{
	var cn;
	cn = x.getAttribute("className");
	if (cn=="de_flash_file") {
		return true;
	} else {
		return false;
	}
};

Editor.prototype.isMedia = function(x)
{
	var cn;
	cn = x.getAttribute("className");
	if (cn=="de_media_file") {
		return true;
	} else {
		return false;
	}
};

Editor.prototype.checkTags = function(tags)
{
	var tags = tags.split("|");
	var r;
	for (var i=0; i<tags.length; i++) {
		switch (tags[i]) {
			case "empty":
				if (this.GetSelection()=="") {
					r = OFF;
				} else {
					r = DISABLED;
				}
				break;
			case "text":
				if (this.GetType()=="Control") {
					r = DISABLED;
				} else {
					if (this.GetSelection()!="") {
						r = OFF;
					} else {
						r = DISABLED;
					}
				}
				break;
			case "flash":
				var x = E.GetSelectedElement();
				if (x && this.isFlash(x)) {
					return OFF;
				} else {
					return DISABLED;
				}
				break;
			case "media":
				var x = E.GetSelectedElement();
				if (x && this.isMedia(x)) {
					return OFF;
				} else {
					return DISABLED;
				}
				break;
			case "link":
				if (E.GetType()=="Control") {
					var  x = Selection.parentNode("A");
					if (!x) {
						return DISABLED;
					}
					if (x.href) {
						if (x.href.indexOf("mailto:")==-1) {
							return OFF;
						} else {
							return DISABLED;
						}
					}
				} else if (E.GetSelection()!=""){
					var x = E.GetSelectedElement();
					if (!x) {
						return OFF;
					}
					if (x.href&&x.href.indexOf("mailto:")==-1) {
						return OFF;
					}
				}
				break;
			default:
				var x = this.GetSelectedElement();
				if (!x) {
					x = Selection.parentNode(tags[i]);
				}
				if (!x) {
					return DISABLED;
				}
				if (x && x.getAttribute("className") && (x.getAttribute("className")=="de_flash_file" || x.getAttribute("className")=="de_media_file")) {
					return DISABLED;
				}
				if (x && x.tagName && tags[i].toUpperCase()==x.tagName.toUpperCase()) {
					r=OFF;
				} else {
					r = DISABLED;
				}
		}
		if (r==OFF) {
			return OFF;
		}
	}
	return DISABLED;
};


Editor.prototype.storePos = function()
{
	this.Pos = null;
	var selection = this._frame.selection;
	if (selection.type.toLowerCase() == 'text'||selection.type.toLowerCase() == 'none') {
		this.Pos =  selection.createRange().getBookmark();
	}
};

Editor.prototype.restorePos = function()
{
	if (this.Pos){
		var range = this._frame.body.createTextRange();
		range.moveToBookmark(this.Pos);
		range.select();
	}
};

var checkbegin	= false;
var checkend	= false;
var traverse_end = false;
var check		= false;
var ret			= false;
var insideWrap	= false;
var wrap = null;

Editor.prototype.walkDOM = function(node)
{
	if (!node) {
		return false;
	}
	traverse_end = false;
	checkbegin	= false;
	checkend	= false;
	ret			= false;
	insideWrap	= false;
	wrap = null;
	if (E.unlock) {
		return true;
	}
	if (!E.isbegin && !E.isend) {
		return true;
	}
	traverse(this._frame.body,node);
	if (checkbegin && !checkend ) {
		return true;
	} else {
		return false;
	}
};

Editor.prototype.updateSpellButton = function(){
	E.commands.getCommand("Spellcheck").mode = ON;
	ToolbarSets.Redraw();
};


function traverse(node,selnode)
{
	if (ret) {
		return;
	}
	if (node && node.id && node.id.substr(0,7)=="de_wrap") {
		insideWrap=true;
		wrap=node;
	}
	if (node.nodeType == 8) {
		if (node.nodeValue.toLowerCase().indexOf("begineditable")>=0) {
			checkend = false;
			checkbegin = true;
		}
		if (node.nodeValue.toLowerCase().indexOf("endeditable")>=0) {
			checkend = true;
		}
		if (checkbegin && checkend) {
			check=true;
			checkend=false;
			checkbegin=false;
		}
	}
	if (node==selnode){
		ret=true;
		return;
	}
	if (node.childNodes != null) {
		for ( var i=0; i < node.childNodes.length; i++) {
			traverse(node.childNodes.item(i),selnode);
		}
	}
}

function findAllEditable(node)
{
	if (check==true) {
		return;
	}
	if (node.nodeType == 8) {
		if (node.nodeValue.toLowerCase().indexOf("begineditable")>=0) {
			checkend = false;
			checkbegin = true;
		}
		if (node.nodeValue.toLowerCase().indexOf("endeditable")>=0) {
			checkend = true;
		}
		if (checkbegin && checkend) {
			check=true;
			checkend=false;
			checkbegin=false;
		}
	}
	if (node.childNodes != null) {
		for ( var i=0; i < node.childNodes.length; i++) {
			findAllEditable(node.childNodes.item(i));
		}
	}
}

// function below fix IE bug

// convert attribute name inside style defenition to lower case.
function convert_attr_name_to_lowercase(code)
{
	r = /(style=["'][^"']*?["'])/gi;
	return code.replace(r,function(s1,s2){
							s2 = s2.replace(/;?([^:]*)/g,function(d1,d2){return d2;}//.toLowerCase()
						);
			return s2;
	});
}

// move cursor left by 1 character right and then left
function move_cursor_right_and_left() // fix_bug_02
{
	try{
		var sel = E._frame.selection;
		var r = sel.createRange();
		r.moveEnd("character", 1);
		r.moveStart("character", 1);
		r.collapse(false);
		r.select();
		window.setTimeout("move_cursor_right_to_100_and_back()",10);
	} catch(e){}
}

// move cursor right to 100 character and than back
function move_cursor_right_to_100_and_back()
{
	try{
		var sel = E._frame.selection;
		var r = sel.createRange();
		r.moveEnd("character", -100);
		r.moveStart("character", -100);
		r.collapse(false);
		r.select();
	} catch(e){}
}

// convert align="center" to  align="middle"
function convert_align_middle_to_center(code)
{
	r = /(\salign="middle")/gi;
	r1 = /(\salign=middle)/gi;
	code = code.replace(r," align=\"center\"");
	code = code.replace(r1," align=center");
	return code;
}

// browser strip <param> tag from OBJECT TAG
function convert_param_tag_to_xhtml(code)
{
	if (useXHTML != 1) {
		// Make param tags <param .... ></param>
		r = /(<param(.*?)>)[^<\/param>]/gi;
		code = code.replace(r, "$1</PARAM>");
	}

	return code;
}

function set_cursor_at_begin()
{
	try{
	var sel = E._frame.selection;
		var r = sel.createRange();
		r.moveToElementText(E._frame.body);
		r.select();
		r.collapse(true);
		r.select();

	} catch(e){}
}

// Name: XHTML function
// Info: XHTML function.

function getXHTML(content) {
  var html = new cls_html();
  html.setHTML(content);
  return (html.toXHTML());
}

/**
 *_NULL_
 */
Array.prototype.clone = __prototype_array_clone;
function __prototype_array_clone() {
  var temp = [];
  for(var i in this) {
    if (typeof this[i] == "object") {
      temp[i] = this[i].clone();
    } else {
      temp[i] = this[i];
    }
  }
  return temp;
}

var XHTML_TEMP_VAR = a;
a = null;
var a = new Array();
a['p'] = 1;             a['span'] = 1;		    a['a'] = 1;	          a['div'] = 1;
a['b'] = 1;		          a['u'] = 1;	          a['i'] = 1;	          a['td'] = 1;
a['img'] = 1;		        a['table'] = 1;	      a['input'] = 1;	      a['li'] = 1;
a['ol'] = 1;	          a['script'] = 1;	    a['br'] = 1;	        a['textarea'] = 1;
a['strong'] = 1;		    a['center'] = 1;	    a['cite'] = 1;	      a['code'] = 1;
a['col'] = 10;		      a['colgroup'] = 1;	  a['dd'] = 1;	        a['del'] = 1;
a['dir'] = 1;  		      a['dfn'] = 1; 	      a['acronym'] = 1;	    a['dl'] = 1;
a['dt'] = 1;		        a['em'] = 1;	        a['fieldset'] = 1;	  a['font'] = 1;
a['form'] = 1;		      a['frame'] = 1;	      a['frameset'] = 1;	  a['h1'] = 1;
a['h2'] = 1;		        a['h3'] = 1;	        a['h4'] = 1;	        a['h5'] = 1;
a['h6'] = 1;		        a['head'] = 1;	      a['hr'] = 1;	        a['html'] = 1;
a['area'] = 1;		      a['iframe'] = 1;	    a['base'] = 1;	      a['bdo'] = 1;
a['ins'] = 1;	  	      a['isindex'] = 1;	    a['kbd'] = 1;	        a['label'] = 1;
a['legend'] = 1;		    a['big'] = 1;	        a['link'] = 1;	      a['map'] = 1;
a['menu'] = 1;		      a['meta'] = 1;	      a['noframes'] = 1;	  a['noscript'] = 1;
a['object'] = 1;		    a['blockquote'] = 1;	a['optgroup'] = 1;	  a['option'] = 1;
a['!doctype'] = 1;      a['param'] = 1;	      a['pre'] = 1;	        a['q'] = 1;
a['s'] = 1;             a['samp'] = 1;	      a['body'] = 1;	      a['select'] = 1;
a['small'] = 1; 		    a['abbr'] = 1;	      a['strike'] = 1;	    a['caption'] = 1;
a['style'] = 1; 	      a['sub'] = 1;	        a['sup'] = 1;	        a['basefont'] = 1;
a['tbody'] = 1;	        a['address'] = 1;	    a['button'] = 1;	    a['tfoot'] = 1;
a['th'] = 1;		        a['thead'] = 1;	      a['title'] = 1;	      a['tr'] = 1;
a['tt'] = 1;		        a['applet'] = 1;	    a['ul'] = 1;	        a['v'] = 1;
a['embed'] = 1;         a['marquee'] = 1;     a['!doctype'] = 1;    a['!--'] = 1;
_xhtml_parser_aTags = a;
xxx=111;
a = null;
a = XHTML_TEMP_VAR;

/**
 * HTML : <hr noshade>
 * XHTML: <hr noshade="noshade" />
 */
var aEmptyAttributes = new Array();
aEmptyAttributes['compact'] = 1;
aEmptyAttributes['nowrap'] = 1;
aEmptyAttributes['ismap'] = 1;
aEmptyAttributes['declare'] = 1;
aEmptyAttributes['noshade'] = 1;
aEmptyAttributes['checked'] = 1;
aEmptyAttributes['disabled'] = 1;
aEmptyAttributes['readonly'] = 1;
aEmptyAttributes['multiple'] = 1;
aEmptyAttributes['selected'] = 1;
aEmptyAttributes['noresize'] = 1;
aEmptyAttributes['defer'] = 1;
aEmptyAttributes['nosave'] = 1;
var _xhtml_parser_aEmptyAttributes = aEmptyAttributes;

/**
 * Alle tags die geen sluittag hebben. Die tags moeten een slash aan het eind krijgen
 *
 * HTML : <br>
 * XHTML: <br />
 */
var aEmptyTags = new Array();
aEmptyTags['br'] = 1;
aEmptyTags['img'] = 1;
aEmptyTags['input'] = 1;
aEmptyTags['hr'] = 1;
aEmptyTags['link'] = 1;
aEmptyTags['meta'] = 1;
aEmptyTags['embed'] = 1;
aEmptyTags['area'] = 1;
aEmptyTags['param'] = 1;
aEmptyTags['base'] = 1;
aEmptyTags['basefont'] = 1;
var _xhtml_parser_aEmptyTags = aEmptyTags;

var aFlushAfter = new Array();
aFlushAfter['td'] = 1;
aFlushAfter['tr'] = 1;
aFlushAfter['table'] = 1;
aFlushAfter['ul'] = 1;
aFlushAfter['select'] = 1;
aFlushAfter['html'] = 1;
aFlushAfter['body'] = 1;
_xhtml_parser_aFlushAfter = aFlushAfter;

var _xhtml_parser_aNoNestedTags = new Array();
_xhtml_parser_aNoNestedTags["li"] = 1;
_xhtml_parser_aNoNestedTags["option"] = 1;

var aDoNotAnalyse = new Array();
aDoNotAnalyse['script'] = 1;
aDoNotAnalyse['style'] = 1;
aDoNotAnalyse['textarea'] = 1;
var _xhtml_parser_aDoNotAnalyse = aDoNotAnalyse;

var aIgnoreTags = new Array();
//aIgnoreTags["dl"] = 1;
aIgnoreTags["dd"] = 1;
aIgnoreTags["dt"] = 1;
_xhtml_parser_aIgnoreTags = aIgnoreTags;

/**
 * Alle HTML entiteiten moeten omgezet worden in XHTML.
 * Dezelfde omleiding wordt hier gebruikt als bij het zetten van
 * alle HTML tags.
 */
XHTML_TEMP_VAR = a;
a = null;
var a = new Array();
a['&nbsp;']   = '&nbsp;'; // Moet &nbsp; blijven!
a['&quot;']   = '&#34;';
a['&amp;']    = '&#38;';
a['&lt;']     = '&#60;';
a['&gt;']     = '&#62;';
a['&iexcl;']  = '&#161;';
a['&cent;']   = '&#162;';
a['&pound;']  = '&#163;';
a['&curren;'] = '&#164;';
a['&yen;']    = '&#165;';
a['&brvbar;'] = '&#166;';
a['&brkbar;'] = '&#166;';
a['&sect;']   = '&#167;';
a['&uml;']    = '&#168;';
a['&die;']    = '&#168;';
a['&copy;']   = '&#169;';
a['&ordf;']   = '&#170;';
a['&laquo;']  = '&#171;';
a['&not;']    = '&#172;';
a['&reg;']    = '&#174;';
a['&macr;']   = '&#175;';
a['&hibar;']  = '&#175;';
a['&deg;']    = '&#176;';
a['&plusmn;'] = '&#177;';
a['&sup2;']   = '&#178;';
a['&sup3;']   = '&#179;';
a['&acute;']  = '&#180;';
a['&micro;']  = '&#181;';
a['&para;']   = '&#182;';
a['&middot;'] = '&#183;';
a['&cedil;']  = '&#184;';
a['&sup1;']   = '&#185;';
a['&ordm;']   = '&#186;';
a['&raquo;']  = '&#187;';
a['&frac14;'] = '&#188;';
a['&frac12;'] = '&#189;';
a['&frac34;'] = '&#190;';
a['&iquest;'] = '&#191;';
a['&Agrave;'] = '&#192;';
a['&Aacute;'] = '&#193;';
a['&Acirc;']  = '&#194;';
a['&Atilde;'] = '&#195;';
a['&Auml;']   = '&#196;';
a['&Aring;']  = '&#197;';
a['&AElig;']  = '&#198;';
a['&Ccedil;'] = '&#199;';
a['&Egrave;'] = '&#200;';
a['&Eacute;'] = '&#201;';
a['&Ecirc;']  = '&#202;';
a['&Euml;']   = '&#203;';
a['&Igrave;'] = '&#204;';
a['&Iacute;'] = '&#205;';
a['&Icirc;']  = '&#206;';
a['&Iuml;']   = '&#207;';
a['&ETH;']    = '&#208;';
a['&Ntilde;'] = '&#209;';
a['&Ograve;'] = '&#210;';
a['&Oacute;'] = '&#211;';
a['&Ocirc;']  = '&#212;';
a['&Otilde;'] = '&#213;';
a['&Ouml;']   = '&#214;';
a['&times;']  = '&#215;';
a['&Oslash;'] = '&#216;';
a['&Ugrave;'] = '&#217;';
a['&Uacute;'] = '&#218;';
a['&Ucirc;']  = '&#219;';
a['&Uuml;']   = '&#220;';
a['&Yacute;'] = '&#221;';
a['&THORN;']  = '&#222;';
a['&szlig;']  = '&#223;';
a['&agrave;'] = '&#224;';
a['&aacute;'] = '&#225;';
a['&acirc;']  = '&#226;';
a['&atilde;'] = '&#227;';
a['&auml;']   = '&#228;';
a['&aring;']  = '&#229;';
a['&aelig;']  = '&#230;';
a['&ccedil;'] = '&#231;';
a['&egrave;'] = '&#232;';
a['&eacute;'] = '&#233;';
a['&ecirc;']  = '&#234;';
a['&euml;']   = '&#235;';
a['&igrave;'] = '&#236;';
a['&iacute;'] = '&#237;';
a['&icirc;']  = '&#238;';
a['&iuml;']   = '&#239;';
a['&eth;']    = '&#240;';
a['&ntilde;'] = '&#241;';
a['&ograve;'] = '&#242;';
a['&oacute;'] = '&#243;';
a['&ocirc;']  = '&#244;';
a['&otilde;'] = '&#245;';
a['&ouml;']   = '&#246;';
a['&divide;'] = '&#247;';
a['&oslash;'] = '&#248;';
a['&ugrave;'] = '&#249;';
a['&uacute;'] = '&#250;';
a['&ucric;']  = '&#251;';
a['&uuml;']   = '&#252;';
a['&yacute;'] = '&#253;';
a['&thorn;']  = '&#254;';
a['&yuml;']   = '&#255;';
var _xhtml_parser_aEntities = a;
a = null;
a = XHTML_TEMP_VAR;

/**
 * Alle modi:
 *
 * - 0: TEXT
 * - 1: OPEN TAG
 * - 2: CLOSE TAG
 * - 3: EMPTY TAG
 * - 4: COMMENT
 * - 5: CDATA
 * - 6: DOCTYPE
 */

function _xhtml_array() {
  /**
   * Haal alle Tags op en zet ze in de locale variabele this.aTags
   */
  this.aTags = _xhtml_parser_aTags;
  this.aEntities = _xhtml_parser_aEntities
  this.aEmptyAttributes = _xhtml_parser_aEmptyAttributes;
  this.aEmptyTags = _xhtml_parser_aEmptyTags;
  this.aDoNotAnalyse = _xhtml_parser_aDoNotAnalyse;
  /**
   * Als er een SCRIPT tag gevonden wordt, dan moet de inhoud ervan
   * niet ge-analyseerd worden. Gewoon domweg doorlopen totdat er
   * een </script> gevonden wordt.
   */
  this.bInScriptTag = false;
  this.bDoNotAnalyse = false;
  this.sDoNotAnalyseTill = "";

  this.aRet = new Array();
  /**
   * Variabele met de HTML
   */
  this.sHTML = "";
  /**
   * Zet de HTML tekenreeks waarvan een Array moet worden gemaakt.
   */
  this.setHTML = function (sHTML) {
    this.sHTML = sHTML;
  }

  this.toArray = function () {
    /**
     * Dit is een zeer belangrijke variabele. Deze variabele houdt
     * bij in welke modus de parser zit. Er zijn verschillende
     * modi: 0=>IN_TEXT, 1=>IN_OPEN_TAG, 2=>IN_CLOSE_TAG, IN_ATTRIBUTE
     */
    var iMode = 0;

    var s = this.sHTML;
    var isl = s.length;

    this.currentEntry;

    /**
     * Zorg dat er altijd een parent tag paar is. Het algoritme
     * is afhankelijk van zo'n parent tagpaar.
     */
    this.setEntry();
    this.currentEntry["type"] = 1;
    this.currentEntry["tagname"] = "XHTML_PARENT_TAG";
    /**
     * Door de value op "" te zetten zorg je ervoor dat de waarde
     * bij het genereren van de output string niet beïnvloed wordt.
     */
    this.currentEntry["value"] = "";

    /**
     * Zet de eerste entry en geef hem als type "text" mee
     */
    this.setEntry();
    this.currentEntry["type"] = 0;
//    this.setEntryValue("type", 0, false);

    /**
     * Deze lus, leest de tekenreeks, teken voor teken in. Bij
     * bepaalde tekens, zoals <, > en :, wordt er gekeken in
     * welke modus de parser zit. Die modus is afhankelijk voor het
     * verdere gedrag van de parser. Bijvoorbeeld constateren dat
     * een nieuwe tag geopend wordt, of dat er een tag afgesloten
     * wordt.
     */
    for (var i = 0; i < isl; i++) {
      var c = s.substr(i, 1);
      switch (c) {
        case "<":
          /**
           * Er is een < geopend. Dat kan betekenen dat er een HTML
           * tag aankomt. Alleen als de parser in text modus is kan
           * de < het begin van een tag betekenen.
           */
          if (iMode == 0) {

            /**
             * posType houdt bij of het mogelijke type een OPEN tag
             * of een CLOSE tag kan zijn.
             */
            var posType = 1;
            /**
             * Hier wordt een tijdelijke variabele aangemaakt. i+1
             * houdt in dat je niet het < teken erbij wil hebben. Er
             * wordt expres voor lengte 12 gekozen, omdat een HTML
             * tagname nooit langer is dan 12 karakters.
             */
            var sTemp = s.substr(i + 1, 12);

            /**
             * Als het teken na de < een slash is dan kan het een
             * sluit tag zijn.
             */
            if (sTemp.charCodeAt() == 47) {
              sTemp = sTemp.substr(1);
              posType = 2;
            }
            var iTempLength = sTemp.length;
            /**
             * Analyseer elk teken van de tijdelijke variabele. Als
             * er geen cijfer of nummer gevonden wordt, dan moet er
             * gestopt worden.
             */
            for (var j = 0; j < iTempLength; j++) {
              code = sTemp.charCodeAt(j);
              if (!((code > 96 && code < 123) || (code > 64 && code < 91) || (code > 47 && code < 58) || (code == 33) || (code == 45))) {
                break;
              }
            }
            var posTag = sTemp.substr(0, j);
            posTag = posTag.toLowerCase();

            if (this.bDoNotAnalyse == true && posTag != this.sDoNotAnalyseTill) {
              this.currentEntry["value"] += "<";
              break;
            }

            /**
             * Controleer op commentaar blokken
             */
            if (s.substr(i + 1, 3) == "!--") {
              iStart = i;
              i += 3;
              bFound = false;
              code = s.charCodeAt(i);
              while (bFound == false) {
                i++;
                code = s.charCodeAt(i);
                /**
                 * als het teken een - is en het volgende teken ook een - en het teken daarna een > dan is het het einde van
                 * een commentaar blok
                 */
                if (code == 45 && s.charCodeAt(i+1) == 45 && s.charCodeAt(i+2) == 62) {
                  bFound = true;
                  i += 3;
                }
              }
              if (this.currentEntry && !(this.currentEntry['type'] == 0 && this.currentEntry['value'] == '')) {
                this.setEntry();
              }
              this.currentEntry["type"] = 4;
              this.currentEntry["tagname"] = "";
              this.currentEntry["value"]   = s.substr(iStart, i - iStart);
              this.setEntry();
              this.currentEntry["type"]  = 0;
              this.currentEntry["value"] = "";
              i--;
              break;
            }

            if (posTag == "!doctype") {
              i += posTag.length + 1;
              iStart = i;
              code = s.charCodeAt(i);
              while (code != 62) {
                i++;
                code = s.charCodeAt(i);
              }
              if (this.currentEntry && !(this.currentEntry['type'] == 0 && this.currentEntry['value'] == '')) {
                this.setEntry();
              }
              this.currentEntry["type"] = 6;
              this.currentEntry["tagname"] = "!DOCTYPE";
              this.currentEntry["value"]   = s.substr(iStart, i - iStart);
              if (this.currentEntry["value"].lastIndexOf("/") == this.currentEntry["value"].length-1)this.currentEntry["value"] = this.currentEntry["value"].substr(0,this.currentEntry["value"].length-1);
              this.setEntry();
              this.currentEntry["type"] = 0;
              this.currentEntry["value"] = "";
              iMode = 0;
              break;
            }

            if (this.bDoNotAnalyse == true && this.sDoNotAnalyseTill == posTag) {
              this.bDoNotAnalyse = false;
            }

            /**
             * Als het inderdaad de opening van een tag is, voeg dan
             * een nieuwe entry toe, zet het type, tagnaam en de
             * eerste "<".
             */
            if (this.aTags[posTag] == 1) {
              /**
               * Als de vorige entry nog leeg is en van het type text, dan kan die entry
               * gebruikt worden.
               */
              if (this.currentEntry && !(this.currentEntry['type'] == 0 && this.currentEntry['value'] == '')) {
                this.setEntry();
              }

              this.currentEntry["tagname"] = posTag;
              if (this.aEmptyTags[posTag] == 1) {
                this.currentEntry["type"] = 3;
              } else {
                this.currentEntry["type"] = posType;
              }
              if (posType == 1) {
                this.currentEntry["value"] += "<" + posTag;
                i += posTag.length;
                iMode = 1;
              }
              if (posType == 2) {
                this.currentEntry["value"] += "</" + posTag;
                i += posTag.length + 1;
                iMode = 2;
              }

            } else {
              /**
               * De modus is IN_TEXT en er is geen tag. Vervang de <
               * daarom voor zijn HTML entiteit.
               */
              this.currentEntry["value"] += "<"//"&#60;";
            }
            break;
          }
          break;
        case ">":
          if (this.aDoNotAnalyse[posTag] == 1 && posType == 1) {
            this.sDoNotAnalyseTill = posTag;
            this.bDoNotAnalyse = true;
            this.currentEntry["value"] += ">";
            this.setEntry();
            this.currentEntry["type"] = 5;
            iMode = 0;
            break;
          }
          /**
           * Als de modus IN_OPEN_TAG is, dan wordt nu de tag afgesloten.
           * Voeg daarom nog het > toe aan de entry en open een nieuwe
           * entry en zet het type van die entry.
           */
          if (iMode != 0) {
            if (this.currentEntry["type"] == 3) {
              this.currentEntry["value"] += "/>";
            } else {
              this.currentEntry["value"] += ">";
            }
            iMode = 0;
            this.setEntry();
            this.currentEntry["type"] = 0;
            break;
          }

          if (this.bDoNotAnalyse == true) {
            this.currentEntry["value"] += ">";
            break;
          }
          /**
           * Als de modus IN_TEXT modus is, voeg dan gewoon het teken toe
           * Het is geen afsluiting van een tag, maar gewoon het teken.
           */
          if (iMode == 0) {
            this.currentEntry["value"] += ">"//"&#62;";
          }
          break;
        default:
          /**
           * Als de modus IN_TEXT is, voeg dat het teken toe aan de
           * laatste entry waarde
           */
          if (iMode == 0) {
            this.currentEntry["value"] += c;
            break;
          }

          if (iMode == 1) {
            /**
             * Het volgende teken is een whitespace, zo ja, loop dan net
             * zo lang totdat alle whitespaces weg zijn.
             */
            code = s.charCodeAt(i);
            if (code == 32 || code == 10 || code == 13 || code == 9) {
              while (code == 32 || code == 10 || code == 13 || code == 9) {
                if (i > isl) {break;}
                i++;
                code = s.charCodeAt(i);
              }
            }
            /**
             * Nadat alle whitespaces verwijderd zijn, moet er gekeken worden
             * of er een attribuut is.
             */
            if ((code > 96 && code < 123) || (code > 64 && code < 91) || (code > 47 && code < 58) || code == 45) {
              /**
               * Zoek een mogelijk attribuut, een attribuut mag alleen bestaan
               * uit letters en cijfers.
               */
              var posAttrBegin = i;
              while ((code > 96 && code < 123) || (code > 64 && code < 91) || (code > 47 && code < 58) || code == 45) {
                if (i > isl) {break;}
                i++;
                code = s.charCodeAt(i);
              }
              var posAttr = s.substr(posAttrBegin, i - posAttrBegin);
              /**
               * Na de mogelijke attribuut naam, kunnen nog spaties voorkomen.
               * spaties voor het = teken, doorloop dus ook eerst die spaties.
               *
               * vb: <b onClick     ="">
               */
              if (code == 32 || code == 10 || code == 13 || code == 9) {
                while (code == 32 || code == 10 || code == 13 || code == 9) {
                  if (i > isl) {break;}
                  i++;
                  code = s.charCodeAt(i);
                }
              }
              /**
               * Is het gevonden teken een is-teken? Zo ja, dan is er een
               * attribuut gevonden. Dan moet er op zoek worden gegaan
               * naam de waarde van het attribuut.
               * 61 => "="
               */
              if (code == 61) {
                /**
                 * Nu eenmaal zeker is dat er een attribuut is, moet er dus
                 * op zoek worden gegaan naar de waarde van het attribuut. Na het
                 * is-teken kunnen opnieuw spaties voorkomen. Doorloop dus eerst
                 * die spaties.
                 */
                i++;
                code = s.charCodeAt(i);
                if (code == 32 || code == 10 || code == 13 || code == 9) {
                  while (code == 32 || code == 10 || code == 13 || code == 9) {
                    if (i > isl) {break;}
                    i++;
                    code = s.charCodeAt(i);
                  }
                }
                c = s.substr(i, 1);
                /**
                 * Het volgende teken dat gevonden is, is geen teken voor het
                 * openen van een attribuut.
                 *
                 * vb: <b onClick=alert('foo');>
                 *
                 * Er moet nu doorgezocht worden totdat er een whitespace gevonden is
                 * elk teken mag, behalve whitespace en een sluit teken mag niet >
                 */
                if (code != 39 && code != 34) {
                  var attrValueBegin = i
                  while (!(code == 32 || code == 10 || code == 13 || code == 9) && code != 62) {
                    if (i > isl) {break;}
                    i++;
                    code = s.charCodeAt(i);
                  }
                  var attrValue = s.substr(attrValueBegin, i - attrValueBegin);
                  if (attrValue.match("/\"/g")) {
                    attrValue = "'" + attrValue + "'";
                  } else {
                    attrValue = "\"" + attrValue + "\"";
                  }
                  /**
                   * Voeg het attribuut en zijn waarde toe
                   */
                  this.currentEntry["value"] += " " + posAttr.toLowerCase() + "=" + attrValue;
                  //this.addAttribute(posAttr, attrValue);
                } else {
                  /**
                   * Het volgende teken is wel een " of een '. Nu moet er net zolang
                   * worden doorgezocht totdat er nog zo'n teken gevonden wordt; dat
                   * is het einde van het attribuut.
                   */
                  var end = code;
                  i++;
                  code = s.charCodeAt(i);
                  var attrValueBegin = i;
                  while (code != end) {
                    if (i > isl) {break;}
                    i++;
                    code = s.charCodeAt(i);
                  }
                  /**
                   * Deze regel gebruiken als je om de waarde van het attribuut alvast de "
                   * of ' wil hebben
                   */
                  var attrValue = s.substr(attrValueBegin - 1, i - attrValueBegin + 2);
                  //var attrValue = s.substr(attrValueBegin, i - attrValueBegin);

                  /**
                   * Voeg het attribuut en zijn waarde toe
                   */
                  this.currentEntry["value"] += " " + posAttr.toLowerCase() + "=" + attrValue;
                  //this.addAttribute(posAttr, attrValue);
                }

              } else {
                /**
                 * Dat er geen is-teken gevonden is, kan twee dingen betekenen:
                 * het is geen attribuut, of het is een leeg attribuut.
                 *
                 * vb: <hr noshade>
                 *
                 * Er moet dus gecontroleerd worden, of "posAttr" voorkomt in
                 * de array met attributen die leeg kunnen zijn. Zo ja, dan is het
                 * wel een attribuut. Zo nee, dan is het geen attribuut.
                 */
                if (this.aEmptyAttributes[posAttr.toLowerCase()] == 1) {
                  this.currentEntry["value"] += " " + posAttr.toLowerCase() + "=\"" + posAttr + "\"";
                  //this.addAttribute(posAttr, posAttr);
                }
              }

              i--;
            } else {
              /**
               * Dit kan soms voorkomen: voorbeeld: <hr   >
               */
              if (code == 62) {
                if (this.currentEntry["type"] == 3) {
                  this.currentEntry["value"] += " />";
                } else {
                  this.currentEntry["value"] += ">";
                }
                this.setEntry();
                this.currentEntry["type"] = 0;
                iMode = 0;
              }
            }
            break;
          }
      }
    }
    if (this.aRet[this.aRet.length - 1]["value"] == "") {
      this.aRet.length--;
    }

    /**
     * Zorg dat er altijd een parent tag paar is. Het algoritme
     * is afhankelijk van zo'n parent tagpaar. Deze code voegt
     * de sluittag toe.
     */
    this.setEntry();
    this.currentEntry["type"] = 2;
    this.currentEntry["tagname"] = "XHTML_PARENT_TAG";
    this.currentEntry["value"] = "";

    return this.aRet;
  }

  /**
   * Maak een nieuwe entry aan in de return Array.
   */
  this.setEntry = function () {
    var i = this.aRet.length;
    this.aRet[i]               = new Array();
    this.aRet[i]["tagname"]    = "";
    //this.aRet[i]["attributes"] = new Array();
    this.aRet[i]["type"]       = "";
    this.aRet[i]["value"]      = "";
    this.currentEntry = this.aRet[i];
  }

  this.addAttribute = function (sAttribute, sValue) {
/**

Tijdens het optimaliseren is gekozen om geen array van attributen bij
te houden. Het is mogelijk. Dan moet dit commentaar verwijderd
worden.

    var ai = this.currentEntry['attributes'].length;
    this.currentEntry['attributes'][ai] = new Array();
    this.currentEntry['attributes'][ai]['name']  = sAttribute.toLowerCase();;
    this.currentEntry['attributes'][ai]['value'] = sValue;
*/
  }
}

function _xhtml_nesting() {
  this.aData;
  this.setArray = function (a) {
    this.aData = a;
  }
  /**
   * Deze functie corrigeert de nesting van een gegeven array. Het algoritme
   * voor het corrigeren gaat er vanuit dat er een alles omvattend paar tags
   * is. In de meeste gevallen is dat de <HTML> tag.
   */
  this.correct = function () {
    var aReturn = new Array();
    var a = this.aData;
    var al = this.aData.length;

    var aNoNestedTags = _xhtml_parser_aNoNestedTags;
    var aFlushAfter = _xhtml_parser_aFlushAfter;
    var aIgnoreTags = _xhtml_parser_aIgnoreTags;
    /**
     * Een array met alle tags die zijn geopend
     */
    var aStack = new Array();
    //aStack[aStack.length] = a[0].clone();
    /**
     * Een array met alle tags die zijn gesloten voordat de juiste tag
     * gevonden werd.
     */
    var aFixStack = new Array();

    /**
     * Een array met alle tags die zijn geopend, verschil met de stack array
     * is dat in deze array de index van de array de tagname is. Zo kan snel
     * gekeken worden of een tag geopend (1) is of niet (0)
     */
    var aOpenTags = new Array();
    /**
     * Voeg de eerste tag toe aan de stack. En voeg een sluit paar toe aan het
     * einde van de invoer Array. Dit zorgt ervoor dat de array een parent
     * tag paar heeft.
     */
    //aStack[aStack.length] = new Array();
    //aStack[aStack.length - 1]["tagname"] = "parent_node";
    //aStack[aStack.length - 1]["type"]    = 1;
    //a[a.length] = aStack[aStack.length - 1].clone();
    //a[a.length - 1]["type"] = 2;
    /**
     * Doorloop alle items in de Array
     */
    for (var i = 0; i < al; i++) {
      var iType       = a[i]["type"];
      var sTagName    = a[i]["tagname"];
      switch (iType) {
        case 0: // TEXT NODE
          /**
           * Wanneer het een text node betreft kan de data gewoon direct aan de return
           * Array toegevoegd worden. De nesting hoeft niet geanalyseerd te worden.
           */
          aReturn[aReturn.length] = a[i].clone();
          break;
        case 1: // OPEN TAG NODE
          /**
           * Als de tag voor het eerst voorkomt, dan bestaat de entry aOpenTags[sTagName]
           * nog niet. Die moet dan aangemaakt worden en op nul gezet worden.
           */
          if (!aOpenTags[sTagName]) {
            aOpenTags[sTagName] = 0;
          }
          if (aIgnoreTags[sTagName]) {
            aReturn[aReturn.length] = a[i].clone();
            break;
          }

          if (aNoNestedTags[sTagName] == 1 && aOpenTags[sTagName] != 0) {
            /**
             * Bouw de stack af totdat de tag gevonden is
             */
            for (var j = aStack.length - 1; j > -1; j--) {
              if (aReturn[aReturn.length - 1]["algorithm"] == 1 && aReturn[aReturn.length - 1]["tagname"] == aStack[j]["tagname"]) {
                aReturn.length--;
                aStack.length--;
                //aReturn[aReturn.length] = a[i].clone();
                //alert('foo');
                break;
              }
              aOpenTags[aStack[aStack.length - 1]["tagname"]]--;
              aReturn[aReturn.length] = aStack[j].clone();
              aReturn[aReturn.length - 1]["type"] = 2;
              if (aStack[aStack.length - 1]["tagname"] == sTagName) {
                aStack.length--;
                break;
              }
              aFixStack[aFixStack.length] = aStack[j].clone();
              aStack.length--;
            }
            if (aStack.length == 0) {
              break;
            }
            /**
             * Heropen UL en OL tags voordat de LI tag geopend wordt...
             */
            for (var j = aFixStack.length - 1; j > -1; j--) {
              var tag = aFixStack[j]["tagname"];
              if (tag == "ul" || tag == "ol") {
                aOpenTags[tag]++;
                aReturn[aReturn.length] = aFixStack[j].clone();
                aStack[aStack.length] = aFixStack[j].clone();
              }
            }
            aOpenTags[sTagName]++;
            aReturn[aReturn.length] = a[i].clone();
            aStack[aStack.length] = a[i].clone();
            for (var j = aFixStack.length - 1; j > -1; j--) {
              /**
               * Negeer de UL en OL tags
               */
              var tag = aFixStack[j]["tagname"];
              if (tag == "ul" || tag == "ol") {
                continue;
              }
              for (var k = i + 1; k < al; k++) {
                if (!a[k]["value"].match("/^(\w)+$/gi")) {
                  /**
                   * Bug solve
                   */
                  if (a[k]["tagname"] == "") {
                    i=k-1;
                  } else {
                    i=k;
                  }
                  break;
                }
              }
              if (a[k]["tagname"] == aFixStack[j]["tagname"]) {;
                continue;
              }
              aOpenTags[aFixStack[j]["tagname"]]++;
              aReturn[aReturn.length] = aFixStack[j].clone();
              aReturn[aReturn.length - 1]["algorithm"] = 1;
              /**
               * Geef aan dat dit Item is ingevoegd door het algoritme. Wanneer de volgende
               * open tag merkt dat de laatste tag dezelfde naam heeft en de vorige tag is ingevoegd
               * door het algoritme. Dan moet de laatste uit de array gegooid worden en moet die
               * tag ook genegeerd worden.
               */
              aStack[aStack.length] = aFixStack[j].clone();
            }
            aFixStack.length = 0;
            break;
          }

          aOpenTags[sTagName]++;
          aReturn[aReturn.length] = a[i].clone();
          aStack[aStack.length] = a[i].clone();
          break;
        case 2: // CLOSE TAG NODE
          /**
           * De tag die gesloten wordt, is niet geopend. Daarom moet de tag genegeerd
           * worden; hij doet niet mee.
           */
          if (!(aOpenTags[sTagName] > 0)) {
            aOpenTags[sTagName] = 0;
            break;
          }

          for (var j = aStack.length - 1; j > -1; j--) {
            if (aReturn[aReturn.length - 1]["algorithm"] == 1 && aReturn[aReturn.length - 1]["tagname"] == aStack[j]["tagname"]) {
              aReturn.length--;
              aStack.length--;
              //aReturn[aReturn.length] = a[i].clone();
              //alert('foo');
              break;
            }
            aOpenTags[aStack[aStack.length - 1]["tagname"]]--;
            aReturn[aReturn.length] = aStack[j].clone();
            aReturn[aReturn.length - 1]["type"] = 2;
            if (aStack[aStack.length - 1]["tagname"] == sTagName) {
              aStack.length--;
              break;
            }
            aFixStack[aFixStack.length] = aStack[j].clone();
            aStack.length--;
          }
          if (aStack.length == 0) {
            break;
          }
          if (aFlushAfter[sTagName] != 1) {
            for (var j = aFixStack.length - 1; j > -1; j--) {
              if (aNoNestedTags[aFixStack[j]["tagname"]] == 1) {
                continue;
              }
              for (var k = i + 1; k < al; k++) {
                if (!a[k]["value"].match("/^(\w)+$/gi")) {
                  /**
                   * Bug solve
                   */
                  if (a[k]["tagname"] == "") {
                    i=k-1;
                  } else {
                    i=k;
                  }
                  break;
                }
              }
             if (!a[k])break;
              if (a[k]["tagname"] == aFixStack[j]["tagname"]) {;
                continue;
              }
              aOpenTags[aFixStack[j]["tagname"]]++;
              aReturn[aReturn.length] = aFixStack[j].clone();
              aReturn[aReturn.length - 1]["algorithm"] = 1;
              /**
               * Geef aan dat dit Item is ingevoegd door het algoritme. Wanneer de volgende
               * open tag merkt dat de laatste tag dezelfde naam heeft en de vorige tag is ingevoegd
               * door het algoritme. Dan moet de laatste uit de array gegooid worden en moet die
               * tag ook genegeerd worden.
               */
              aStack[aStack.length] = aFixStack[j].clone();
            }
          }
          aFixStack.length = 0;
          /**
           * Verminder het aantal tags dat geopend is van tag sTagName met 1. Hij is namelijk
           * afgesloten. Het aantal open tags is nu nog oud - 1.
           */

          //aReturn[aReturn.length] = a[i].clone();
          break;
        case 3: // EMPTY TAG NODE
          /**
           * Wanneer het een empty tag betreft kan de data gewoon direct aan de return
           * Array toegevoegd worden. De nesting hoeft niet geanalyseerd te worden.
           */
          aReturn[aReturn.length] = a[i].clone();
          break;
        case 4: // COMMENT NODE
          aReturn[aReturn.length] = a[i].clone();
          break;
        case 5: // CDATA NODE
          aReturn[aReturn.length] = a[i].clone();
          break;
        case 6: // DOCTYPE NODE
          aReturn[aReturn.length] = a[i].clone();
          break;
      }
      if (aStack.length == 0) {
        break;
      }
    }
    /*alert(aOpenTags["table"]);
    alert(aOpenTags["td"]);
    alert(aOpenTags["tr"]);
    */
    return (aReturn);
  }
}

function _xhtml_string_builder() {
  this.a = new Array();
  this.setArray = function (a) {
    this.a = a
  }

  this.build = function () {
    var v = "";
    for (var i = 0; i < this.a.length - 1; i++) {
/**

Testje:

      v += this.a[i]["tagname"] + "\n";
      v += this.a[i]["type"] + "\n";
      v += this.a[i]["value"] + "\n---------------------------------------\n\n";
*/
      switch (this.a[i]["type"]) {
        case 0:
          v += this.a[i]["value"];
          break
        case 1:
          v += this.a[i]["value"];
          break;
        case 2:
          v += "</" + this.a[i]["tagname"] + ">";
          break;
        case 3:
          v += this.a[i]["value"];
          break;
        case 4:
          v += this.a[i]["value"];
          break;
        case 5:
          v += this.a[i]["value"];
          break;
        case 6:
          v += "<" + this.a[i]["tagname"] + this.a[i]["value"] + " />";
          break;
      }
    }
    v = this.removeEmptyTags (v)

    return (v);
  }

  this.removeEmptyTags = function (v) {
    //v = v.replace(/(<font[^>]*>)([\s]*?)(<\/font[^>]*>)/gi, "");
    v = v.replace(/(<ul[^>]*>)([\s]*?)(<\/ul[^>]*>)/gi, "");
    v = v.replace(/(<ol[^>]*>)([\s]*?)(<\/ol[^>]*>)/gi, "");
    v = v.replace(/(<p[^>]*>)([\s]*?)(<\/p[^>]*>)/gi, "");
    //v = v.replace(/(<i[^>]*>)([\s]*?)(<\/i[^>]*>)/gi, "");
    //v = v.replace(/(<u[^>]*>)([\s]*?)(<\/u[^>]*>)/gi, "");
    return (v);
  }
}

function cls_html() {
  this.sHTML = "";
  this.sRet = "";

  this.setHTML = function (s) {
    this.sHTML = s;
  }

  this.toXHTML = function () {
    var xhtml_array = new _xhtml_array();
    xhtml_array.setHTML(this.sHTML);
    var xhtml_nesting = new _xhtml_nesting();
    xhtml_nesting.setArray(xhtml_array.toArray());
    this.aNesting = xhtml_nesting.correct();

    var xhtml_string_builder = new _xhtml_string_builder();
    xhtml_string_builder.setArray(this.aNesting);
    this.sRet = xhtml_string_builder.build();
    return this.sRet;
  }
}

function clearContentBlocks(isFirst){

	var content = E._frame.body.innerHTML;

	content = removeBlock(content);
	content = content.replace(/(<!--[#\s]*?StartBlock(?:No|Can)Delete[^>]+>(<\/[^>]+>)*?\s*(<div\s+id="?de_add[^>]+>\s*?<img[^>]+>\s*?(?:<img[^>]+>)))/gi, function(s1,s2,s3){return s3;});
	content = content.replace(/<div><\/div><!--[#\s]*?EndBlock(?:No|Can)Delete[^>]+>/gi, "");
	content = addBlock(content);

	E._frame.body.innerHTML = "<div id='ie_hack_comments'>&nbsp;&nbsp;&nbsp;</div>"+content;
	var hack_div = E._frame.body.firstChild;
	if(hack_div.id == "ie_hack_comments") E._frame.body.removeChild(hack_div);

	var div = E._frame.getElementById('anchor_div');

	if(div){
		var div_prop = getElemProp(div);
		var r = E._frame.selection.createRange();

	    r.moveToPoint(div_prop.left, div_prop.top);
	    r.expand("word");
		r.collapse();
	    r.select();
		div.parentNode.removeChild(div);
	}
}

function getElemProp(element){
	if (element){
		var left = element.offsetLeft;
		var top = element.offsetTop;
		for (var parent = element.offsetParent; parent; parent = parent.offsetParent){
			left += parent.offsetLeft;
			top += parent.offsetTop;
		}
	}
	return {left: left, top: top};
}