// htmlArea v3.0 - Copyright (c) 2002-2004 interactivetools.com, inc.
// This copyright notice MUST stay intact for use (see license.txt).
//
// Portions (c) dynarch.com, 2003-2004
//
// A free WYSIWYG editor replacement for <textarea> fields.
// For full source code and docs, visit http://www.interactivetools.com/
//
// Version 3.0 developed by Mihai Bazon.
//   http://dynarch.com/mishoo
//
// $Id: htmlarea.js,v 1.152.4.3 2011/06/22 11:05:34 schoudhari Exp $
var agt = navigator.userAgent.toLowerCase();
var is_major = parseInt(navigator.appVersion);
var is_minor = parseFloat(navigator.appVersion);
var is_nav = ((agt.indexOf('mozilla') != -1) && (agt.indexOf('spoofer') == -1)
		&& (agt.indexOf('compatible') == -1) && (agt.indexOf('opera') == -1)
		&& (agt.indexOf('webtv') == -1) && (agt.indexOf('hotjava') == -1));
var is_nav6up = (is_nav && (is_major >= 5));
var is_gecko = (agt.indexOf('gecko') != -1);
var is_ie = ((agt.indexOf("msie") != -1) && (agt.indexOf("opera") == -1));
var is_ie3 = (is_ie && (is_major < 4));
var is_ie4 = (is_ie && (is_major == 4) && (agt.indexOf("msie 4") != -1));
var is_ie4up = (is_ie && (is_major >= 4));
var is_ie5 = (is_ie && (is_major == 4) && (agt.indexOf("msie 5.0") != -1));
var is_ie5_5 = (is_ie && (is_major == 4) && (agt.indexOf("msie 5.5") != -1));
var is_ie5_2 = (is_ie && (is_major == 4) && (agt.indexOf("msie 5.2") != -1));
var is_ie5up = (is_ie && !is_ie3 && !is_ie4);
var is_ie5_5up = (is_ie && !is_ie3 && !is_ie4 && !is_ie5);
var is_ie6 = (is_ie && (is_major == 4) && (agt.indexOf("msie 6.") != -1));
var is_ie6up = (is_ie && !is_ie3 && !is_ie4 && !is_ie5 && !is_ie5_5 && !is_ie5_2);
var is_ie7 = (is_ie && (agt.indexOf("msie 7.") != -1));
var is_safari = (agt.indexOf("safari") != -1);
var is_chrome = (agt.indexOf("chrome") != -1);

if (is_chrome)
	is_safari = false;
var is_firefox = (agt.indexOf("firefox") != -1);
var skin = "gray";
var collabapplication = "wiki";
var E_MODE_TEXT = false;
var checkSupportedBrowser_val = null;
var setEventFlag = "false";
var linkHeight = 350;
if(is_ie)
{
	linkHeight = 800;
}

var BrowserDetect = {
	init : function() {
		this.browser = this.searchString(this.dataBrowser)
				|| "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
				|| this.searchVersion(navigator.appVersion)
				|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString : function(data) {
		for ( var i = 0; i < data.length; i++) {
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch
					|| data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			} else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion : function(dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1)
			return;
		return parseFloat(dataString.substring(index
				+ this.versionSearchString.length + 1));
	},
	dataBrowser : [ {
		string :navigator.userAgent,
		subString :"OmniWeb",
		versionSearch :"OmniWeb/",
		identity :"OmniWeb"
	}, {
		string :navigator.vendor,
		subString :"Apple",
		identity :"Safari"
	}, {
		prop :window.opera,
		identity :"Opera"
	}, {
		string :navigator.vendor,
		subString :"iCab",
		identity :"iCab"
	}, {
		string :navigator.vendor,
		subString :"KDE",
		identity :"Konqueror"
	}, {
		string :navigator.userAgent,
		subString :"Firefox",
		identity :"Firefox"
	}, {
		string :navigator.vendor,
		subString :"Camino",
		identity :"Camino"
	}, {
		string :navigator.userAgent,
		subString :"Netscape",
		identity :"Netscape"
	}, {
		string :navigator.userAgent,
		subString :"MSIE",
		identity :"Explorer",
		versionSearch :"MSIE"
	}, {
		string :navigator.userAgent,
		subString :"Gecko",
		identity :"Mozilla",
		versionSearch :"rv"
	}, {
		string :navigator.userAgent,
		subString :"Mozilla",
		identity :"Netscape",
		versionSearch :"Mozilla"
	} ],
	dataOS : [ {
		string :navigator.platform,
		subString :"Win",
		identity :"Windows"
	}, {
		string :navigator.platform,
		subString :"Mac",
		identity :"Mac"
	}, {
		string :navigator.platform,
		subString :"Linux",
		identity :"Linux"
	} ]

};
BrowserDetect.init();

var is_safari_2 = ( function is_safari2() {
	if (BrowserDetect.browser == "safari" || BrowserDetect.browser == "Safari") {
		if (parseInt(BrowserDetect.version) < 510
				&& (agt.indexOf("Mobile") == -1)) {
			return true;
		} else {
			return false;
		}
	} else {
		return false;
	}
})();

if (typeof _editor_url == "string") {
	// Leave exactly one backslash at the end of _editor_url
	_editor_url = _editor_url.replace(/\x2f*$/, '/');
} else {
	alert("WARNING: _editor_url is not set!  You should set this variable to the editor files path; it should preferably be an absolute path, like in '/htmlarea', but it can be relative if you prefer.  Further we will try to load the editor files correctly but we'll probably fail.");
	_editor_url = '';
}

// make sure we have a language
if (typeof _editor_lang == "string") {
	_editor_lang = _editor_lang.toLowerCase();
} else {
	_editor_lang = "en";
}

// skin stylesheet to load
if (!(typeof _editor_skin == "string")) {
	_editor_skin = skin;
}

var fullScreenWin = null;
var winPopupWindow = null;
var application = null;
var winPopups = null;
// Creates a new HTMLArea object.  Tries to replace the textarea with the given
// ID with it.
function HTMLArea(textarea, config, application) {
	//if (HTMLArea.checkSupportedBrowser()) {
	if (typeof config == "undefined") {
		this.config = new HTMLArea.Config();
	} else {
		this.config = config;
	}

	this.application = application;
	this._htmlArea = null;
	this._textArea = textarea;

	if (HTMLArea.checkSupportedBrowser()) {
		this._editMode = "wysiwyg";
	} else {
		this._editMode = "textmode";
	}

	this._editMode = "wysiwyg";
	this.plugins = {};
	this._timerToolbar = null;
	this._timerUndo = null;
	this._undoQueue = new Array(this.config.undoSteps);
	this._undoPos = -1;
	this._customUndo = true;
	this._mdoc = document; // cache the document, we need it in plugins
	this.doctype = '';
	this.editorCSS = null;
	this.userCSS = null;
	this.stripBase = true;
	this.toolBarChange = false;
	this.globalStateChange = false; //for full editor disable
	//for adv/std toggling
	this.toggleMode = 1; //Adv default 1-Adv 0 Std

	//}
};

// load some scripts
( function() {

	var scripts = HTMLArea._scripts = [ _editor_url + "htmlarea.js",
			_editor_url + "dialog.js", _editor_url + "popupwin.js",
			/*_editor_url + "lang/" + _editor_lang + ".js"*/
			_editor_lang_path ];
	var head = document.getElementsByTagName("head")[0];
	// start from 1, htmlarea.js is already loaded
	for ( var i = 1; i < scripts.length; ++i) {
		var script = document.createElement("script");
		script.src = scripts[i];
		head.appendChild(script);
	}
})();

// cache some regexps
HTMLArea.RE_tagName = /(<\/|<)\s*([^ \t\n>]+)/ig;
HTMLArea.RE_doctype = /(<!doctype((.|\n)*?)>)\n?/i;
HTMLArea.RE_head = /<head>((.|\n)*?)<\/head>/i;
HTMLArea.RE_body = /<body>((.|\n)*?)<\/body>/i;

HTMLArea.Config = function() {
	this.version = "3.0";

	this.width = "auto";
	this.height = "auto";

	// enable creation of a status bar?
	this.statusBar = false;

	// maximum size of the undo queue
	this.undoSteps = 50;

	// the time interval at which undo samples are taken
	this.undoTimeout = 500; // 1/2 sec.

	// the next parameter specifies whether the toolbar should be included
	// in the size or not.
	this.sizeIncludesToolbar = true;

	// if true then HTMLArea will retrieve the full HTML, starting with the
	// <HTML> tag.
	this.fullPage = false;

	// style included in the iframe document
	this.pageStyle = "";

	// set to true if you want Word code to be cleaned upon Paste
	this.killWordOnPaste = false;

	// BaseURL included in the iframe document
	this.baseURL = document.baseURI || document.URL;
	if (this.baseURL && this.baseURL.match(/(.*)\/([^\/]+)/))
		this.baseURL = RegExp.$1 + "/";

	// URL-s
	this.imgURL = "images/";
	this.popupURL = "popups/";

	/** CUSTOMIZING THE TOOLBAR
	 * -------------------------
	 *
	 * It is recommended that you customize the toolbar contents in an
	 * external file (i.e. the one calling HTMLArea) and leave this one
	 * unchanged.  That's because when we (InteractiveTools.com) release a
	 * new official version, it's less likely that you will have problems
	 * upgrading HTMLArea.
	 */
	this.toolbar = [
			[ "fontname", "space", "fontsize", "space", "formatblock", "space",
					"bold", "italic", "underline", "strikethrough",
					"separator", "subscript", "superscript", "separator",
					"copy", "cut", "paste", "space", "undo", "redo" ],

			[ "justifyleft", "justifycenter", "justifyright", "justifyfull",
					"separator", "lefttoright", "righttoleft", "separator",
					"insertorderedlist", "insertunorderedlist", "outdent",
					"indent", "separator", "forecolor", "hilitecolor",
					"separator", "inserthorizontalrule", "createlink",
					"insertimage", "inserttable", "htmlmode", "separator",
					"popupeditor", "separator", "showhelp", "about" ] ];

	this.fontname = {
		"--font--" :'',
		"Arial" :'arial,helvetica,sans-serif',
		"Courier New" :'courier new,courier,monospace',
		"Georgia" :'georgia,times new roman,times,serif',
		"Tahoma" :'tahoma,arial,helvetica,sans-serif',
		"Times New Roman" :'times new roman,times,serif',
		"Verdana" :'verdana,arial,helvetica,sans-serif',
		"Trebuchet MS" :'Trebuchet MS,verdana,arial,helvetica,sans-serif'
	};

	this.fontsize = {
		"--size--" :"",
		"8" :"1",
		"10" :"2",
		"12" :"3",
		"14" :"4",
		"18" :"5",
		"24" :"6",
		"36" :"7"
	};

	this.formatblock = {
		"--format--" :"",
		"Normal" :"p",
		"Heading 1" :"h1",
		"Heading 2" :"h2",
		"Heading 3" :"h3",
		"Heading 4" :"h4",
		"Heading 5" :"h5",
		"Heading 6" :"h6",
		"Address" :"address",
		"Formatted" :"pre"
	};

	this.customSelects = {};
	function cut_copy_paste(e, cmd, obj) {
		e.execCommand(cmd);
	}
	;

	// ADDING CUSTOM BUTTONS: please read below!
	// format of the btnList elements is "ID: [ ToolTip, Icon, Enabled in text mode?, ACTION ]"
	//    - ID: unique ID for the button.  If the button calls document.execCommand
	//	    it's wise to give it the same name as the called command.
	//    - ACTION: function that gets called when the button is clicked.
	//              it has the following prototype:
	//                 function(editor, buttonName)
	//              - editor is the HTMLArea object that triggered the call
	//              - buttonName is the ID of the clicked button
	//              These 2 parameters makes it possible for you to use the same
	//              handler for more HTMLArea objects or for more different buttons.
	//    - ToolTip: default tooltip, for cases when it is not defined in the -lang- file (HTMLArea.I18N)
	//    - Icon: path to an icon image file for the button (TODO: use one image for all buttons!)
	//    - Enabled in text mode: if false the button gets disabled for text-only mode; otherwise enabled all the time.
	this.btnList = {
		bold : [ "Bold", "ed_format_bold.gif", false, function(e) {
			e.execCommand("bold");
		} ],
		italic : [ "Italic", "ed_format_italic.gif", false, function(e) {
			e.execCommand("italic");
		} ],
		underline : [ "Underline", "ed_format_underline.gif", false,
				function(e) {
					e.execCommand("underline");
				} ],
		strikethrough : [ "Strikethrough", "ed_format_strike.gif", false,
				function(e) {
					e.execCommand("strikethrough");
				} ],
		subscript : [ "Subscript", "ed_format_sub.gif", false, function(e) {
			e.execCommand("subscript");
		} ],
		superscript : [ "Superscript", "ed_format_sup.gif", false, function(e) {
			e.execCommand("superscript");
		} ],
		justifyleft : [ "Justify Left", "ed_align_left.gif", false,
				function(e) {
					e.execCommand("justifyleft");
				} ],
		justifycenter : [ "Justify Center", "ed_align_center.gif", false,
				function(e) {
					e.execCommand("justifycenter");
				} ],
		justifyright : [ "Justify Right", "ed_align_right.gif", false,
				function(e) {
					e.execCommand("justifyright");
				} ],
		justifyfull : [ "Justify Full", "ed_align_justify.gif", false,
				function(e) {
					e.execCommand("justifyfull");
				} ],
		insertorderedlist : [ "Ordered List", "ed_list_num.gif", false,
				function(e) {
					e.execCommand("insertorderedlist");
				} ],
		insertunorderedlist : [ "Bulleted List", "ed_list_bullet.gif", false,
				function(e) {
					e.execCommand("insertunorderedlist");
				} ],
		outdent : [ "Decrease Indent", "ed_indent_less.gif", false,
				function(e) {
					e.execCommand("outdent");
				} ],
		indent : [ "Increase Indent", "ed_indent_more.gif", false, function(e) {
			e.execCommand("indent");
		} ],
		forecolor : [ "Font Color", "ed_color_fg.gif", false, function(e) {
			e.execCommand("forecolor");
		} ],
		hilitecolor : [ "Background Color", "ed_color_bg.gif", false,
				function(e) {
					e.execCommand("hilitecolor");
				} ],
		inserthorizontalrule : [ "Horizontal Rule", "ed_hr.gif", false,
				function(e) {
					e.execCommand("inserthorizontalrule");
				} ],

		removestyle : [ "Remove height and width", "ed_blank.gif", false,
				function(e) {
					e.execCommand("removestyle");
				} ],
		inserttable : [ "Insert Table", "table_add.png", false, function(e) {
			e.execCommand("inserttable");
		} ],
		htmlmode : [ "Toggle HTML Source", "ed_html.gif",
				(HTMLArea.checkSupportedBrowser() ? true : false), function(e) {
					e.execCommand("htmlmode");
				} ],
		popupeditor : [ "Enlarge Editor Ctrl+F1", "fullscreen_maximize.gif",
				(HTMLArea.checkSupportedBrowser() ? true : false), function(e) {
					e.execCommand("popupeditor");
				} ],
		about : [ "About this editor", "ed_about.gif", true, function(e) {
			e.execCommand("about");
		} ],
		showhelp : [ "Help using editor", "ed_help.gif", true, function(e) {
			e.execCommand("showhelp");
		} ],
		undo : [ "Undoes your last action", "ed_undo.gif", false, function(e) {
			e.execCommand("undo");
		} ],
		redo : [ "Redoes your last action", "ed_redo.gif", false, function(e) {
			e.execCommand("redo");
		} ],
		cut : [ "Cut selection", "cut.png", false, cut_copy_paste ],
		copy : [ "Copy selection", "copy.png", false, cut_copy_paste ],
		paste : [ "Paste from clipboard", "paste.png", false, cut_copy_paste ],
		lefttoright : [ "Direction left to right", "ed_left_to_right.gif",
				false, function(e) {
					e.execCommand("lefttoright");
				} ],
		righttoleft : [ "Direction right to left", "ed_right_to_left.gif",
				false, function(e) {
					e.execCommand("righttoleft");
				} ]
	};

	/* ADDING CUSTOM BUTTONS
	 * ---------------------
	 *
	 * It is recommended that you add the custom buttons in an external
	 * file and leave this one unchanged.  That's because when we
	 * (InteractiveTools.com) release a new official version, it's less
	 * likely that you will have problems upgrading HTMLArea.
	 *
	 * Example on how to add a custom button when you construct the HTMLArea:
	 *
	 *   var editor = new HTMLArea("your_text_area_id");
	 *   var cfg = editor.config; // this is the default configuration
	 *   cfg.btnList["my-hilite"] =
	 *	[ function(editor) { editor.surroundHTML('<span style="background:yellow">', '</span>'); }, // action
	 *	  "Highlight selection", // tooltip
	 *	  "my_hilite.gif", // image
	 *	  false // disabled in text mode
	 *	];
	 *   cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new button to the toolbar
	 *
	 * An alternate (also more convenient and recommended) way to
	 * accomplish this is to use the registerButton function below.
	 */
	// initialize tooltips from the I18N module and generate correct image path
	for ( var i in this.btnList) {
		var btn = this.btnList[i];
		btn[1] = _editor_url + this.imgURL + btn[1];
		if (typeof HTMLArea.I18N != "undefined") {
			if (typeof HTMLArea.I18N.tooltips[i] != "undefined") {
				btn[0] = HTMLArea.I18N.tooltips[i];
			}
		}
	}
};

/** Helper function: register a new button with the configuration.  It can be
 * called with all 5 arguments, or with only one (first one).  When called with
 * only one argument it must be an object with the following properties: id,
 * tooltip, image, textMode, action.  Examples:
 *
 * 1. config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", false, function(editor) {...});
 * 2. config.registerButton({
 *      id       : "my-hilite",      // the ID of your button
 *      tooltip  : "Hilite text",    // the tooltip
 *      image    : "my-hilite.gif",  // image to be displayed in the toolbar
 *      textMode : false,            // disabled in text mode
 *      action   : function(editor) { // called when the button is clicked
 *                   editor.surroundHTML('<span class="hilite">', '</span>');
 *                 },
 *      context  : "p"               // will be disabled if outside a <p> element
 *      button text  : "Save"        // text before image
 *    });
 */
HTMLArea.Config.prototype.registerButton = function(id, tooltip, image,
		textMode, action, context, buttonText) {
	var the_id;
	if (typeof id == "string") {
		the_id = id;
	} else if (typeof id == "object") {
		the_id = id.id;
	} else {
		alert("ERROR [HTMLArea.Config::registerButton]:\ninvalid arguments");
		return false;
	}
	// check for existing id
	if (typeof this.customSelects[the_id] != "undefined") {
		// alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
	}
	if (typeof this.btnList[the_id] != "undefined") {
		// alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
	}
	switch (typeof id) {
	case "string":
		this.btnList[id] = [ tooltip, image, textMode, action, context,
				buttonText ];
		break;
	case "object":
		this.btnList[id.id] = [ id.tooltip, id.image, id.textMode, id.action,
				id.context, id.buttonText ];
		break;
	}
};

/** The following helper function registers a dropdown box with the editor
 * configuration.  You still have to add it to the toolbar, same as with the
 * buttons.  Call it like this:
 *
 * FIXME: add example
 */
HTMLArea.Config.prototype.registerDropdown = function(object) {
	// check for existing id
	if (typeof this.customSelects[object.id] != "undefined") {
		// alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown with the same ID already exists.");
	}
	if (typeof this.btnList[object.id] != "undefined") {
		// alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button with the same ID already exists.");
	}
	this.customSelects[object.id] = object;
};

/** Call this function to remove some buttons/drop-down boxes from the toolbar.
 * Pass as the only parameter a string containing button/drop-down names
 * delimited by spaces.  Note that the string should also begin with a space
 * and end with a space.  Example:
 *
 *   config.hideSomeButtons(" fontname fontsize textindicator ");
 *
 * It's useful because it's easier to remove stuff from the defaul toolbar than
 * create a brand new toolbar ;-)
 */
HTMLArea.Config.prototype.hideSomeButtons = function(remove) {
	var toolbar = this.toolbar;
	for ( var i in toolbar) {
		var line = toolbar[i];
		for ( var j = line.length; --j >= 0;) {
			if (remove.indexOf(" " + line[j] + " ") >= 0) {
				var len = 1;
				if (/separator|space/.test(line[j + 1])) {
					len = 2;
				}
				line.splice(j, len);
			}
		}
	}
};

/** Helper function: replace all TEXTAREA-s in the document with HTMLArea-s. */
HTMLArea.replaceAll = function(config) {
	var tas = document.getElementsByTagName("textarea");
	for ( var i = tas.length; i > 0; (new HTMLArea(tas[--i], config))
			.generate())
		;
};

/** Helper function: replaces the TEXTAREA with the given ID with HTMLArea. */
HTMLArea.replace = function(id, config) {
	var ta = HTMLArea.getElementById("textarea", id);
	return ta ? (new HTMLArea(ta, config)).generate() : null;
};

// Creates the toolbar and appends it to the _htmlarea
HTMLArea.prototype._createToolbar = function() {
	var editor = this; // to access this in nested functions
	var toolbar = document.createElement("div");
	//	toolbar.setAttribute("accesskey","x");
	toolbar.setAttribute("id", "wys_editor_toolbar");
	this._toolbar = toolbar;
	toolbar.className = "toolbar";
	toolbar.unselectable = "1";
	var tb_row = null;
	var tb_objects = new Object();
	this._toolbarObjects = tb_objects;

	// creates a new line in the toolbar
	function newLine() {
		//var aTable = document.createElement("a");
		//aTable.setAttribute("name","toolbaranchor");
		//toolbar.appendChild(aTable);
		var table = document.createElement("table");

		table.style.borderTop = "0px solid #CCCCCC";
		table.style.borderBottom = "1px solid #CCCCCC";
		table.style.borderLeft = "0px solid #CCCCCC";
		table.style.borderRight = "1px solid #CCCCCC";
		//table.border = "0px";
		table.cellSpacing = "0px";
		table.cellPadding = "0px";
		table.style.padding = "0px";
		table.style.margin = "0px";
		toolbar.appendChild(table);
		// TBODY is required for IE, otherwise you don't see anything
		// in the TABLE.
		var tb_body = document.createElement("tbody");
		table.appendChild(tb_body);
		tb_row = document.createElement("tr");
		tb_row.style.padding = "0px";
		tb_row.style.margin = "0px";
		tb_body.appendChild(tb_row);
	}
	; // END of function: newLine
	// init first line
	newLine();

	// updates the state of a toolbar element.  This function is member of
	// a toolbar element object (unnamed objects created by createButton or
	// createSelect functions below).
	function setButtonStatus(id, newval) {
		var oldval = this[id];
		var el = this.element;
		if (oldval != newval) {
			switch (id) {
			case "enabled":
				if (newval) {
					HTMLArea._removeClass(el, "buttonDisabled");
					el.disabled = false;
				} else {
					HTMLArea._addClass(el, "buttonDisabled");
					el.disabled = true;
				}
				break;
			case "active":
				if (newval) {
					HTMLArea._addClass(el, "buttonPressed");
				} else {
					HTMLArea._removeClass(el, "buttonPressed");
				}
				break;
			}
			this[id] = newval;
		}
	}
	; // END of function: setButtonStatus

	// this function will handle creation of combo boxes.  Receives as
	// parameter the name of a button as defined in the toolBar config.
	// This function is called from createButton, above, if the given "txt"
	// doesn't match a button.
	function createSelect(txt) {
		var options = null;
		var el = null;
		var cmd = null;
		var customSelects = editor.config.customSelects;
		var context = null;
		switch (txt) {
		case "fontsize":
		case "fontname":
		case "formatblock":
			// the following line retrieves the correct
			// configuration option because the variable name
			// inside the Config object is named the same as the
			// button/select in the toolbar.  For instance, if txt
			// == "formatblock" we retrieve config.formatblock (or
			// a different way to write it in JS is
			// config["formatblock"].
			options = editor.config[txt];
			cmd = txt;
			break;
		default:
			// try to fetch it from the list of registered selects
			cmd = txt;
			var dropdown = customSelects[cmd];
			if (typeof dropdown != "undefined") {
				options = dropdown.options;
				context = dropdown.context;
			} else {
				alert("ERROR [createSelect]:\nCan't find the requested dropdown definition");
				printStackTrace();
			}
			break;
		}
		if (options) {
			el = document.createElement("select");
			var obj = {
				name :txt, // field name
				element :el, // the UI element (SELECT)
				enabled :true, // is it enabled?
				text :false, // enabled in text mode?
				cmd :cmd, // command ID
				state :setButtonStatus, // for changing state
				context :context
			};
			tb_objects[txt] = obj;
			for ( var i in options) {
				var op = document.createElement("option");
				op.appendChild(document.createTextNode(i));
				op.value = options[i];
				el.appendChild(op);
			}
			HTMLArea._addEvent(el, "change", function() {
				setEventFlag = "true";
				editor._comboSelected(el, txt);
			});
		}
		return el;
	}
	; // END of function: createSelect

	// appends a new button to toolbar
	function createButton(txt, j) {

		// the element that will be created
		var el = null;
		var btn = null;
		switch (txt) {
		case "separator":
			el = document.createElement("div");
			el.className = "separator";
			break;
		case "space":
			el = document.createElement("div");
			el.className = "space";
			break;
		case "linebreak":
			newLine();
			return false;
		case "textindicator":
			el = document.createElement("div");
			el.appendChild(document.createTextNode("A"));
			el.className = "indicator";
			el.title = HTMLArea.I18N.tooltips.textindicator;
			var obj = {
				name :txt, // the button name (i.e. 'bold')
				element :el, // the UI element (DIV)
				enabled :true, // is it enabled?
				active :false, // is it pressed?
				text :false, // enabled in text mode?
				cmd :"textindicator", // the command ID
				state :setButtonStatus
			// for changing state
			};
			tb_objects[txt] = obj;
			break;
		default:
			btn = editor.config.btnList[txt];
		}
		if (!el && btn) {
			el = document.createElement("A");
			el.style.display = 'block';
			el.style.textDecoration = 'none';
			el.tabIndex = 0;
			//e1.setAttribute("onkeypress","alert(1)");
			el.title = btn[0];
			el.className = "button";
			if (txt == "advsimp")
				el.className = "toggle_button";

			//el.style.height="40px";
			var isText = false;
			if (typeof btn[5] != "undefined" && btn[5] != null && btn[5] != "") {
				isText = true;
			}
			if (isText) {
				el.className = "buttontext";
			}
			// let's just pretend we have a button object, and
			// assign all the needed information to it.
			var obj = {
				name :txt, // the button name (i.e. 'bold')
				element :el, // the UI element (DIV)
				enabled :true, // is it enabled?
				active :false, // is it pressed?
				text :btn[2], // enabled in text mode?
				cmd :btn[3], // the command ID
				state :setButtonStatus, // for changing state
				context :btn[4] || null // enabled in a certain context?
			};
			tb_objects[txt] = obj;
			// handlers to emulate nice flat toolbar buttons
			HTMLArea._addEvent(el, "mouseover", function() {
				if (obj.enabled) {
					HTMLArea._addClass(el, "buttonHover");
				}
			});
			HTMLArea._addEvent(el, "focus", function() {
				if (obj.enabled) {
					HTMLArea._addClass(el, "buttonHover");
				}
			});
			HTMLArea._addEvent(el, "mouseout", function() {
				if (obj.enabled)
					with (HTMLArea) {
						_removeClass(el, "buttonHover");
						_removeClass(el, "buttonActive");
						(obj.active) && _addClass(el, "buttonPressed");
					}
			});
			HTMLArea._addEvent(el, "blur", function() {
				if (obj.enabled)
					with (HTMLArea) {
						_removeClass(el, "buttonHover");
						_removeClass(el, "buttonActive");
						(obj.active) && _addClass(el, "buttonPressed");
					}
			});
			HTMLArea._addEvent(el, "mousedown", function(ev) {
				if (obj.enabled)
					with (HTMLArea) {
						setEventFlag = "true";

						_addClass(el, "buttonActive");
						_removeClass(el, "buttonPressed");
						_stopEvent(is_ie ? window.event : ev);
					}
			});
			// when clicked, do the following:
			HTMLArea._addEvent(el, "click", function(ev) {
				if (obj.enabled)
					with (HTMLArea) {
						setEventFlag = "true";
						_removeClass(el, "buttonActive");
						_removeClass(el, "buttonHover");
						obj.cmd(editor, obj.name, obj);
						_stopEvent(is_ie ? window.event : ev);
					}
			});

			// when key-pressed, do the following:

			HTMLArea._addEvent(el, "keydown", function(ev) {

				if (ev.keyCode == 13) {
					obj.cmd(editor, obj.name, obj);
					_stopEvent(is_ie ? window.event : ev);
				}
			});

			var img = document.createElement("img");
			img.src = btn[1];
			img.alt = btn[0];
			img.hspace = "2";
			img.vspace = "0";
			img.style.width = "18px";
			img.style.height = "18px";
			img.setAttribute("align", "absmiddle");

			el.appendChild(img);
			if (isText) {
				var tNode = document.createTextNode(" " + btn[5]);
				el.appendChild(tNode);
			}
		} else if (!el) {

			if (typeof txt != "undefined")
				el = createSelect(txt);
		}
		if (el) {
			var tb_cell = document.createElement("td");
			//tb_cell.className = "button";
			if (j == 0) {
				var aTable = document.createElement("a");
				aTable.setAttribute("name", "toolbaranchor");
				tb_cell.appendChild(aTable);
			}

			//tb_cell.style.paddingLeft="0px";
			tb_cell.style.padding = "0px";
			tb_cell.style.margin = "0px";
			tb_row.appendChild(tb_cell);

			if (txt == "advsimp") {
				tb_cell.style.width = "100%";
				tb_cell.align = "right";
				tb_cell.style.border = "none";
			}

			tb_cell.appendChild(el);
			if (isText) {
				tb_cell.setAttribute("align", "center");
			}
		} else {
			alert("FIXME: Unknown toolbar item: " + txt);
		}
		return el;
	}
	;

	var first = true;
	for ( var i in this.config.toolbar) {
		if (!first) {
			createButton("linebreak");
		} else {
			first = false;
		}
		var group = this.config.toolbar[i];
		for ( var j in group) {
			var code = group[j];
			if (/^([IT])\[(.*?)\]/.test(code)) {
				// special case, create text label
				var l7ed = RegExp.$1 == "I"; // localized?
				var label = RegExp.$2;
				if (l7ed) {
					label = HTMLArea.I18N.custom[label];
				}
				var tb_cell = document.createElement("td");
				tb_cell.style.border = "0px solid #000000";
				tb_row.appendChild(tb_cell);
				tb_cell.className = "label";
				tb_cell.innerHTML = label;

			} else {

				createButton(code, j);
			}
		}
	}
	//alert(toolbar.innerHTML);
	if (this.toolBarChange) {
		fChild = this._htmlArea.firstChild;
		this._htmlArea.insertBefore(toolbar, fChild);
		this.toolBarChange = false;
	} else {
		this._htmlArea.appendChild(toolbar);
	}
	if (this.config.toolbar.length > 0 && this.config.toolbar[0].length > 0) {
		toolbar.style.display = ""
	} else {
		toolbar.style.display = "none"
		document.getElementById("wys_editor_container").style.display = "none";
	}
};

HTMLArea.prototype._createStatusBar = function() {
	var statusbar = document.createElement("div");
	statusbar.className = "statusBar";
	this._htmlArea.appendChild(statusbar);
	this._statusBar = statusbar;
	// statusbar.appendChild(document.createTextNode(HTMLArea.I18N.msg["Path"] + ": "));
	// creates a holder for the path view
	div = document.createElement("span");
	div.className = "statusBarTree";
	//div.innerHTML = HTMLArea.I18N.msg["Path"] + ": ";
	this._statusBarTree = div;
	this._statusBar.appendChild(div);
	if (!this.config.statusBar) {
		// disable it...
		statusbar.style.display = "none";
	}
};

// Creates the HTMLArea object and replaces the textarea with it.
HTMLArea.prototype.generate = function() {

	var editor = this; // we'll need "this" in some nested functions
	// get the textarea
	var textarea = this._textArea;
	if (typeof textarea == "string") {
		// it's not element but ID
		this._textArea = textarea = HTMLArea.getElementById("textarea",
				textarea);
	}
	this._ta_size = {
		w :textarea.offsetWidth,
		h :textarea.offsetHeight
	};
	textarea.style.display = "none";

	// create the editor framework
	var htmlarea = document.createElement("div");
	htmlarea.className = "htmlarea";
	htmlarea.setAttribute("id", "wys_editor_container");
	this._htmlArea = htmlarea;

	// insert the editor before the textarea.
	textarea.parentNode.insertBefore(htmlarea, textarea);

	if (textarea.form) {
		// we have a form, on submit get the HTMLArea content and
		// update original textarea.
		var f = textarea.form;
		if (typeof f.onsubmit == "function") {
			var funcref = f.onsubmit;
			if (typeof f.__msh_prevOnSubmit == "undefined") {
				f.__msh_prevOnSubmit = [];
			}
			f.__msh_prevOnSubmit.push(funcref);
		}
		f.onsubmit = function() {
			editor._textArea.value = editor.getHTML();
			var a = this.__msh_prevOnSubmit;
			// call previous submit methods if they were there.
			if (typeof a != "undefined") {
				for ( var i in a) {
					a[i]();
				}
			}
		};
	}
	// add a handler for the "back/forward" case -- on body.unload we save
	// the HTML content into the original textarea.
	window.onunload = function() {
		editor._textArea.value = editor.getHTML();
	};

	// creates & appends the toolbar
	this._createToolbar();

	if (HTMLArea.checkSupportedBrowser()) {
		var aIframe = document.createElement("a");
		aIframe.setAttribute("name", "#editoranchor");
		aIframe.setAttribute("tabindex", "0");
		htmlarea.appendChild(aIframe);
		var iframe = document.createElement("iframe");

		//iframe.src="about:blank"; //HTMLArea.is_ie?"about:blank":"javascript:void();";
		iframe.src = "/" + appContext + "/" + jspContext
				+ "/htmlarea/popups/blank.html";

		htmlarea.appendChild(iframe);
		this._iframe = iframe;
	}
	this._createStatusBar();

	if (!HTMLArea.is_ie && HTMLArea.checkSupportedBrowser()) {
		iframe.style.borderWidth = "0";
	}

	var height = this.config.height, width = this.config.width;
	if (height == "auto")
		height = this._ta_size.h;
	if (height == parseInt(height, 10)) {
		if (this.config.sizeIncludesToolbar) {
			if (typeof this._toolbar.offsetHeight != "undefined") {
				height -= this._toolbar.offsetHeight;
			}
			if (typeof this._statusBar.offsetHeight != "undefined") {
				height -= this._statusBar.offsetHeight;
			}
		}
		if (height < 0)
			height = 0;
		height += "px";
	}
	if (width == "auto")
		width = this._ta_size.w;
	if (width == parseInt(width, 10))
		width += "px";

	if (HTMLArea.checkSupportedBrowser()) {
		iframe.style.width = width;
		iframe.style.height = height;
	} else {
		textarea.style.display = "block";
	}

	textarea.style.width = width;
	textarea.style.height = height;

	/*
	// create the IFRAME
	var iframe = document.createElement("iframe");
	htmlarea.appendChild(iframe);

	this._iframe = iframe;

	// creates & appends the status bar, if the case
	this._createStatusBar();

	// remove the default border as it keeps us from computing correctly
	// the sizes.  (somebody tell me why doesn't this work in IE)

	if (!HTMLArea.is_ie) {
		iframe.style.borderWidth = "1px";
	// iframe.frameBorder = "1";
	// iframe.marginHeight = "0";
	// iframe.marginWidth = "0";
	}

	// size the IFRAME according to user's prefs or initial textarea
	var height = (this.config.height == "auto" ? (this._ta_size.h + "px") : this.config.height);
	height = parseInt(height);
	var width = (this.config.width == "auto" ? (this._ta_size.w + "px") : this.config.width);
	width = parseInt(width);

	if (!HTMLArea.is_ie) {
		height -= 2;
		width -= 2;
	}

	iframe.style.width = width + "px";
	if (this.config.sizeIncludesToolbar) {
		// substract toolbar height
		height -= this._toolbar.offsetHeight;
		height -= this._statusBar.offsetHeight;
	}
	if (height < 0) {
		height = 0;
	}
	iframe.style.height = height + "px";

	// the editor including the toolbar now have the same size as the
	// original textarea.. which means that we need to reduce that a bit.
	textarea.style.width = iframe.style.width;
	textarea.style.height = iframe.style.height;
	 */
	// IMPORTANT: we have to allow Mozilla a short time to recognize the
	// new frame.  Otherwise we get a stupid exception.
	function initIframe() {

		if (!HTMLArea.checkSupportedBrowser()) {
			editor.focusEditor();
			editor.updateToolbar();
			return;
		}

		var doc = editor._iframe.contentWindow.document;

		if (!doc) {
			// Try again..
			// FIXME: don't know what else to do here.  Normally
			// we'll never reach this point.
			if (HTMLArea.is_gecko) {
				setTimeout(initIframe, 100);
				return false;
			} else {
				alert("ERROR: IFRAME can't be initialized.");
			}
		}

		if (HTMLArea.is_gecko) {
			// enable editable mode for Mozilla
			doc.designMode = "on";
		}
		editor._doc = doc;
		if (!editor.config.fullPage) {
			doc.open();
			var html = "<html>\n";
			html += "<head>\n";
			html += "<META http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />";
			if (editor.config.baseURL)
				html += '<base href="' + editor.config.baseURL + '" />';

			if (editor.editorCSS != null) {
				html += "<link rel=\"stylesheet\" type=\"text/css\" href=\""
						+ editor.editorCSS + "\" />";
			}

			if (editor.userCSS != null) {
				html += editor.userCSS;
			}

			//html += "<style> html,body { border: 0px; } " + editor.config.pageStyle + "</style>\n";
			html += "<style> html,body {background:#ffffff;} "
					+ editor.config.pageStyle
					+ " .anchor{background-image: url(\"anchor.gif\"); width:21px;height:21px;} .anchor:before { content: url(\"anchor.gif\")}</style>\n";
			html += "<style title=\"table borders\">"
					+ ".htmtableborders {border : 1px dashed #000000 ! important;},.plugin{background-color:#CCCCCC;border:1px solid #919EBE;padding:2px;margin-right:2px;margin-bottom:2px;} \n"
					+ "</style>\n";
			html += "</head>\n";
			html += "<body>\n";
			if (editor._textArea.textContent) {
				html += (editor._textArea.textContent);
			} else {
				html += (editor._textArea.value);
			}
			html += "</body>\n";
			html += "</html>";
			doc.write(html);
			doc.close();
		} else {
			var html = editor._textArea.value;
			if (html.match(HTMLArea.RE_doctype)) {
				editor.setDoctype(RegExp.$1);
				html = html.replace(HTMLArea.RE_doctype, "");
			}
			doc.open();
			doc.write(html);
			doc.close();
		}

		if (HTMLArea.is_ie) {
			// enable editable mode for IE.	 For some reason this
			// doesn't work if done in the same place as for Gecko
			// (above).
			doc.body.contentEditable = true;
		}
		editor._toggleBorders();
		editor.focusEditor();
		// intercept some events; for updating the toolbar & keyboard handlers
		HTMLArea
				._addEvents(
						doc,
						[ "keydown", "keypress", "mousedown", "mouseup", "drag" ],
						function(event) {

							setEventFlag = "true";
							return editor
									._editorEvent(HTMLArea.is_ie ? editor._iframe.contentWindow.event
											: event);
						});

		// check if any plugins have registered refresh handlers
		for ( var i in editor.plugins) {
			var plugin = editor.plugins[i].instance;
			if (typeof plugin.onGenerate == "function")
				plugin.onGenerate();
		}

		setTimeout( function() {
			editor.updateToolbar();
		}, 250);

		if (typeof editor.onGenerate == "function")
			editor.onGenerate();

		var familyObj = document.getElementById("family");
		var ePageSubmitObj = document.getElementById("editpage_submit");
		if (familyObj == null) {
			if (window.opener) {
				familyObj = window.opener.document.getElementById("family");
			}
		}
		if (ePageSubmitObj == null) {
			if (window.opener) {
				ePageSubmitObj = window.opener.document
						.getElementById("editpage_submit");
			}
		}
		/*
		if( familyObj != null && ePageSubmitObj != null )
		{
		   if( familyObj.value == "20" 
		   		|| familyObj.value == "21" )
		   {
			   if( ePageSubmitObj.value =="Update" )
			   {
				  if (HTMLArea.is_gecko) 
				  {
					doc.designMode = "off";
				  }
				  else
				  {
					doc.body.contentEditable = false;
				  }
			   }
		   }
		}
		 */
	}
	;
	setTimeout(initIframe, 100);
	HTMLAreaSetTimer();
};

// Switches editor mode; parameter can be "textmode" or "wysiwyg".  If no
// parameter was passed this function toggles between modes.
HTMLArea.prototype.setMode = function(mode) {

	if (!HTMLArea.checkSupportedBrowser()) {
		return;
	}
	if (typeof mode == "undefined") {
		mode = ((this._editMode == "textmode") ? "wysiwyg" : "textmode");
	}
	switch (mode) {
	case "textmode":
		var val = this.getHTML();
		//val = CodeFormatter.Format(val);
		if (this._textArea.textContent) {
			this._textArea.textContent = val;
			this._textArea.value = this._textArea.textContent;
		} else {
			this._textArea.value = val;
		}
		this._iframe.style.display = "none";
		this._textArea.style.display = "block";
		if (this.config.statusBar) {
			this._statusBar.innerHTML = HTMLArea.I18N.msg["TEXT_MODE"];
		}
		break;
	case "wysiwyg":
		if (HTMLArea.is_gecko) {
			// disable design mode before changing innerHTML
			try {
				this._doc.designMode = "off";
			} catch (e) {
			}
			;
		}
		if (!this.config.fullPage)
			this._doc.body.innerHTML = this.getHTML();
		else
			this.setFullHTML(this.getHTML());
		this._iframe.style.display = "block";
		this._textArea.style.display = "none";
		if (HTMLArea.is_gecko) {
			// we need to refresh that info for Moz-1.3a
			try {
				this._doc.designMode = "on";
			} catch (e) {
			}
			;
		}
		if (this.config.statusBar) {
			this._statusBar.innerHTML = '';
			//this._statusBar.appendChild(document.createTextNode(HTMLArea.I18N.msg["Path"] + ": "));
			//this._statusBar.appendChild(this._statusBarTree);
		}
		break;
	default:
		alert("Mode <" + mode + "> not defined!");
		return false;
	}
	this._editMode = mode;
	this.focusEditor();

};

HTMLArea.prototype.setFullHTML = function(html) {
	var save_multiline = RegExp.multiline;
	RegExp.multiline = true;
	if (html.match(HTMLArea.RE_doctype)) {
		this.setDoctype(RegExp.$1);
		html = html.replace(HTMLArea.RE_doctype, "");
	}
	RegExp.multiline = save_multiline;
	if (!HTMLArea.is_ie) {
		if (html.match(HTMLArea.RE_head))
			this._doc.getElementsByTagName("head")[0].innerHTML = RegExp.$1;
		if (html.match(HTMLArea.RE_body))
			this._doc.getElementsByTagName("body")[0].innerHTML = RegExp.$1;
	} else {
		var html_re = /<html>((.|\n)*?)<\/html>/i;
		html = html.replace(html_re, "$1");
		this._doc.open();
		this._doc.write(html);
		this._doc.close();
		this._doc.body.contentEditable = true;
		return true;
	}
};

/***************************************************
 *  Category: PLUGINS
 ***************************************************/

// this is the variant of the function above where the plugin arguments are
// already packed in an array.  Externally, it should be only used in the
// full-screen editor code, in order to initialize plugins with the same
// parameters as in the opener window.
HTMLArea.prototype.registerPlugin2 = function(plugin, args) {
	if (HTMLArea.checkSupportedBrowser()) {
		if (typeof plugin == "string") {
			plugin = eval(plugin);
		}
		var obj = new plugin(this, args);
		if (obj) {
			var clone = {};
			var info = plugin._pluginInfo;
			for ( var i in info)
				clone[i] = info[i];
			clone.instance = obj;
			clone.args = args;
			this.plugins[plugin._pluginInfo.name] = clone;
		} else
			alert("Can't register plugin " + plugin.toString() + ".");
	}
};

// Create the specified plugin and register it with this HTMLArea
HTMLArea.prototype.registerPlugin = function() {
	if (HTMLArea.checkSupportedBrowser()) {
		var plugin = arguments[0];
		var args = [];
		for ( var i = 1; i < arguments.length; ++i)
			args.push(arguments[i]);
		this.registerPlugin2(plugin, args);
	}
};

// static function that loads the required plugin and lang file, based on the
// language loaded already for HTMLArea.  You better make sure that the plugin
// _has_ that language, otherwise shit might happen ;-)
HTMLArea.loadPlugin = function(pluginName) {

	var langName = _editor_lang_path.substring(_editor_lang_path
			.lastIndexOf("/") + 1);
	if (!is_safari_2) {
		if (HTMLArea.checkSupportedBrowser()) {
			var dir = _editor_url + "plugins/" + pluginName;
			var plugin = pluginName.replace(/([a-z])([A-Z])([a-z])/g,
					function(str, l1, l2, l3) {
						return l1 + "-" + l2.toLowerCase() + l3;
					}).toLowerCase()
					+ ".js";
			var plugin_file = dir + "/" + plugin;
			var plugin_lang = _editor_lang_path; //dir + "/lang/" + HTMLArea.I18N.lang + ".js";
			HTMLArea._scripts.push(plugin_file, plugin_lang);
			if (!isJsFileLoaded(pluginName)) {
				document.write("<script type='text/javascript' src='"
						+ plugin_file + "'></script>");
			}
			if (!isJsFileLoaded(langName)) {
				document.write("<script type='text/javascript' src='"
						+ plugin_lang + "'></script>");
			}
		}
	}
};

HTMLArea.loadStyle = function(style, plugin) {
	var url = _editor_url || '';
	if (typeof plugin != "undefined") {
		url += "plugins/" + plugin + "/";
	}
	url += style;
	document.write("<style type='text/css'>@import url(" + url + ");</style>");
};
HTMLArea.loadStyle("./skins/" + skin + "/htmlarea.css");

/***************************************************
 *  Category: EDITOR UTILITIES
 ***************************************************/

// The following function is a slight variation of the word cleaner code posted
// by Weeezl (user @ InteractiveTools forums).
HTMLArea.prototype._wordClean = function(want_stats) {
	var body = this._doc.body;

	if (!body)
		return;
	var stats = {
		empty_tags :0,
		mso_class :0,
		mso_style :0,
		mso_xmlel :0,
		orig_len :body.innerHTML.length,
		T :(new Date()).getTime()
	}, stats_txt = {
		empty_tags :"Empty tags removed: ",
		mso_class :"MSO class names removed: ",
		mso_style :"MSO inline style removed: ",
		mso_xmlel :"MSO XML elements stripped: "
	};
	function showStats() {
		var txt = "Word cleaner stats: \n\n";
		for ( var i in stats)
			if (stats_txt[i])
				txt += stats_txt[i] + stats[i] + "\n";
		txt += "\nInitial document length: " + stats.orig_len + "\n";
		txt += "Final document length: " + body.innerHTML.length + "\n";
		txt += "Clean-up took " + (((new Date()).getTime() - stats.T) / 1000)
				+ " seconds";
		alert(txt);
	}
	;
	function clearClass(node) {
		var newc = node.className.replace(/(^|\s)mso.*?(\s|$)/ig, ' ');
		if (newc != node.className) {
			node.className = newc;
			if (!/\S/.test(node.className)) {
				node.removeAttribute("className");
				++stats.mso_class;
			}
		}
	}
	;
	function clearStyle(node) {
		var declarations = node.style.cssText.split(/\s*;\s*/), line;
		for ( var i = declarations.length; --i >= 0;) {
			line = declarations[i];
			if (/^mso|^tab-stops|^layout-grid/i.test(line)
					|| /^margin\s*:\s*[0-9]+..\s+[0-9]+..\s+[0-9]+../i
							.test(line)) {
				++stats.mso_style;
				declarations.splice(i, 1);
			} else {
				declarations[i] = line.replace(/windowtext/, '#000');
			}
		}
		node.style.cssText = declarations.join("; ");
	}
	;

	function stripTag(el) {
		if (HTMLArea.is_ie)
			el.outerHTML = HTMLArea.htmlEncode(el.innerText);
		else {
			var txt = document.createTextNode(HTMLArea.getInnerText(el));
			el.parentNode.insertBefore(txt, el);
			el.parentNode.removeChild(el);
		}
		++stats.mso_xmlel;
	}
	;

	function checkEmpty(el) {
		if (/^(a|span|b|strong|i|em|font)$/i.test(el.tagName)
				&& el.childNodes.length == 0) {
			el.parentNode.removeChild(el);
			++stats.empty_tags;
		}
	}
	;

	function parseTree(root) {
		var tag = root.tagName.toLowerCase(), i, next;
		if ((HTMLArea.is_ie && root.scopeName != 'HTML')
				|| (!HTMLArea.is_ie && /:/.test(tag))) {
			stripTag(root);
			return false;
		} else {
			clearClass(root);
			clearStyle(root);
			for (i = root.firstChild; i; i = next) {
				next = i.nextSibling;
				if (i.nodeType == 1 && parseTree(i))
					checkEmpty(i);
			}
		}
		return true;
	}
	;
	parseTree(body);

	this.updateToolbar();

};

HTMLArea.prototype._stripScriptTag = function() {
	var editor = this;
	var text = editor.getHTML();
	var val = RegExp.multiline;

	RegExp.multiline = true;
	var reg = new RegExp("<script.*?>.*?<\/script>", "gi");
	text = text.replace(reg, "");

	editor.setHTML(text);
}

HTMLArea.prototype._clearFonts = function() {
	var D = this.getInnerHTML();
	if (confirm(("Would you like to clear font typefaces?"))) {
		D = D.replace(/<([^>]*)face="([^>"]*)"([^>]*)>/gi, '<$1 $3>')
		D = D.replace(/<([^>]*)face=([^>]*)>/gi, '<$1>');
		D = D.replace(/font-family:[^;}"']+;?/gi, "");
	}
	if (confirm(("Would you like to clear font sizes?"))) {
		D = D.replace(/<([^>]*)size="([^>"]*)"([^>]*)>/gi, '<$1 $3>')
		D = D.replace(/<([^>]*)size=([^>]*)>/gi, '<$1>');
		D = D.replace(/font-size:[^;}"']+;?/gi, "");
	}
	if (confirm(("Would you like to clear font colors?"))) {
		D = D.replace(/<([^>]*)color="([^>"]*)"([^>]*)>/gi, '<$1 $3>')
		D = D.replace(/<([^>]*)color=([^>]*)>/gi, '<$1>');
		D = D.replace(/([^-])color:[^;}"']+;?/gi, "$1");
	}
	D = D.replace(/<(font|FONT)\s*>([^<]+)(<\/FONT>|<\/font>)/gi, '$2');
	//D = D.replace(/<[\/]?(font|[ovwxp]:\w+)[^>]*?>/gi, '');
	this.setHTML(D);
	this.updateToolbar();
};

HTMLArea.prototype.forceRedraw = function() {
	this._doc.body.style.visibility = "hidden";
	this._doc.body.style.visibility = "visible";
	// this._doc.body.innerHTML = this.getInnerHTML();
};

// focuses the iframe window.  returns a reference to the editor document.
HTMLArea.prototype.focusEditor = function() {
	try {
		switch (this._editMode) {
		case "wysiwyg":
			this._iframe.contentWindow.focus();
			break;
		case "textmode":
			this._textArea.focus();
			break;
		default:
			alert("ERROR: mode " + this._editMode + " is not defined");
		}
		return this._doc;
	} catch (err) {
	}
	return null;
};

// takes a snapshot of the current text (for undo)
HTMLArea.prototype._undoTakeSnapshot = function() {
	++this._undoPos;
	if (this._undoPos >= this.config.undoSteps) {
		// remove the first element
		this._undoQueue.shift();
		--this._undoPos;
	}
	// use the fasted method (getInnerHTML);
	var take = true;
	var txt = this.getInnerHTML();
	if (this._undoPos > 0)
		take = (this._undoQueue[this._undoPos - 1] != txt);
	if (take) {
		this._undoQueue[this._undoPos] = txt;
	} else {
		this._undoPos--;
	}
};

HTMLArea.prototype.undo = function() {
	if (this._undoPos > 0) {
		var txt = this._undoQueue[--this._undoPos];
		if (txt)
			this.setHTML(txt);
		else
			++this._undoPos;
	}
};

HTMLArea.prototype.redo = function() {
	if (this._undoPos < this._undoQueue.length - 1) {
		var txt = this._undoQueue[++this._undoPos];
		if (txt)
			this.setHTML(txt);
		else
			--this._undoPos;
	}
};

// updates enabled/disable/active state of the toolbar elements
HTMLArea.prototype.updateToolbar = function(noStatus) {
	var doc = this._doc;
	var text = (this._editMode == "textmode");
	var ancestors = null;
	if (!text) {
		ancestors = this.getAllAncestors();
		if (this.config.statusBar && !noStatus) {
		}
	}
	for ( var i in this._toolbarObjects) {
		var btn = this._toolbarObjects[i];
		var cmd = i;
		var inContext = true;
		if (btn.context && !text) {
			inContext = false;
			var context = btn.context;
			var attrs = [];
			if (/(.*)\[(.*?)\]/.test(context)) {
				context = RegExp.$1;
				attrs = RegExp.$2.split(",");
			}
			context = context.toLowerCase();
			var match = (context == "*");
			for ( var k in ancestors) {
				if (!ancestors[k]) {
					// the impossible really happens.
					continue;
				}
				if (match || (ancestors[k].tagName.toLowerCase() == context)) {
					inContext = true;
					for ( var ka in attrs) {
						if (!eval("ancestors[k]." + attrs[ka])) {
							inContext = false;
							break;
						}
					}
					if (inContext) {
						break;
					}
				}
			}
		}

		btn.state("enabled",
				((!text || btn.text) && inContext && !this.globalStateChange));
		if (typeof cmd == "function") {
			continue;
		}
		// look-it-up in the custom dropdown boxes
		var dropdown = this.config.customSelects[cmd];
		if ((!text || btn.text) && (typeof dropdown != "undefined")) {
			dropdown.refresh(this);
			continue;
		}
		switch (cmd) {
		case "fontname":
		case "fontsize": {
			if (!text)
				try {
					var value = ("" + doc.queryCommandValue(cmd)).toLowerCase();
					if (!value) {
						btn.element.selectedIndex = 0;
						break;
					}

					// HACK -- retrieve the config option for this
					// combo box.  We rely on the fact that the
					// variable in config has the same name as
					// button name in the toolbar.
					var options = this.config[cmd];
					var k = 0;
					for ( var j in options) {
						// FIXME: the following line is scary.
						if ((j.toLowerCase() == value)
								|| (options[j].substr(0, value.length)
										.toLowerCase() == value)) {
							btn.element.selectedIndex = k;
							throw "ok";
						}
						++k;
					}
					btn.element.selectedIndex = 0;
				} catch (e) {
				}
			;
		}
			break;

		case "formatblock": {

			var blocks = [];
			for ( var i in this.config['formatblock']) {
				if (typeof (this.config['formatblock'][i]) == 'string') // prevent iterating over wrong type
				{
					blocks[blocks.length] = this.config['formatblock'][i];
				}
			}

			var deepestAncestor = this._getFirstAncestor(this._getSelection(),
					blocks);

			if (deepestAncestor) {
				for ( var x = 0; x < blocks.length; x++) {
					if (blocks[x].toLowerCase() == deepestAncestor.tagName
							.toLowerCase()) {
						btn.element.selectedIndex = x;
					}
				}
			} else {
				btn.element.selectedIndex = 0;
			}
		}
			break;

		case "textindicator":
			if (!text) {
				try {
					with (btn.element.style) {
						backgroundColor = HTMLArea._makeColor(doc
								.queryCommandValue(HTMLArea.is_ie ? "backcolor"
										: "hilitecolor"));
						if (/transparent/i.test(backgroundColor)) {
							// Mozilla
							backgroundColor = HTMLArea._makeColor(doc
									.queryCommandValue("backcolor"));
						}
						color = HTMLArea._makeColor(doc
								.queryCommandValue("forecolor"));
						fontFamily = doc.queryCommandValue("fontname");
						alert(fontFamily);
						fontWeight = doc.queryCommandState("bold") ? "bold"
								: "normal";
						fontStyle = doc.queryCommandState("italic") ? "italic"
								: "normal";
					}
				} catch (e) {
					// alert(e + "\n\n" + cmd);
				}
			}
			break;
		case "htmlmode":
			btn.state("active", (text && HTMLArea.checkSupportedBrowser()));
			break;
		case "lefttoright":
		case "righttoleft":
			var el = this.getParentElement();
			while (el && !HTMLArea.isBlockElement(el))
				el = el.parentNode;
			if (el)
				btn.state("active",
						(el.style.direction == ((cmd == "righttoleft") ? "rtl"
								: "ltr")));
			break;
		default:
			try {
				btn.state("active", (!text && doc.queryCommandState(cmd)));
			} catch (e) {
			}
		}
	}
	// take undo snapshots
	if (this._customUndo && !this._timerUndo) {
		this._undoTakeSnapshot();
		var editor = this;
		this._timerUndo = setTimeout( function() {
			editor._timerUndo = null;
		}, this.config.undoTimeout);
	}
	// check if any plugins have registered refresh handlers
	for ( var i in this.plugins) {
		var plugin = this.plugins[i].instance;
		if (typeof plugin.onUpdateToolbar == "function")
			plugin.onUpdateToolbar();
	}
};

/** Returns a node after which we can insert other nodes, in the current
 * selection.  The selection is removed.  It splits a text node, if needed.
 */
HTMLArea.prototype.insertNodeAtSelection = function(toBeInserted) {
	if (!HTMLArea.is_ie) {
		var sel = this._getSelection();
		var range = this._createRange(sel);
		// remove the current selection
		sel.removeAllRanges();
		range.deleteContents();
		var node = range.startContainer;
		var pos = range.startOffset;
		switch (node.nodeType) {
		case 3: // Node.TEXT_NODE
			// we have to split it at the caret position.
			if (toBeInserted.nodeType == 3) {
				// do optimized insertion
				node.insertData(pos, toBeInserted.data);
				range = this._createRange();
				range.setEnd(node, pos + toBeInserted.length);
				range.setStart(node, pos + toBeInserted.length);
				sel.addRange(range);
			} else {
				node = node.splitText(pos);
				var selnode = toBeInserted;
				if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
					selnode = selnode.firstChild;
				}
				node.parentNode.insertBefore(toBeInserted, node);
				this.selectNodeContents(selnode);
				this.updateToolbar();
			}
			break;
		case 1: // Node.ELEMENT_NODE
			if (node.tagName == "HTML") {
				var kids = node.childNodes;
				for ( var i = 0; i < kids.length; i++) {
					if (kids[i].tagName == "BODY") {
						node = kids[i];
						break;
					}
				}
			}
			var selnode = toBeInserted;
			if (toBeInserted.nodeType == 11 /* Node.DOCUMENT_FRAGMENT_NODE */) {
				selnode = selnode.firstChild;
			}
			node.insertBefore(toBeInserted, node.childNodes[pos]);
			this.selectNodeContents(selnode);
			this.updateToolbar();
			break;
		}
	} else {
		return null; // this function not yet used for IE <FIXME>
	}
};

// Returns the deepest node that contains both endpoints of the selection.
HTMLArea.prototype.getParentElement = function() {
	var sel = this._getSelection();
	var range = this._createRange(sel);
	if (HTMLArea.is_ie) {
		switch (sel.type) {
		case "Text":
			var parent = range.parentElement();
			while (true) {
				var TestRange = range.duplicate();
				TestRange.moveToElementText(parent);
				if (TestRange.inRange(range))
					break;
				if ((parent.nodeType != 1)
						|| (parent.tagName.toLowerCase() == 'body'))
					break;
				parent = parent.parentElement;
			}
			return parent;
		case "None":
			// It seems that even for selection of type "None",
			// there _is_ a parent element and it's value is not
			// only correct, but very important to us.  MSIE is
			// certainly the buggiest browser in the world and I
			// wonder, God, how can Earth stand it?
			return range.parentElement();
		case "Control":
			return range.item(0);
		default:
			return this._doc.body;
		}
	} else
		try {
			var p = range.commonAncestorContainer;
			if (!range.collapsed && range.startContainer == range.endContainer
					&& range.startOffset - range.endOffset <= 1
					&& range.startContainer.hasChildNodes())
				p = range.startContainer.childNodes[range.startOffset];
			/*
			alert(range.startContainer + ":" + range.startOffset + "\n" +
			      range.endContainer + ":" + range.endOffset);
			 */
			while (p.nodeType == 3) {
				p = p.parentNode;
			}
			return p;
		} catch (e) {
			return null;
		}
};

// Returns an array with all the ancestor nodes of the selection.
HTMLArea.prototype.getAllAncestors = function() {
	this.focusEditor();
	var p = this.getParentElement();
	var a = [];
	while (p && (p.nodeType == 1) && (p.tagName.toLowerCase() != 'body')) {
		a.push(p);
		p = p.parentNode;
	}
	a.push(this._doc.body);
	return a;
};

// Selects the contents inside the given node
HTMLArea.prototype.selectNodeContents = function(node, pos) {
	this.focusEditor();
	this.forceRedraw();
	var range;
	var collapsed = (typeof pos != "undefined");
	if (HTMLArea.is_ie) {
		range = this._doc.body.createTextRange();
		range.moveToElementText(node);
		(collapsed) && range.collapse(pos);
		range.select();
	} else {
		var sel = this._getSelection();
		range = this._doc.createRange();
		range.selectNodeContents(node);
		(collapsed) && range.collapse(pos);
		sel.removeAllRanges();
		sel.addRange(range);
	}
};

/** Call this function to insert HTML code at the current position.  It deletes
 * the selection, if any.
 */
HTMLArea.prototype.insertHTML = function(html) {
	var sel = this._getSelection();
	var range = this._createRange(sel);
	if (HTMLArea.is_ie) {
		if (sel.type == "Control") {
			var theItem = range.item(0);
			if (/^img$/i.test(theItem.tagName)) {
				parNode = theItem.parentNode;
				var nextElem = theItem.nextSibling;
				var divElem = this._doc.createElement("div");
				divElem.innerHTML = html;
				var childElems = divElem.childNodes;
				if (childElems.length > 0) {
					parNode.replaceChild(childElems(0), theItem);
				}

				for ( var i = 1; i < childElems.length; i++) {
					if (nextElem) {
						parNode.insertBefore(childElems(i), nextElem);
					} else {
						parNode.appendChild(childElems(i));
					}
				}
			}
		} else {
			range.pasteHTML(html);
		}
	} else {
		// construct a new document fragment with the given HTML
		var fragment = this._doc.createDocumentFragment();
		var div = this._doc.createElement("div");
		div.innerHTML = html;
		while (div.firstChild) {
			// the following call also removes the node from div
			fragment.appendChild(div.firstChild);
		}
		// this also removes the selection
		var node = this.insertNodeAtSelection(fragment);
	}
};

/**
 *  Call this function to surround the existing HTML code in the selection with
 *  your tags.  FIXME: buggy!  This function will be deprecated "soon".
 */
HTMLArea.prototype.surroundHTML = function(startTag, endTag) {
	var html = this.getSelectedHTML();
	// the following also deletes the selection
	this.insertHTML(startTag + html + endTag);
};

/// Retrieve the selected block
HTMLArea.prototype.getSelectedHTML = function() {
	var sel = this._getSelection();
	var range = this._createRange(sel);
	var existing = null;
	if (HTMLArea.is_ie) {
		if (sel.type == "Control") {
			var rTagName = range.item(0).tagName;
			if (rTagName && /^img$/i.test(rTagName)) {
				existing = range.item(0).outerHTML;
			}
		} else {
			existing = range.htmlText;
		}
	} else {
		existing = HTMLArea.getHTML(range.cloneContents(), false, this);
	}
	return existing;
};

/// Return true if we have some selection
HTMLArea.prototype.hasSelectedText = function() {
	// FIXME: come _on_ mishoo, you can do better than this ;-)
	return this.getSelectedHTML() != '';
};

HTMLArea.prototype._createBlogLink = function(link) {
	var editor = this;
	var outparam = null;
	if (typeof link == "undefined") {
		link = this.getParentElement();
		if (link && !/^a$/i.test(link.tagName))
			link = null;
	}
	if (link)
		outparam = {
			f_href :HTMLArea.is_ie ? editor.stripBaseURL(link.href) : link
					.getAttribute("href"),
			f_title :link.title,
			f_target :link.target
		};
	var blogLinkDialogUrl = "blog_link.jsp";

	var blogName = "";
	if (document.getElementById("blogname"))
		blogName = document.getElementById("blogname").value;
	else
		blogName = window.opener.document.getElementById("blogname").value;

	var userName = "";

	if (document.getElementById("username"))
		userName = document.getElementById("username").value;
	else
		userName = window.opener.document.getElementById("username").value;

	//var projectName = getProjectTitle();
	//var pageTitle = getPageTitle();
	blogLinkDialogUrl += "?blogname=" + escape(blogName) + "&username="
			+ escape(userName);

	//this._popupDialog("link.html", function(param) {
	this._popupDialog(blogLinkDialogUrl, function(param) {
		try {
			if (!param)
				return false;
			var a = link;
			var sel = editor._getSelection();
			var range = editor._createRange(sel);
			if (!a) {
				if (!HTMLArea.is_ie) {

					if (range == "") {
						var selHtml = editor.getSelectedHTML();
						if (/^<img(.*)$/i.test(selHtml)) {
							editor.insertHTML("<a href='" + param.f_href + "'>"
									+ selHtml + "</a>");
						} else {
							editor.insertHTML("<a href='" + param.f_href + "'>"
									+ param.f_title + "</a>");
						}
					} else {
						if (range.startContainer
								&& range.startContainer.nodeType == 1)
							editor._doc.execCommand("createlink", false,
									param.f_href);
						else
							editor.insertHTML("<a href='" + param.f_href + "'>"
									+ range + "</a>");
					}

				} else {
					if (range.text == "") {
						var selHtml = editor.getSelectedHTML();
						if (/^<img(.*)$/i.test(selHtml)) {
							editor.insertHTML("<a href='" + param.f_href + "'>"
									+ selHtml + "</a>");
						} else {
							editor.insertHTML("<a href='" + param.f_href + "'>"
									+ param.f_title + "</a>");
						}
					} else {
						editor._doc.execCommand("createlink", false,
								param.f_href);
					}
				}
				a = editor.getParentElement();
				var sel = editor._getSelection();
				var range = editor._createRange(sel);
				if (!HTMLArea.is_ie) {
					a = range.startContainer;
					if (!/^a$/i.test(a.tagName))
						a = a.nextSibling;
				}
			} else
				a.href = param.f_href.trim();
			if (!/^a$/i.test(a.tagName))
				return false;
			a.target = param.f_target.trim();
			a.title = param.f_title.trim();
			editor.selectNodeContents(a);
			editor.updateToolbar();
		} catch (er) {
		}
	}, outparam, 600, 500);
};

HTMLArea.prototype._createLink = function(link) {
	var editor = this;
	editor.focusEditor();
	var outparam = null;
	if (typeof link == "undefined") {
		link = this.getParentElement();
		if (link && !/^a$/i.test(link.tagName))
			link = null;
	}
	var hyperlink = "";
	var valinternal = "";
	var valexternal = "";
	if (link) {
		var className = HTMLArea.is_ie ? link.getAttribute("className") : link
				.getAttribute("class");
		hyperlink = HTMLArea.is_ie ? editor.stripBaseURL(link.href) : link
				.getAttribute("href");
		if (className == "internal") {
			valinternal = hyperlink;
		} else {
			valexternal = hyperlink;
		}
	}
	if (link)
		outparam = {
			f_internal_href :valinternal,
			f_external_href :valexternal,
			f_title :link.title,
			f_target :link.target
		};
	var wikiLinkDialogUrl = "link.jsp";

	/**var projectName = document.getElementById("projectname").value;
	var pageTitle = "";
	if( document.getElementById("pagetitle") != null )
	{
		pageTitle = document.getElementById("pagetitle").value;
	}
	 **/
	var projectName = "";

	if (!window.opener) {

		projectName = document.getElementById("projectname").value;
	} else {

		if (document.getElementById("pop") != null
				&& document.getElementById("pop").value == "true") {
			projectName = document.getElementById("projectname").value;
		} else {
			if (document.getElementById("projectname")) {
				projectName = document.getElementById("projectname").value;

			} else {
				projectName = window.opener.document
						.getElementById("projectname").value;
			}
		}
	}
	var pageTitle = "";
	if (!window.opener) {

		if (document.getElementById("pagetitle") != null) {
			pageTitle = document.getElementById("pagetitle").value;
		}
	} else {
		if (document.getElementById("pop") != null
				&& document.getElementById("pop").value == "true") {
			if (document.getElementById("pagetitle") != null) {
				pageTitle = document.getElementById("pagetitle").value;
			}
		} else {
			try {
				if (document.getElementById("pagetitle")) {
					pageTitle = document.getElementById("pagetitle").value;
				} else {
					pageTitle = window.opener.document
							.getElementById("pagetitle").value;
				}
			} catch (e) {
			}
			;
		}
	}
	wikiLinkDialogUrl += "?projectname=" + escape(projectName) + "&pagetitle="
			+ escape(pageTitle);

	//this._popupDialog("link.html", function(param) {
	this._popupDialog(wikiLinkDialogUrl, function(param) {
		try {
			if (!param) {
				return false;
			}

			var a = link;
			if (!a) {
				var sel = editor._getSelection();
				var range = editor._createRange(sel);
				if (param.radioexternal == "external") {
					if (!HTMLArea.is_ie) {
						if (range == "") {
							var selHtml = editor.getSelectedHTML();
							if (/^<img(.*)$/i.test(selHtml)) {
								editor.insertHTML("<a target='"
										+ param.f_target.trim() + "' href='"
										+ param.f_external_href + "'>"
										+ selHtml + "</a>");
							} else {
								editor.insertHTML("<a target='"
										+ param.f_target.trim() + "' href='"
										+ param.f_external_href + "'>"
										+ param.f_external_href + "</a>");
							}
						} else {
							if (range.startContainer
									&& range.startContainer.nodeType == 1)
								editor._doc.execCommand("createlink", false,
										param.f_external_href);
							else
								editor.insertHTML("<a target='"
										+ param.f_target.trim() + "' href='"
										+ param.f_external_href + "'>" + range
										+ "</a>");
						}
						a = editor.getParentElement();
						//var test = this.getClosest("a");
			if (param.radioexternal == "external") {
				a.setAttribute("class", "external");
			}
			if (param.radiointernal == "internal") {
				a.setAttribute("class", "internal");
			}
		} else {

			//editor._doc.execCommand("createlink", false, param.f_external_href);
			var tt = range.text;
			var sHtml = editor.getSelectedHTML();
			if (sHtml == "") {
				sHtml = param.f_external_href;
			}
			if (/^<img(.*)$/i.test(sHtml)) {
				editor.insertHTML("<a target='" + param.f_target.trim()
						+ "' class='external' href='" + param.f_external_href
						+ "'>" + sHtml + "</a>");
			} else {
				if (tt != "") {
					range.pasteHTML("<a target='" + param.f_target.trim()
							+ "' class='external' href='"
							+ param.f_external_href + "'>" + tt + "</a>");
				} else if (param.f_title && param.f_title.length > 0) {
					range.pasteHTML("<a target='" + param.f_target.trim()
							+ "' class='external' href='"
							+ param.f_external_href + "'>" + param.f_title
							+ "</a>");
				} else if (param.f_external_href
						&& param.f_external_href.length > 0) {
					range.pasteHTML("<a target='" + param.f_target.trim()
							+ "' class='external' href='"
							+ param.f_external_href + "'>"
							+ param.f_external_href + "</a>");
				}
			}
		}
	}
	if (param.radiointernal == "internal") {
		if (!HTMLArea.is_ie) {
			if (range == "") {
				var selHtml = editor.getSelectedHTML();
				if (/^<img(.*)$/i.test(selHtml)) {
					editor.insertHTML("<a target='" + param.f_target.trim()
							+ "' href='" + param.f_internal_href + "'>"
							+ selHtml + "</a>");
				} else {
					if (param.f_title && param.f_title.length > 0) {
						editor.insertHTML("<a target='" + param.f_target.trim()
								+ "' href='" + param.f_internal_href + "'>"
								+ param.f_title + "</a>");
					} else if (param.f_internal_href
							&& param.f_internal_href.length > 0) {
						editor.insertHTML("<a target='" + param.f_target.trim()
								+ "' href='" + param.f_internal_href + "'>"
								+ param.f_internal_href + "</a>");
					}
				}
			} else {
				if (range.startContainer && range.startContainer.nodeType == 1)
					editor._doc.execCommand("createlink", false,
							param.f_internal_href);
				else
					editor.insertHTML("<a target='" + param.f_target.trim()
							+ "' href='" + param.f_internal_href + "'>" + range
							+ "</a>");
			}
			a = editor.getParentElement();
			//var test = this.getClosest("a");
			if (param.radioexternal == "external") {
				a.setAttribute("class", "external");
			}
			if (param.radiointernal == "internal") {
				a.setAttribute("class", "internal");
			}
		} else {

			var tt = range.text;
			var sHtml = editor.getSelectedHTML();
			if (sHtml == "") {
				sHtml = param.f_internal_href;
			}
			if (/^<img(.*)$/i.test(sHtml)) {
				editor.insertHTML("<a target='" + param.f_target.trim()
						+ "' class='internal' href='" + param.f_internal_href
						+ "'>" + sHtml + "</a>");
			} else {
				if (tt != "") {
					range.pasteHTML("<a target='" + param.f_target.trim()
							+ "' class='internal' href='"
							+ param.f_internal_href + "'>" + tt + "</a>");
				} else if (param.f_title && param.f_title.length > 0) {
					range.pasteHTML("<a target='" + param.f_target.trim()
							+ "' class='internal' href='"
							+ param.f_internal_href + "'>" + param.f_title
							+ "</a>");
				} else if (param.f_internal_href
						&& param.f_internal_href.length > 0) {
					range.pasteHTML("<a target='" + param.f_target.trim()
							+ "' class='internal' href='"
							+ param.f_internal_href + "'>"
							+ param.f_internal_href + "</a>");
				}
			}

		}
	}

	if (!HTMLArea.is_ie) {
		a = range.startContainer;
		if (a && !/^a$/i.test(a.tagName))
			a = a.nextSibling;
	}

} else {
	if (param.radioexternal == "external") {
		a.href = param.f_external_href.trim();
		if (!HTMLArea.is_ie)
			a.setAttribute("class", "external");
		else
			a.setAttribute("className", "external");
	}
	if (param.radiointernal == "internal") {
		a.href = param.f_internal_href.trim();
		if (!HTMLArea.is_ie)
			a.setAttribute("class", "internal");
		else
			a.setAttribute("className", "internal");
	}
} //end else

if (!/^a$/i.test(a.tagName)) {
	return false;
}

a.target = param.f_target.trim();
a.title = param.f_title.trim();
//editor.selectNodeContents(a);
editor.updateToolbar();
} catch (er) {
}
}, outparam, linkHeight, 600);
};

HTMLArea.prototype._removeStyleImage = function(img) {

	img.removeAttribute("height");
	img.removeAttribute("width");
	img.removeAttribute("style");

};

// Called when the user clicks on "InsertImage" button.  If an image is already
// there, it will just modify it's properties.
HTMLArea.prototype._insertBlogImage = function(image) {
	var editor = this; // for nested functions
	editor.focusEditor();
	var outparam = null;
	if (typeof image == "undefined") {
		image = this.getParentElement();
		if (image && !/^img$/i.test(image.tagName))
			image = null;
	}

	var imgIdParam = "";
	if (image) {
		srcUrl = HTMLArea.is_ie ? editor.stripBaseURL(image.src) : image
				.getAttribute("src");
		imgIdParam = "&imgid=" + srcUrl.substring(srcUrl.lastIndexOf("/") + 1);
	}

	if (image)
		outparam = {
			f_url :HTMLArea.is_ie ? editor.stripBaseURL(image.src) : image
					.getAttribute("src"),
			f_alt :image.alt,
			f_border :image.border,
			f_align :image.align,
			f_vert :image.vspace,
			f_horiz :image.hspace,
			f_height :image.height,
			f_width :image.width
		};

	var useOpener = false;
	var parentpage = "";
	var isNewAsset = false;
	var blogImgDialogUrl = "insert_blog_image.jsp";
	var blogName = "";
	var pageTitle = "";
	var postTopic = "";

	if (document.getElementById("editpost_topic")) {
		postTopic = document.getElementById("editpost_topic").value;
	} else {
		postTopic = window.opener.document.getElementById("editpost_topic").value;
	}

	if (document.getElementById("ptitle"))
		pageTitle = document.getElementById("ptitle").value;
	else
		pageTitle = window.opener.document.getElementById("ptitle").value;

	if (document.getElementById("blogname"))
		blogName = document.getElementById("blogname").value;
	else
		blogName = window.opener.document.getElementById("blogname").value;

	var userName = "";

	if (document.getElementById("username"))
		userName = document.getElementById("username").value;
	else
		userName = window.opener.document.getElementById("username").value;

	var postId = "";
	if (document.getElementById("postid"))
		postId = document.getElementById("postid").value;
	else
		postId = window.opener.document.getElementById("postid").value;

	var commentsAllowed = "";
	if (document.getElementById("commentsAllowed"))
		commentsModerated = document.getElementById("commentsAllowed").value;
	else
		commentsModerated = window.opener.document
				.getElementById("commentsAllowed").value;

	var commentsModerated = "";
	if (document.getElementById("commentsModerated"))
		commentsModerated = document.getElementById("commentsModerated").value;
	else
		commentsModerated = window.opener.document
				.getElementById("commentsModerated").value;

	blogImgDialogUrl += "?blogname=" + escape(blogName) + "&postid=" + postId
			+ "&username=" + escape(userName) + "&ca=" + commentsModerated
			+ "&cm=" + commentsModerated;

	if (!window.opener) {

		if (document.getElementById("parentpage") != null) {
			parentpage = document.getElementById("parentpage").value;
		}
		blogImgDialogUrl += "&postid=" + postId + "&posttitle="
				+ escape(pageTitle) + "&posttopic=" + escape(postTopic);
	} else {
		if (document.getElementById("pop") != null
				&& document.getElementById("pop").value == "true") {

			if (document.getElementById("parentpage") != null) {
				parentpage = document.getElementById("parentpage").value;
			}
			blogImgDialogUrl += "&postid=" + postId + "&posttitle="
					+ escape(pageTitle) + "&posttopic=" + escape(postTopic);
		} else {
			try {
				if (document.getElementById("parentpage")) {
					parentpage = document.getElementById("parentpage").value;

				} else {
					parentpage = window.opener.document
							.getElementById("parentpage").value;
				}
			} catch (err) {
			}
			blogImgDialogUrl += "&postid=" + postId + "&posttitle="
					+ escape(pageTitle) + "&posttopic=" + escape(postTopic);
			useOpener = true;
		}
	}

	//Now add imgId incase changing img properties
	blogImgDialogUrl += imgIdParam;

	//alert("blogImgDialogUrl "+blogImgDialogUrl);

	//this._popupDialog("insert_image.html", function(param) {
	this._popupDialog(blogImgDialogUrl, function(param) {
		if (!param) { // user must have pressed Cancel
				return false;
			}
			var img = image;
			if (!img) {
				if (HTMLArea.is_ie) {
					var sel = editor._getSelection();
					var range = editor._createRange(sel);
					//editor._doc.execCommand("insertblogimage", false, param.f_url);
			editor._doc.execCommand("insertimage", false, param.f_url);
			img = range.parentElement();
			// wonder if this works...
			if (img.tagName.toLowerCase() != "img") {
				img = img.previousSibling;
			}
		} else {
			img = document.createElement('img');
			img.src = param.f_url;
			editor.insertNodeAtSelection(img);
			if (!img.tagName) {
				// if the cursor is at the beginning of the document
				img = range.startContainer.firstChild;
			}
		}
	} else {
		img.src = param.f_url;
	}

	for (field in param) {

		var value = param[field];

		switch (field) {
		case "f_alt":
			img.alt = value;
			break;
		case "f_border":
			img.border = parseInt(value || "0");
			break;
		case "f_align":
			img.align = value;
			break;
		case "f_vert":
			img.vspace = parseInt(value || "0");
			break;
		case "f_horiz":
			img.hspace = parseInt(value || "0");
			break;
		case "f_height":
			if (value == "") {

			} else {

				img.height = parseInt(value || img.height);
			}
			var style = img.style;

			if (HTMLArea.is_ie || HTMLArea.is_safari) {
				style.removeAttribute("height");
			} else {
				style.removeProperty("height");
			}
			break;
		case "f_width":
			if (value == "") {

			} else {
				img.width = parseInt(value || img.width);
			}

			var style = img.style;
			if (HTMLArea.is_ie || HTMLArea.is_safari) {
				style.removeAttribute("width");
			} else {
				style.removeProperty("width");
			}
			break;
		}
	}
}, outparam, 600, 600);
};

/*

 // Called when the user clicks on "InsertImage" button.  If an image is already
 // there, it will just modify it's properties.
 HTMLArea.prototype._insertImage = function(image) {
 var editor = this;	// for nested functions
 var outparam = null;
 if (typeof image == "undefined") {
 image = this.getParentElement();
 if (image && !/^img$/i.test(image.tagName))
 image = null;
 }
 if(image)outparam = {
 f_url    : HTMLArea.is_ie ? editor.stripBaseURL(image.src) : image.getAttribute("src"),
 f_alt    : image.alt,
 f_border : image.border,
 f_align  : image.align,
 f_vert   : image.vspace,
 f_horiz  : image.hspace,
 f_height : image.height,
 f_width  : image.width,
 f_thumbnail  : image.format
 };

 var wikiImgDialogUrl = "insert_image.jsp";

 //var projectName = document.getElementById("projectname").value;
 //var pageTitle = document.getElementById("pagetitle").value;

 var projectName = "";
 var pageTitle = "";
 var useOpener = false;
 var parentpage = "";
 var isNewAsset = false;

 if(!window.opener)
 {
 projectName = getProjectTitle();
 pageTitle = getPageTitle();
 if(pageTitle==null)
 {
 pageTitle = getNewPageTitle();
 isNewAsset  = (document.getElementById("pagetitle")==null?true:false);
 }
 if(document.getElementById("parentpage") != null)
 {
 parentpage=document.getElementById("parentpage").value;
 }
 wikiImgDialogUrl+="?projectname="+escape(projectName)+"&pagetitle="+escape(pageTitle)+"&family="+document.getElementById("family").value+"&parentpage="+escape(parentpage)+"&newasset="+(isNewAsset?"true":"false");
 }
 else
 {
 if( document.getElementById("pop") != null && document.getElementById("pop").value=="true" )
 {
 projectName = getProjectTitle();
 pageTitle 	= getPageTitle();
 if(pageTitle==null)
 {
 pageTitle = getNewPageTitle();
 isNewAsset  = (document.getElementById("pagetitle")==null?true:false);
 }
 if(document.getElementById("parentpage") != null)
 {
 parentpage=document.getElementById("parentpage").value;
 }
 wikiImgDialogUrl+="?projectname="+escape(projectName)+"&pagetitle="+escape(pageTitle)+"&family="+document.getElementById("family").value+"&parentpage="+escape(parentpage)+"&newasset="+(isNewAsset?"true":"false");
 }
 else
 {
 projectName = window.opener.getProjectTitle();
 pageTitle 	= window.opener.getPageTitle();
 if(pageTitle==null)
 {
 pageTitle = window.opener.getNewPageTitle();
 isNewAsset  = (window.opener.document.getElementById("pagetitle")==null?true:false);
 }
 if(window.opener.document.getElementById("parentpage") != null)
 {
 parentpage=window.opener.document.getElementById("parentpage").value;
 }
 wikiImgDialogUrl+="?projectname="+escape(projectName)+"&pagetitle="+escape(pageTitle)+"&family="+window.opener.document.getElementById("family").value+"&parentpage="+escape(parentpage)+"&newasset="+(isNewAsset?"true":"false");
 useOpener = true;
 }
 }
 if( pageTitle == null || pageTitle == "" )
 {
 alert("Please enter the title.");
 return;
 }
 //this._popupDialog("insert_image.html", function(param) {
 this._popupDialog(wikiImgDialogUrl, function(param) {
 if (!param) {	// user must have pressed Cancel
 return false;
 }
 var img = image;
 if (!img) {      
 if (HTMLArea.is_ie) {
 var sel = editor._getSelection();
 var range = editor._createRange(sel);
 editor._doc.execCommand("insertimage", false, param.f_url);
 img = range.parentElement();
 // wonder if this works...
 if (img.tagName.toLowerCase() != "img") {
 img = img.previousSibling;
 }
 } else {
 img = document.createElement('img');
 img.src = param.f_url;
 editor.insertNodeAtSelection(img);
 if (!img.tagName) {
 // if the cursor is at the beginning of the document
 img = range.startContainer.firstChild;
 }
 }
 } else {
 img.src = param.f_url;
 }

 for (field in param) {

 var value = param[field];

 switch (field) {
 case "f_alt"    : 
 img.alt	 = value; 
 break;
 case "f_border" : 
 img.border = parseInt(value || "0"); 
 break;
 case "f_align"  : 
 img.align	 = value; 
 break;
 case "f_vert"   : 
 img.vspace = parseInt(value || "0"); 
 break;
 case "f_horiz"  : 
 img.hspace = parseInt(value || "0"); 
 break;
 case "f_height" : 
 img.height = parseInt(value || img.height); 
 var style = img.style;
 if(HTMLArea.is_ie)
 {
 style.removeAttribute("height");
 }
 else
 {
 style.removeProperty("height");
 }
 break;	   
 case "f_width"  : 
 img.width = parseInt(value || img.width); 
 var style = img.style;
 if(HTMLArea.is_ie)
 {
 style.removeAttribute("width");
 }
 else
 {
 style.removeProperty("width");
 }
 break;
 }
 }
 }, outparam);
 };
 */

// Called when the user clicks on "InsertImage" button.  If an image is already
// there, it will just modify it's properties.
HTMLArea.prototype._insertImage = function(image) {
	var editor = this; // for nested functions
	editor.focusEditor();
	var outparam = null;
	if (typeof image == "undefined") {
		image = this.getParentElement();
		if (image && !/^img$/i.test(image.tagName))
			image = null;

	}
	if (image)
		outparam = {
			f_url :HTMLArea.is_ie ? editor.stripBaseURL(image.src) : image
					.getAttribute("src"),
			f_alt :image.alt,
			f_border :image.border,
			f_align :image.align,
			f_vert :image.vspace,
			f_horiz :image.hspace,
			f_height :image.height,
			f_width :image.width,
			f_thumbnail :image.getAttribute("format")
		};

	var wikiImgDialogUrl = "insert_image.jsp";

	//var projectName = document.getElementById("projectname").value;
	//var pageTitle = document.getElementById("pagetitle").value;

	var projectName = "";
	var pageTitle = "";
	var useOpener = false;
	var parentpage = "";
	var isNewAsset = false;
	var pageId = page_id;
	var resourceId = "";
	var thumb = "";
	if(outparam != null)
	{
		if(outparam.f_url.indexOf("/thumb") > 0)
		{
			thumb= "true";
			outparam.f_url = outparam.f_url.substring(0,outparam.f_url.lastIndexOf("/"));
			resourceId = outparam.f_url.substring(outparam.f_url.lastIndexOf("/")+1,outparam.f_url.length);
		}
		else
		{
			resourceId = outparam.f_url.substring(outparam.f_url.lastIndexOf("/")+1,outparam.f_url.length);
		}
	}

	if (!window.opener) {
		projectName = getProjectTitle();
		pageTitle = getPageTitle();
		if (pageTitle == null) {
			pageTitle = getNewPageTitle();
			isNewAsset = (document.getElementById("pagetitle") == null ? true
					: false);
		}
		if (document.getElementById("parentpage") != null) {
			parentpage = document.getElementById("parentpage").value;
		}
		wikiImgDialogUrl += "?projectname=" + escape(projectName)
				+ "&pagetitle=" + pageTitle + "&family="
				+ document.getElementById("family").value + "&parentpage="
				+ escape(parentpage) + "&newasset="
				+ (isNewAsset ? "true" : "false") + "&pageid=" + pageId;
		if(resourceId.length > 0)
			wikiImgDialogUrl += "&resourceid="+ resourceId;
		if(thumb.length > 0)
			wikiImgDialogUrl += "&thumb="+ thumb;

	} else {

		if (document.getElementById("pop") != null
				&& document.getElementById("pop").value == "true") {
			projectName = getProjectTitle();
			pageTitle = getPageTitle();
			if (pageTitle == null) {
				pageTitle = getNewPageTitle();
				isNewAsset = (document.getElementById("pagetitle") == null ? true
						: false);
			}
			if (document.getElementById("parentpage") != null) {
				parentpage = document.getElementById("parentpage").value;
			}
			wikiImgDialogUrl += "?projectname=" + escape(projectName)
					+ "&pagetitle=" + pageTitle + "&family="
					+ document.getElementById("family").value + "&parentpage="
					+ escape(parentpage) + "&newasset="
					+ (isNewAsset ? "true" : "false") + "&pageid=" + pageId;
		} else {
			if (document.getElementById("projectname")) {
				projectName = document.getElementById("projectname").value;
			} else {
				projectName = window.opener.document
						.getElementById("projectname").value;
			}
			try {
				if (document.getElementById("pagetitle")) {
					pageTitle = document.getElementById("pagetitle").value;
				} else {
					pageTitle = window.opener.document
							.getElementById("pagetitle").value;
				}
			} catch (e) {
				pageTitle = document.getElementById("editpage_title").value;
				isNewAsset = true;
			}
			;
			if (pageTitle == null) {
				if (document.getElementById("editpage_title")) {
					pageTitle = document.getElementById("editpage_title").value;
				} else {
					pageTitle = window.opener.document
							.getElementById("editpage_title").value;
				}

				if (document.getElementById("pagetitle")) {
					isNewAsset = (document.getElementById("pagetitle") == null ? true
							: false);
				} else {
					isNewAsset = (window.opener.document
							.getElementById("pagetitle") == null ? true : false);

				}
			}
			if (document.getElementById("parentpage")) {
				parentpage = document.getElementById("parentpage").value;

			} else {
				parentpage = window.opener.document
						.getElementById("parentpage").value;
			}
			var family = "";
			if (document.getElementById("family")) {
				family = document.getElementById("family").value;
			} else {
				family = window.opener.document.getElementById("family").value;
			}
			wikiImgDialogUrl += "?projectname=" + escape(projectName)
					+ "&pagetitle=" + pageTitle + "&family=" + family
					+ "&parentpage=" + escape(parentpage) + "&newasset="
					+ (isNewAsset ? "true" : "false") + "&pageid=" + pageId;
			useOpener = true;
		}
	}
	if (pageTitle == null || pageTitle == "") {
		alert(HTMLArea.I18N.msg["please_enter_title"]);
		return;
	}
	//this._popupDialog("insert_image.html", function(param) {
	this._popupDialog(wikiImgDialogUrl, function(param) {
		if (!param) { // user must have pressed Cancel
				return false;
			}
			var img = image;
			if (!img) {
				if (HTMLArea.is_ie) {
					var sel = editor._getSelection();
					var range = editor._createRange(sel);
					editor._doc.execCommand("insertimage", false, param.f_url);
					img = range.parentElement();
					// wonder if this works...
			if (img.tagName.toLowerCase() != "img") {
				img = img.previousSibling;
			}
		} else {
			img = document.createElement("img");

			img.src = param.f_url;
			if (is_safari) {
				img.removeAttribute("height");
				img.removeAttribute("width");

			}
			editor.insertNodeAtSelection(img);

			if (!img.tagName) {
				// if the cursor is at the beginning of the document
				img = range.startContainer.firstChild;
			}
		}
	} else {
		img.src = param.f_url;
	}

	for (field in param) {

		var value = param[field];
		switch (field) {
		case "f_alt":
			img.alt = value;
			break;
		case "f_border":
			img.border = parseInt(value || "0");
			break;
		case "f_align":
			img.align = value;
			break;
		case "f_vert":
			img.vspace = parseInt(value || "0");
			break;
		case "f_horiz":
			img.hspace = parseInt(value || "0");
			break;
		case "f_height":
			if (value == "") {

			} else {

				img.height = parseInt(value || img.height);
			}
			var style = img.style;
			if (HTMLArea.is_ie || HTMLArea.is_safari) {
				style.removeAttribute("height");
			} else {
				style.removeProperty("height");
			}
			break;
		case "f_width":
			if (value == "") {

			} else {
				img.width = parseInt(value || img.width);
			}

			var style = img.style;
			if (HTMLArea.is_ie || HTMLArea.is_safari) {
				style.removeAttribute("width");
			} else {
				style.removeProperty("width");
			}
			break;
		}
	}
}, outparam, 640, 700);
};

// Called when the user clicks on "InsertSmiley" button. 
HTMLArea.prototype._insertSmiley = function(image) {

	var editor = this; // for nested functions
	editor.focusEditor();
	var doc = editor._doc;
	var outparam = null;
	this._popupDialog("insert_smiley.jsp", function(param) {
		if (!param) { // user must have pressed Cancel
				return false;
			}
			var img = image;
			var img = doc.createElement("img");

			img.src = param.f_url;
			img.setAttribute("align", "absmiddle");
			img.setAttribute("hspace", "2");
			if (HTMLArea.is_ie) {
				var sel = editor._getSelection();
				var range = editor._createRange(sel);
				range.pasteHTML(img.outerHTML);
			} else {
				// insert the table
			editor.insertNodeAtSelection(img);
		}
		editor.focusEditor();
		return true;
	}, outparam, 300, 400);
};

// Called when the user clicks on "InsertSmiley" button. 
HTMLArea.prototype._insertBlogSmiley = function(image) {

	var editor = this; // for nested functions
	editor.focusEditor();
	var doc = editor._doc;
	var outparam = null;
	this._popupDialog("insert_blog_smiley.jsp", function(param) {
		if (!param) { // user must have pressed Cancel
				return false;
			}
			var img = image;
			var img = doc.createElement("img");

			img.src = param.f_url;
			img.setAttribute("align", "absmiddle");
			img.setAttribute("hspace", "2");
			if (HTMLArea.is_ie) {
				var sel = editor._getSelection();
				var range = editor._createRange(sel);
				range.pasteHTML(img.outerHTML);
			} else {
				// insert the table
			editor.insertNodeAtSelection(img);
		}
		editor.focusEditor();
		return true;
	}, outparam, 300, 400);
};

// Called when the user clicks on "InsertSmiley" button. 
HTMLArea.prototype._spellCheck = function(image) {

	var editor = this; // for nested functions
	editor.focusEditor();
	var doc = editor._doc;
	var outparam = null;
	this._popupDialog("spellcheck.jsp?b=wiki_text", function(param) {

		return true;
	}, outparam, 300, 400);
};

//Called when the user clicks on "InsertSpecialChar" button. 
HTMLArea.prototype._insertExcel = function() {

	var editor = this; // for nested functions
	editor.focusEditor();
	var doc = editor._doc;
	var outparam = null;
	this._popupDialog("insert_excel.jsp", function(param) {
		if (!param) { // user must have pressed Cancel
				return false;
			}
			if (HTMLArea.is_ie) {
				var sel = editor._getSelection();
				var range = editor._createRange(sel);
				range.pasteHTML(param.content);
			} else {
				var newNode = doc.createElement("div");
				newNode.innerHTML = param.content;
				editor.insertNodeAtSelection(newNode);
			}
			editor.focusEditor();
			return true;
		}, outparam, 600, 650);
};

//  Called when the user clicks on Math Editor button. 
HTMLArea.prototype._showMath = function() {
	var outparam = null;

	var wikiWordDialogUrl = "insert_math.jsp";
	var projectName = "";
	var pageTitle = "";
	var useOpener = false;
	var parentpage = "";
	var isNewAsset = false;
	var pageId = page_id;

	if (!window.opener) {
		projectName = getProjectTitle();
		pageTitle = getPageTitle();
		if (pageTitle == null) {
			pageTitle = getNewPageTitle();
			isNewAsset = (document.getElementById("pagetitle") == null ? true
					: false);
		}
		if (document.getElementById("parentpage") != null) {
			parentpage = document.getElementById("parentpage").value;
		}
		wikiWordDialogUrl += "?projectname=" + escape(projectName)
				+ "&pagetitle=" + escape(pageTitle) + "&family="
				+ document.getElementById("family").value + "&parentpage="
				+ escape(parentpage) + "&newasset="
				+ (isNewAsset ? "true" : "false");
	} else {
		if (document.getElementById("pop") != null
				&& document.getElementById("pop").value == "true") {
			projectName = getProjectTitle();
			pageTitle = getPageTitle();
			if (pageTitle == null) {
				pageTitle = getNewPageTitle();
				isNewAsset = (document.getElementById("pagetitle") == null ? true
						: false);
			}
			if (document.getElementById("parentpage") != null) {
				parentpage = document.getElementById("parentpage").value;
			}
			wikiWordDialogUrl += "?projectname=" + escape(projectName)
					+ "&pagetitle=" + escape(pageTitle) + "&family="
					+ document.getElementById("family").value + "&parentpage="
					+ escape(parentpage) + "&newasset="
					+ (isNewAsset ? "true" : "false");
		} else {
			if (document.getElementById("projectname")) {
				projectName = document.getElementById("projectname").value;
			} else {
				projectName = window.opener.document
						.getElementById("projectname").value;
			}
			if (document.getElementById("pagetitle")) {
				pageTitle = document.getElementById("pagetitle").value;
			} else {
				pageTitle = window.opener.document.getElementById("pagetitle").value;
			}
			if (pageTitle == null) {
				if (document.getElementById("editpage_title")) {
					pageTitle = document.getElementById("editpage_title").value;
				} else {
					pageTitle = window.opener.document
							.getElementById("editpage_title").value;
				}

				if (document.getElementById("pagetitle")) {
					isNewAsset = (document.getElementById("pagetitle") == null ? true
							: false);
				} else {
					isNewAsset = (window.opener.document
							.getElementById("pagetitle") == null ? true : false);

				}
			}
			if (document.getElementById("parentpage")) {
				parentpage = document.getElementById("parentpage").value;

			} else {
				parentpage = window.opener.document
						.getElementById("parentpage").value;
			}
			var family = "";
			if (document.getElementById("family")) {
				family = document.getElementById("family").value;
			} else {
				family = window.opener.document.getElementById("family").value;
			}

			wikiWordDialogUrl += "?projectname=" + escape(projectName)
					+ "&pagetitle=" + escape(pageTitle) + "&family=" + family
					+ "&parentpage=" + escape(parentpage) + "&newasset="
					+ (isNewAsset ? "true" : "false");
			useOpener = true;
		}
	}

	if (pageTitle == null || pageTitle == "") {
		alert(HTMLArea.I18N.msg["please_enter_title"]);
		return;
	}

	var editor = this; // for nested functions
	editor.focusEditor();
	var doc = editor._doc;

	this._popupDialog(wikiWordDialogUrl, function(param) {
		if (!param) { // user must have pressed Cancel
				return false;
			}

			if (HTMLArea.is_ie) {
				var sel = editor._getSelection();
				var range = editor._createRange(sel);
				range.pasteHTML(param.content);
			} else {
				var newNode = doc.createElement("div");
				newNode.innerHTML = param.content;
				editor.insertNodeAtSelection(newNode);
			}
			editor.focusEditor();
			return true;
		}, outparam, 600, 800);
};

//  Called when the user clicks on "InsertWord" button. 
HTMLArea.prototype._insertWord = function() {
	//var editor = this;	// for nested functions
	//editor.focusEditor();
	//var doc = editor._doc;
	var outparam = null;

	var wikiWordDialogUrl = "insert_word.jsp";
	var projectName = "";
	var pageTitle = "";
	var useOpener = false;
	var parentpage = "";
	var isNewAsset = false;
	var pageId = page_id;

	if (!window.opener) {
		projectName = getProjectTitle();
		pageTitle = getPageTitle();
		if (pageTitle == null) {
			pageTitle = getNewPageTitle();
			isNewAsset = (document.getElementById("pagetitle") == null ? true
					: false);
		}
		if (document.getElementById("parentpage") != null) {
			parentpage = document.getElementById("parentpage").value;
		}
		wikiWordDialogUrl += "?projectname=" + escape(projectName)
				+ "&pagetitle=" + escape(pageTitle) + "&family="
				+ document.getElementById("family").value + "&parentpage="
				+ escape(parentpage) + "&newasset="
				+ (isNewAsset ? "true" : "false") + "&pageid=" + pageId;
	} else {
		if (document.getElementById("pop") != null
				&& document.getElementById("pop").value == "true") {
			projectName = getProjectTitle();
			pageTitle = getPageTitle();
			if (pageTitle == null) {
				pageTitle = getNewPageTitle();
				isNewAsset = (document.getElementById("pagetitle") == null ? true
						: false);
			}
			if (document.getElementById("parentpage") != null) {
				parentpage = document.getElementById("parentpage").value;
			}
			wikiWordDialogUrl += "?projectname=" + escape(projectName)
					+ "&pagetitle=" + escape(pageTitle) + "&family="
					+ document.getElementById("family").value + "&parentpage="
					+ escape(parentpage) + "&newasset="
					+ (isNewAsset ? "true" : "false") + "&pageid=" + pageId;
		} else {
			if (document.getElementById("projectname")) {
				projectName = document.getElementById("projectname").value;
			} else {
				projectName = window.opener.document
						.getElementById("projectname").value;
			}
			if (document.getElementById("pagetitle")) {
				pageTitle = document.getElementById("pagetitle").value;
			} else {
				pageTitle = window.opener.document.getElementById("pagetitle").value;
			}
			if (pageTitle == null) {
				if (document.getElementById("editpage_title")) {
					pageTitle = document.getElementById("editpage_title").value;
				} else {
					pageTitle = window.opener.document
							.getElementById("editpage_title").value;
				}

				if (document.getElementById("pagetitle")) {
					isNewAsset = (document.getElementById("pagetitle") == null ? true
							: false);
				} else {
					isNewAsset = (window.opener.document
							.getElementById("pagetitle") == null ? true : false);

				}
			}
			if (document.getElementById("parentpage")) {
				parentpage = document.getElementById("parentpage").value;

			} else {
				parentpage = window.opener.document
						.getElementById("parentpage").value;
			}
			var family = "";
			if (document.getElementById("family")) {
				family = document.getElementById("family").value;
			} else {
				family = window.opener.document.getElementById("family").value;
			}
			wikiWordDialogUrl += "?projectname=" + escape(projectName)
					+ "&pagetitle=" + escape(pageTitle) + "&family=" + family
					+ "&parentpage=" + escape(parentpage) + "&newasset="
					+ (isNewAsset ? "true" : "false") + "&pageid=" + pageId;
			useOpener = true;
		}
	}
	if (pageTitle == null || pageTitle == "") {
		alert(HTMLArea.I18N.msg["please_enter_title"]);
		return;
	}

	var editor = this; // for nested functions
	editor.focusEditor();
	var doc = editor._doc;

	this._popupDialog(wikiWordDialogUrl, function(param) {
		if (!param) { // user must have pressed Cancel
				return false;
			}

			if (HTMLArea.is_ie) {
				var sel = editor._getSelection();
				var range = editor._createRange(sel);
				range.pasteHTML(param.content);
			} else {
				var newNode = doc.createElement("div");
				newNode.innerHTML = param.content;
				editor.insertNodeAtSelection(newNode);
			}
			editor.focusEditor();
			return true;
		}, outparam, 600, 650);
};

// Called when the user clicks on "InsertSpecialChar" button. 
HTMLArea.prototype._insertSpecialChar = function(image) {

	var editor = this; // for nested functions
	editor.focusEditor();
	var doc = editor._doc;
	var outparam = null;
	this._popupDialog("insert_specialchars.jsp", function(param) {
		if (!param) { // user must have pressed Cancel
				return false;
			}
			if (HTMLArea.is_ie) {
				var sel = editor._getSelection();
				var range = editor._createRange(sel);
				range.pasteHTML(param.f_url);
			} else {
				var textNode = doc.createTextNode(param.f_url);
				editor.insertNodeAtSelection(textNode);
			}
			editor.focusEditor();
			return true;
		}, outparam, 220, 550);
};

// Called when the user clicks on "CreateAnchor" button. 
HTMLArea.prototype._createAnchor = function(anchorName) {

	var editor = this; // for nested functions
	editor.focusEditor();
	var doc = editor._doc;
	var outparam = null;
	this._popupDialog("create_anchor.jsp", function(param) {
		if (!param) { // user must have pressed Cancel
				return false;
			}
			var anchor = doc.createElement("a");
			var sel = editor._getSelection();
			var range = editor._createRange(sel);
			anchor.setAttribute("name", param);
			anchor.setAttribute("class", "anchor");
			anchor.setAttribute("alt", param);
			anchor.setAttribute("title", param);
			if (HTMLArea.is_ie) {
				range.pasteHTML("<a name=\"" + param
						+ "\" class=\"anchor\" alt=\"" + param + "\"></a>");
			} else {
				editor.insertNodeAtSelection(anchor);
			}
			editor.focusEditor();
			return true;
		}, outparam, 150, 300);
};

//Called when the user clicks on "InsertPanel" button. 

// Called when the user clicks on "InsertSmiley" button. 
HTMLArea.prototype._insertPanel = function(image) {

	var editor = this; // for nested functions
	editor.focusEditor();
	var doc = editor._doc;
	var outparam = null;
	this
			._popupDialog("insert_panel.jsp", function(param) {
				if (!param) { // user must have pressed Cancel
						return false;
					}
					var table = doc.createElement("table");
					if (param.f_url == "1") {
						table.style.height = "60px";
						table.style.width = "100%";

						table.style.borderCollapse = "collapse";
						table.style.backgroundColor = "#FFFFCC";
						table.style.border = "1px solid #CCCCCC";
						var tr = doc.createElement("tr");
						tr.style.verticalAlign = "top";
						table.appendChild(tr);

						var td = doc.createElement("td");
						td.style.padding = "10px";
						(HTMLArea.is_gecko)
								&& td.appendChild(doc.createElement("br"));
						tr.appendChild(td);

						if (HTMLArea.is_ie) {
							sel = editor._getSelection();
							range = editor._createRange(sel);
							range.pasteHTML(table.outerHTML);
						} else {
							// insert the table
					editor.insertNodeAtSelection(table);
				}
			} else if (param.f_url == "2") {
				table.style.height = "60px";
				table.style.width = "100%";

				table.style.borderCollapse = "collapse";
				table.style.backgroundColor = "#FFCCCC";
				table.style.border = "1px solid #FF0000";
				var tr = doc.createElement("tr");
				tr.style.verticalAlign = "top";
				table.appendChild(tr);

				var td = doc.createElement("td");
				td.style.padding = "10px";
				(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
				tr.appendChild(td);

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					range.pasteHTML(table.outerHTML);
				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
				}
			} else if (param.f_url == "3") {
				table.style.height = "60px";
				table.style.width = "100%";

				table.style.borderCollapse = "collapse";
				table.style.backgroundColor = "#CCFFCC";
				table.style.border = "1px solid #008000";
				var tr = doc.createElement("tr");
				tr.style.verticalAlign = "top";
				table.appendChild(tr);

				var td = doc.createElement("td");
				td.style.padding = "10px";
				(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
				tr.appendChild(td);

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					range.pasteHTML(table.outerHTML);
				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
				}
			} else if (param.f_url == "4") {
				table.style.height = "60px";
				table.style.width = "100%";
				table.style.borderCollapse = "collapse";
				table.style.backgroundColor = "#CEE7FF";
				table.style.border = "1px solid #6699CC";
				var tr = doc.createElement("tr");
				tr.style.verticalAlign = "top";
				table.appendChild(tr);

				var td = doc.createElement("td");
				td.style.padding = "10px";
				(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
				tr.appendChild(td);

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					range.pasteHTML(table.outerHTML);
				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
				}
			} else if (param.f_url == "5") {
				table.style.height = "60px";
				table.style.width = "100%";
				table.style.borderCollapse = "collapse";
				table.style.backgroundColor = "#CCCCCC";
				table.style.border = "1px solid #999999";
				var tr = doc.createElement("tr");
				tr.style.verticalAlign = "top";
				table.appendChild(tr);

				var td = doc.createElement("td");
				td.style.padding = "10px";
				(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
				tr.appendChild(td);

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					range.pasteHTML(table.outerHTML);
				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
				}
			} else if (param.f_url == "15") {
				table.style.height = "60px";
				table.style.width = "100%";
				table.style.borderCollapse = "collapse";
				table.style.backgroundColor = "#FFFFFF";
				table.style.border = "1px dashed #999999";
				var tr = doc.createElement("tr");
				tr.style.verticalAlign = "top";
				table.appendChild(tr);

				var td = doc.createElement("td");
				td.style.padding = "10px";
				(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
				tr.appendChild(td);

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					range.pasteHTML(table.outerHTML);
				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
				}
			} else if (param.f_url == "16") {
				table.style.height = "60px";
				table.style.width = "100%";
				table.style.borderCollapse = "collapse";
				table.style.backgroundColor = "#F4F3F0";
				table.style.border = "1px dashed #999999";
				var tr = doc.createElement("tr");
				tr.style.verticalAlign = "top";
				table.appendChild(tr);

				var td = doc.createElement("td");
				td.style.padding = "10px";
				(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
				tr.appendChild(td);

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					range.pasteHTML(table.outerHTML);
				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
				}
			} else if (param.f_url == "6") {
				table.style.height = "500px";
				table.style.width = "100%";
				table.style.border = "0px none rgb(0, 0, 0)";
				table.cellPadding = "3";
				table.cellSpacing = "3";
				var inner = " <tr><td width=\"33%\" style=\"vertical-align: top; text-align: left;border: 0px none rgb(0, 0, 0);\"> </td><td width=\"33%\" style=\"vertical-align: top; text-align: left;border: 0px none rgb(0, 0, 0);\"> </td><td width=\"33%\" style=\"vertical-align: top; text-align: left;border: 0px none rgb(0, 0, 0);\"> </td></tr>";

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					var tableHtml = "<table style=\"BORDER-RIGHT: rgb(0,0,0) 0px; BORDER-TOP: rgb(0,0,0) 0px; VERTICAL-ALIGN: top; BORDER-LEFT: rgb(0,0,0) 0px; BORDER-BOTTOM: rgb(0,0,0) 0px; TEXT-ALIGN: left\" cellspacing=\"3\" cellpadding=\"3\" width=\"100%\" height=\"500px;\">"
							+ inner + "</table>";
					range.pasteHTML(tableHtml);
				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
					table.innerHTML = inner;
				}
				editor._toggleBorders();
			} else if (param.f_url == "7") {
				table.style.height = "500px";
				table.style.width = "100%";
				table.style.border = "0px none rgb(0, 0, 0)";
				table.cellPadding = "3";
				table.cellSpacing = "3";
				var inner = " <tr><td width=\"65%\" style=\"vertical-align: top; text-align: left;border: 0px none rgb(0, 0, 0);\"> </td><td width=\"35%\" style=\"vertical-align: top; text-align: left;border: 0px none rgb(0, 0, 0);\"> </td></tr>";

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					var tableHtml = "<table style=\"BORDER-RIGHT: rgb(0,0,0) 0px; BORDER-TOP: rgb(0,0,0) 0px; VERTICAL-ALIGN: top; BORDER-LEFT: rgb(0,0,0) 0px; BORDER-BOTTOM: rgb(0,0,0) 0px; TEXT-ALIGN: left\" cellspacing=\"3\" cellpadding=\"3\" width=\"100%\" height=\"500px;\">"
							+ inner + "</table>";
					range.pasteHTML(tableHtml);
				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
					table.innerHTML = inner;
				}
				editor._toggleBorders();
			} else if (param.f_url == "8") {
				table.style.height = "500px";
				table.style.width = "100%";
				table.style.border = "0px none rgb(0, 0, 0)";
				table.cellPadding = "3";
				table.cellSpacing = "3";
				var inner = " <tr><td cellspacing=\"3\" cellpadding=\"3\" width=\"35%\" style=\"vertical-align: top; text-align: left;border: 0px none rgb(0, 0, 0);\"> </td><td width=\"65%\" style=\"vertical-align: top; text-align: left;border: 0px none rgb(0, 0, 0);\"> </td></tr>";

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					var tableHtml = "<table style=\"BORDER-RIGHT: rgb(0,0,0) 0px; BORDER-TOP: rgb(0,0,0) 0px; VERTICAL-ALIGN: top; BORDER-LEFT: rgb(0,0,0) 0px; BORDER-BOTTOM: rgb(0,0,0) 0px; TEXT-ALIGN: left\" width=\"100%\" height=\"500px;\">"
							+ inner + "</table>";
					range.pasteHTML(tableHtml);
				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
					table.innerHTML = inner;
				}
				editor._toggleBorders();
			} else if (param.f_url == "9") {
				table.style.height = "500px";
				table.style.width = "100%";
				table.style.border = "0px none rgb(0, 0, 0)";
				table.cellPadding = "3";
				table.cellSpacing = "3";
				var inner = " <tr><td cellspacing=\"3\" cellpadding=\"3\" width=\"25%\" style=\"vertical-align: top; text-align: left;border: 0px none rgb(0, 0, 0);\"> </td><td width=\"50%\" style=\"vertical-align: top; text-align: left;border: 0px none rgb(0, 0, 0);\"> </td><td width=\"25%\" style=\"vertical-align: top; text-align: left;border: 0px none rgb(0, 0, 0);\"> </td></tr>";

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					var tableHtml = "<table style=\"BORDER-RIGHT: rgb(0,0,0) 0px; BORDER-TOP: rgb(0,0,0) 0px; VERTICAL-ALIGN: top; BORDER-LEFT: rgb(0,0,0) 0px; BORDER-BOTTOM: rgb(0,0,0) 0px; TEXT-ALIGN: left\" width=\"100%\" height=\"500px;\">"
							+ inner + "</table>";
					range.pasteHTML(tableHtml);

				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
					table.innerHTML = inner;
				}

				editor._toggleBorders();
			} else if (param.f_url == "10") {
				table.style.height = "100px";
				table.style.width = "100%";
				table.cellPadding = "3";
				table.cellSpacing = "0";
				var inner = " <tr><td class=\"portlet_heading\" style=\"vertical-align: top; text-align: left;\">Add Header</td></tr><tr><td style=\"vertical-align: top;text-align: left;\" class=\"portlet_content\"><br/></td></tr>";
				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					var tableHtml = "<table width=\"100%\" height=\"100px;\" cellpadding=3 cellspacing=0>"
							+ inner + "</table>";
					range.pasteHTML(tableHtml);
				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
					table.innerHTML = inner;
				}
			} else if (param.f_url == "11") {
				table.className = "panel_gradient_top"
				var tr = doc.createElement("tr");
				tr.style.verticalAlign = "top";
				table.appendChild(tr);

				var td = doc.createElement("td");
				td.style.padding = "3px";
				(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
				tr.appendChild(td);

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					range.pasteHTML(table.outerHTML);
				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
				}
			} else if (param.f_url == "12") {
				table.className = "panel_gradient_bottom"
				var tr = doc.createElement("tr");
				tr.style.verticalAlign = "top";
				table.appendChild(tr);

				var td = doc.createElement("td");
				td.style.padding = "3px";
				(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
				tr.appendChild(td);

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					range.pasteHTML(table.outerHTML);
				} else {
					// insert the table
					editor.insertNodeAtSelection(table);
				}
			} else if (param.f_url == "13") {
				table.className = "panel_gradient_yellow_top"
				var tr = doc.createElement("tr");
				tr.style.verticalAlign = "top";
				table.appendChild(tr);

				var td = doc.createElement("td");
				td.style.padding = "3px";
				(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
				tr.appendChild(td);

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					range.pasteHTML(table.outerHTML);
				} else {
					editor.insertNodeAtSelection(table);
				}
			} else if (param.f_url == "14") {
				table.className = "panel_gradient_yellow_bottom"
				var tr = doc.createElement("tr");
				tr.style.verticalAlign = "top";
				table.appendChild(tr);
				var br1 = doc.createElement("br");

				var td = doc.createElement("td");
				td.style.padding = "3px";
				(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
				tr.appendChild(td);

				if (HTMLArea.is_ie) {
					sel = editor._getSelection();
					range = editor._createRange(sel);
					range.pasteHTML(table.outerHTML);
				} else {
					editor.insertNodeAtSelection(table);
				}
			}

			return true;

		}, outparam, 300, 400);
};

//Called when the user clicks on "InsertWiki" button. 
HTMLArea.prototype._insertWiki = function() {
	var sel = this._getSelection();
	var range = this._createRange(sel);
	var editor = this; // for nested functions
	editor.focusEditor();
	var doc = editor._doc;
	var outparam = null;
	var wiki = doc.createElement("div");
	wiki.setAttribute("class", "wiki");
	wiki.innerHTML = "Enter wiki text here"

	if (HTMLArea.is_ie) {
		range.pasteHTML(wiki.outerHTML + "<br/>");
		editor.focusEditor();
	} else {
		editor.insertNodeAtSelection(wiki);
		doc.createElement("br");
		//wiki.parentNode.insertBefore(doc.createElement("br"), wiki.nextSibling);
		editor.focusEditor();

	}

	return true;

};

HTMLArea.prototype.getOuterHTML = function() {
	var table = this.getClosest("table");
	var attrs = table.attributes;
	var str = "<" + table.tagName;
	for ( var i = 0; i < attrs.length; i++)
		str += " " + attrs[i].name + "=\"" + attrs[i].value + "\"";

	return str + ">" + table.innerHTML + "</" + table.tagName + ">";
};

HTMLArea.prototype._insertTable = function() {

	var sel = this._getSelection();
	var range = this._createRange(sel);
	var editor = this;
	this._popupDialog("insert_table.jsp", function(param) {
		if (!param) {
			return false;
		}
		var doc = editor._doc;
		var table = doc.createElement("table");
		table.style.borderCollapse = "collapse";
		var borderWidth = 1;
		for ( var field in param) {
			var value = param[field];
			if (!value) {
				continue;
			}
			switch (field) {
			case "f_width":
				table.style.width = value + param["f_unit"];
				break;
			case "f_align":
				table.align = value;
				break;
			case "f_border":
				borderWidth = value;
				if (value == "0") {
					table.style.border = parseInt(value) + "px none #000";
				} else {
					table.style.border = parseInt(value) + "px solid #000";
				}
				break;
			case "f_spacing":
				table.cellSpacing = parseInt(value);
				break;
			case "f_padding":
				table.cellPadding = parseInt(value);
				break;
			}
		}
		var cellwidth = 0;
		if (param["f_fixed"] == true)
			cellwidth = Math.floor(100 / parseInt(param.f_cols));
		var tbody = doc.createElement("tbody");
		table.appendChild(tbody);
		
		for ( var i = 0; i < param["f_rows"]; ++i) {
			var tr = doc.createElement("tr");
			tbody.appendChild(tr);
			for ( var j = 0; j < param["f_cols"]; ++j) {
				var td = doc.createElement("td");
				if (param["f_header"] == true) {
					if (i == 0) {
						tr.style.backgroundColor = "#cccccc";
						var header = "Header" + (j + 1);
						td.appendChild(doc.createTextNode(header));
					}
				}
				
				if (param["f_border"] == "0") {
					td.style.border = parseInt(borderWidth) + "px none #000";
				} else {
					td.style.border = parseInt(borderWidth) + "px solid #000";
				}

				//td.style.border=table.style.border;
			if (cellwidth)
				td.style.width = cellwidth + "%";
			tr.appendChild(td);
			(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
		}
	}
	if (HTMLArea.is_ie) {
		range.pasteHTML(table.outerHTML);
	} else {
		editor.insertNodeAtSelection(table);
	}
	return true;
}, null, 360, 500);
};

/***************************************************
 *  Category: EVENT HANDLERS
 ***************************************************/

// el is reference to the SELECT object
// txt is the name of the select field, as in config.toolbar
HTMLArea.prototype._comboSelected = function(el, txt) {
	this.focusEditor();
	try {
		var value = el.options[el.selectedIndex].value;
		switch (txt) {
		case "fontname":
		case "fontsize":
			this.execCommand(txt, false, value);
			break;
		case "formatblock":
			(HTMLArea.is_ie) && (value = "<" + value + ">");
			this.execCommand(txt, false, value);
			break;
		default:
			// try to look it up in the registered dropdowns

			var dropdown = this.config.customSelects[txt];
			if (typeof dropdown != "undefined") {
				dropdown.action(this);
			} else {
				alert("FIXME: combo box " + txt + " not implemented");
			}
		}
	} catch (err) {
	}
};

// the execCommand function (intercepts some commands and replaces them with
// our own implementation)
HTMLArea.prototype.execCommand = function(cmdID, UI, param) {

	var editor = this; // for nested functions
	try {
		// useCSS deprecated & replaced by styleWithCSS
		this._doc.execCommand('useCSS', false, true); //switch useCSS off (true=off)
		this._doc.execCommand('styleWithCSS', false, false); //switch styleWithCSS off     
	} catch (ex) {
	}
	this.focusEditor();
	cmdID = cmdID.toLowerCase();
	switch (cmdID) {
	case "htmlmode":
		this.setMode();
		break;
	case "hilitecolor":
		 cmdID = "backcolor";
		(HTMLArea.is_firefox) && (cmdID = "hilitecolor");
		editor._doc.execCommand("styleWithCSS",false,true);
		var bgcolor = this._doc.queryCommandValue(cmdID);
		editor._doc.execCommand("styleWithCSS", false,false);
		this._popupDialog("select_color.jsp",
				function(color) {
					if (color) 
						{ // selection not canceled
							editor._doc.execCommand("styleWithCSS",false,true);
							editor._doc.execCommand(cmdID, false, "#" + color);
							editor._doc.execCommand("styleWithCSS", false,false);
						}
			}, HTMLArea._colorToRgb(bgcolor), 400,
				400);
		break;
	case "forecolor":
		this._popupDialog("select_color.jsp",
				function(color) {
					if (color) { // selection not canceled
					editor._doc.execCommand(cmdID, false, "#" + color);
				}
			}, HTMLArea._colorToRgb(this._doc.queryCommandValue(cmdID)), 400,
				400);
		break;
	case "createlink":
		this._createLink();
		break;
	case "popupeditor":
		// this object will be passed to the newly opened window
		HTMLArea._object = this;
		var width = screen.availWidth;
		var height = screen.availHeight;
		var destination = "fullscreen.html";

		if (HTMLArea.is_ie) {
			//if (confirm(HTMLArea.I18N.msg["IE-sucks-full-screen"]))
			{

				fullScreenWin = window.open(this.popupURL(destination),
						"ha_fullscreen",
						"toolbar=no,location=no,directories=no,status=no,menubar=no,"
								+ "scrollbars=no,resizable=yes,width=" + width
								+ ",height=" + height);
			}
		} else {

			fullScreenWin = window.open(this.popupURL(destination),
					"ha_fullscreen",
					"toolbar=no,menubar=no,personalbar=no,width=" + width
							+ ",height=" + height + ","
							+ "scrollbars=no,resizable=yes");
		}
		setTimeout("checkFullScreenWin()", 500);
		break;
	case "undo":
	case "redo":
		if (this._customUndo)
			this[cmdID]();
		else
			this._doc.execCommand(cmdID, UI, param);
		break;
	case "inserttable":
		this._insertTable();
		break;
	case "insertimage":
		this._insertImage();
		break;
	case "insertblogimage":
		this._insertBlogImage();
		break;
	case "insertsmiley":
		this._insertSmiley();
		break;
	case "about":
		this._popupDialog("about.html", null, this);
		break;
	case "showhelp":
		var actualUrl = "";
		if (window.opener) {
			actualUrl = window.opener.helpUrl;
		} else {
			actualUrl = helpUrl;
		}
		winPopupWindow = window.open(actualUrl, "Help",
				"height=700,width=900,resizable=yes,scrollbars=yes");
		setTimeout("focusHelpWindow()", 500);
		break;

	case "killword":
		this._wordClean();
		break;

	case "cut":
	case "copy":
	case "paste":

		try {

			this._doc.execCommand(cmdID, UI, param);
		} catch (e) {

			if (HTMLArea.is_gecko) {
				if (confirm("Unprivileged scripts cannot access Cut/Copy/Paste programatically "
						+ "for security reasons.  Click OK to see a technical note at mozilla.org "
						+ "which shows you how to allow a script to access the clipboard."))
					window
							.open("http://mozilla.org/editor/midasdemo/securityprefs.html");
			}
		}

		break;
	case "lefttoright":
	case "righttoleft":
		var dir = (cmdID == "righttoleft") ? "rtl" : "ltr";
		var el = this.getParentElement();
		while (el && !HTMLArea.isBlockElement(el))
			el = el.parentNode;
		if (el) {
			if (el.style.direction == dir)
				el.style.direction = "";
			else
				el.style.direction = dir;
		}
		break;
	default:
		this._doc.execCommand(cmdID, UI, param);
	}
	this.updateToolbar();
	return false;
};

/** A generic event handler for things that happen in the IFRAME's document.
 * This function also handles key bindings. */
HTMLArea.prototype._editorEvent = function(ev) {
	var editor = this;

	var keyEvent = (is_chrome && ev.type == "keydown")
			|| (HTMLArea.is_ie && ev.type == "keydown")
			|| (!HTMLArea.is_ie && ev.type == "keypress");
	//call events of textarea
	if (typeof editor._textArea['on' + ev.type] == "function") {
		editor._textArea['on' + ev.type]();
	}

	if (keyEvent) {
		for ( var i in editor.plugins) {
			var plugin = editor.plugins[i].instance;
			if (typeof plugin.onKeyPress == "function")
				plugin.onKeyPress(ev);
		}
	}
	if (ev.altKey) {
		return true;
	}

	if (keyEvent && ev.ctrlKey) {
		var sel = null;
		var range = null;
		var key = String.fromCharCode(
				HTMLArea.is_ie || is_chrome ? ev.keyCode : ev.charCode)
				.toLowerCase();
		var keycode = HTMLArea.is_ie ? ev.keyCode : ev.charCode;
		var cmd = null;
		var value = null;
		if (ev.keyCode < 112) {
			switch (key) {
			case 'a':
				if (!HTMLArea.is_ie) {
					// KEY select all
					sel = this._getSelection();
					sel.removeAllRanges();
					range = this._createRange();
					range.selectNodeContents(this._doc.body);
					sel.addRange(range);
					HTMLArea._stopEvent(ev);
				}
				break;

			// simple key commands follow

			case 'b':
				cmd = "bold";
				break;
			case 'i':
				cmd = "italic";
				break;
			case 'u':
				cmd = "underline";
				break;

			case 'l':
				cmd = "justifyleft";
				break;
			case 'e':
				cmd = "justifycenter";
				break;
			case 'r':
				cmd = "justifyright";
				break;
			case 'j':
				cmd = "justifyfull";
				break;
			case 'z':
				cmd = "undo";
				break;
			case 'y':
				cmd = "redo";
				break;
			case 'f':
				var tbo = new FindReplace(editor);
				tbo.buttonPress(editor);
				HTMLArea._stopEvent(ev);
				break;
			case 'h':
				var tbo = new FindReplace(editor);
				tbo.buttonPress(editor);
				HTMLArea._stopEvent(ev);
				break;
			case 'k':
				if (collabapplication == "wiki")
					editor._createLink();
				else
					editor._createBlogLink();

				HTMLArea._stopEvent(ev);
				break;
			case 'g':
				if (collabapplication == "wiki")
					editor._insertImage();
				else
					editor._insertBlogImage();
				HTMLArea._stopEvent(ev);
				break;
			case 'p':

				if (window.opener) {
					if (isGuest()
							&& document.getElementById("validate_guest_value").value == "true") {
						window.opener.showCaptchaForGuestInEdit();
					} else {
						window.opener.savePage();
					}
					//window.opener.savePage();
				} else {
					if (isGuest()
							&& document.getElementById("validate_guest_value").value == "true") {
						showCaptchaForGuestInEdit();
					} else {
						savePage();
					}
				}
				//alert(1)
				HTMLArea._stopEvent(ev);
				//alert(2)
				break;
			case 'd':
				if (window.opener)
					window.opener.previewPage();
				else
					previewPage();
				HTMLArea._stopEvent(ev);
				break;
			case 's':
				if (window.opener)
					window.opener.saveDraft();
				else
					saveDraft();
				HTMLArea._stopEvent(ev);
				break;
			case 'v':
				//	cmd = "paste"; break;
				if (HTMLArea.is_ie || editor.config.htmlareaPaste) {
					cmd = "paste";
				}
				this.execCommand(cmd, false, value);
				HTMLArea._stopEvent(ev);
				cmd = null;
				break;

			case '0':
				cmd = "killword";
				break;

			// headings
			case '1':
			case '2':
			case '3':
			case '4':
			case '5':
			case '6':
				cmd = "formatblock";
				value = "h" + key;
				if (HTMLArea.is_ie) {
					value = "<" + value + ">";
				}
				break;
			}
			if (keycode == 32) {
				this.execCommand("removeformat");
				HTMLArea._stopEvent(ev);

			}
		} else {
			switch (ev.keyCode) {
			case 122:
				if (window.opener) {
					window.close();
				} else {
					HTMLArea._object = this;
					var width = screen.availWidth;
					var height = screen.availHeight;
					if (HTMLArea.is_ie) {
						//if (confirm(HTMLArea.I18N.msg["IE-sucks-full-screen"]))
						{

							fullScreenWin = window
									.open(
											this.popupURL("fullscreen.html"),
											"ha_fullscreen",
											"toolbar=no,location=no,directories=no,status=no,menubar=no,"
													+ "scrollbars=no,resizable=yes,width="
													+ width + ",height="
													+ height);
						}
					} else {
						fullScreenWin = window.open(this
								.popupURL("fullscreen.html"), "ha_fullscreen",
								"toolbar=no,menubar=no,personalbar=no,width="
										+ width + ",height=" + height + ","
										+ "scrollbars=no,resizable=yes");
					}
				}
				setTimeout("checkFullScreenWin()", 500);
				HTMLArea._stopEvent(ev);
				break;

			}
		}

		if (cmd) {
			// execute simple command
			this.execCommand(cmd, false, value);
			HTMLArea._stopEvent(ev);
		}

	} else if (keyEvent) {
		//alert(keyEvent)
		if (!is_chrome && !is_safari) {
			switch (ev.keyCode) {
			case 112:
				var actualUrl = "";
				if (window.opener) {
					actualUrl = window.opener.helpUrl;
				} else {
					actualUrl = helpUrl;
				}
				winPopupWindow = window.open(actualUrl, "Help",
						"height=700,width=900,resizable=yes,scrollbars=yes");
				setTimeout("focusHelpWindow()", 500);
				HTMLArea._stopEvent(ev);
				break;
			case 118:
				editor._spellCheck();
				HTMLArea._stopEvent(ev);
				break;
			case 9:
				if (HTMLArea.is_ie) {
					if (editor.ie_tabPressed(ev.shiftKey))
						HTMLArea._stopEvent(ev);
				} else {
					if (editor.moz_tabPressed(ev.shiftKey))
						HTMLArea._stopEvent(ev);
				}
				break;
			}
		} else {
			switch (ev.keyCode) {
			case 9:
				var parents = editor.getAncestorsHash();
				if (parents.table && parents.td) {
					if (editor.moz_tabPressed(ev.shiftKey))
						HTMLArea._stopEvent(ev);
				} else if (parents.ul && parents.li) {
					editor.execCommand(ev.shiftKey ? "outdent" : "indent",
							false, null);
				}
				break;
			}
		}
	} else {
		try {
			if (typeof et_m_cancelMenus != 'undefined') {
				et_m_cancelMenus();
			}
		} catch (err) {
		}
	}

	/*
	else if (keyEvent) {
		// other keys here
		switch (ev.keyCode) {
		    case 13: // KEY enter
			// if (HTMLArea.is_ie) {
			this.insertHTML("<br />");
			HTMLArea._stopEvent(ev);
			// }
			break;
		}
	}
	 */
	// update the toolbar state after some time
	if (editor._timerToolbar) {
		clearTimeout(editor._timerToolbar);
	}
	editor._timerToolbar = setTimeout( function() {
		editor.updateToolbar();
		editor._timerToolbar = null;
	}, 50);
};
HTMLArea.prototype.ie_tabPressed = function(shift) {
	var parents = this.getAncestorsHash();
	if (parents.table && parents.td) {
		var lastTR = parents.tr;
		var range = this._createRange(this._getSelection());
		range.moveToElementText(parents.td);
		if (shift)
			range.moveStart("character", -1);
		else
			range.moveEnd("character", 1);
		range.collapse(shift);
		range.select();
		parents = this.getAncestorsHash();
		if (parents.table && parents.td) {
			this.selectNodeContents(parents.td);
		} else {
			var editor = this;
			var otr = lastTR.cloneNode(true);
			editor.clearRow(otr);
			var insertedRow = lastTR.parentNode.insertBefore(otr,
					lastTR.nextSibling);
			editor.forceRedraw();
			this.selectNodeContents(insertedRow.firstChild);
			editor.focusEditor();

		}
	} else
		this.execCommand(shift ? "outdent" : "indent", false, null);
	return true;
};

HTMLArea.prototype.moz_tabPressed = function(shift) {

	var editor = this;
	setTimeout( function() {

		var parents = editor.getAncestorsHash();
		if (parents.table && parents.td) {
			if (shift) {
				var tr = editor.getClosest("tr");
				var prevTR = tr.previousSibling;
				if (prevTR && prevTR.nodeName != "TR") {
					prevTR = prevTR.previousSibling;
				}
				var td = editor.getClosest("td");
				var prevTD = td.previousSibling;

				if (prevTD && prevTD.nodeName != "TD")
					prevTD = prevTD.previousSibling;

				if (prevTR == null && prevTD == null) {

				} else if (prevTR != null && prevTD != null) {

					editor.selectNodeContents(prevTD);
				} else if (prevTR != null && prevTD == null) {
					var td;
					var children = prevTR.childNodes;

					for ( var i = children.length - 1; i >= 0; i--) {
						if (children[i].nodeName == "TD") {
							td = children[i];
							break;
						}
					}
					editor.selectNodeContents(td);
				} else if (nextTR == null && prevTD != null) {
					editor.selectNodeContents(prevTD);
				}
			} else {
				var tr = editor.getClosest("tr");
				var nextTR = tr.nextSibling;
				if (nextTR && nextTR.nodeName != "TR") {
					nextTR = nextTR.nextSibling;
				}
				var td = editor.getClosest("td");
				var nextTD = td.nextSibling;
				if (nextTD && nextTD.nodeName != "TD")
					nextTD = nextTD.nextSibling;

				if (nextTR == null && nextTD == null) {
					var otr = tr.cloneNode(true);
					editor.clearRow(otr);
					var insertedRow = tr.parentNode.insertBefore(otr,
							tr.nextSibling);
					editor.forceRedraw();
					editor.focusEditor();
				} else if (nextTR != null && nextTD != null) {

					editor.selectNodeContents(nextTD);
				} else if (nextTR != null && nextTD == null) {
					var td;
					var children = nextTR.childNodes;
					for ( var i = 0; i < children.length; i++) {
						if (children[i].nodeName == "TD") {
							td = children[i];
							break;
						}
					}
					editor.selectNodeContents(td);
				} else if (nextTR == null && nextTD != null) {
					editor.selectNodeContents(nextTD);
				}
			}

		} else {
			editor.execCommand(shift ? "outdent" : "indent", false, null);
		}
	}, 20);
	return false;
};

// retrieves the closest element having the specified tagName in the list of
// ancestors of the current selection/caret.
HTMLArea.prototype.getClosest = function(tagName) {
	var editor = this;
	editor.focusEditor();
	var ancestors = editor.getAllAncestors();
	var ret = null;
	tagName = ("" + tagName).toLowerCase();
	for ( var i in ancestors) {
		var el = ancestors[i];

		if (el.tagName.toLowerCase() == tagName) {
			ret = el;
			break;
		}
	}
	return ret;
};

HTMLArea.prototype.clearRow = function(tr) {
	var mozbr = HTMLArea.is_gecko ? "<br />" : "";
	var tds = tr.getElementsByTagName("td");
	for ( var i = tds.length; --i >= 0;) {
		var td = tds[i];
		td.rowSpan = 1;
		td.innerHTML = mozbr;
	}
};

HTMLArea.prototype.getAncestorsHash = function() {
	var p = this.getAllAncestors(), el, i, tn, pnodes = {};
	try {
		for (i = 0; i < p.length; ++i) {
			el = p[i];
			tn = el.tagName.toLowerCase();

			if (!pnodes[tn])
				pnodes[tn] = el;
		}
	} catch (e) {
	}
	;
	return pnodes;
};

HTMLArea.prototype.getHTMLWithoutIndent = function() {
	switch (this._editMode) {
	case "wysiwyg":
		if (!this.config.fullPage) {
			//var val  = HTMLArea.getHTML(this._doc.body, true, this);
			var val = this._doc.body.innerHTML;

			return val;
		} else {
			return this.doctype + "\n"
					+ HTMLArea.getHTML(this._doc.documentElement, true, this);
		}
	case "textmode":
		var val = this._textArea.value;
		if (HTMLArea.checkSupportedBrowser()) {
			//val = CodeFormatter.Format(val);
		}
		return val;
	default:
		alert("Mode <" + mode + "> not defined!");
	}

	return false;
};

// retrieve the HTML
HTMLArea.prototype.getHTML = function() {

	switch (this._editMode) {
	case "wysiwyg":
		if (!this.config.fullPage) {
			//var val  = HTMLArea.getHTML(this._doc.body, true, this);

			var val = this._doc.body.innerHTML;
			val = CodeFormatter.Format(val);
			return val;
		} else {
			return this.doctype + "\n"
					+ HTMLArea.getHTML(this._doc.documentElement, true, this);
		}
	case "textmode":
		var val = this._textArea.value;
		if (HTMLArea.checkSupportedBrowser()) {
			val = CodeFormatter.Format(val);
		}
		return val;
	default:
		alert("Mode <" + mode + "> not defined!");
	}
	return false;
};

// retrieve the HTML (fastest version, but uses innerHTML)
HTMLArea.prototype.getInnerHTML = function() {
	switch (this._editMode) {
	case "wysiwyg":
		if (!this.config.fullPage) {

			if (this._doc && this._doc.body)
				return this._doc.body.innerHTML;
		} else {

			if (this._doc)
				return (this.doctype + "\n" + this._doc.documentElement.innerHTML);
		}
	case "textmode":
		return this._textArea.value;
	default:
		alert("Mode <" + mode + "> not defined!");
	}
	return false;
};

// completely change the HTML inside
HTMLArea.prototype.setHTML = function(html) {
	try {
		switch (this._editMode) {
		case "wysiwyg":
			if (!this.config.fullPage)
				this._doc.body.innerHTML = html;
			else
				// this._doc.documentElement.innerHTML = html;
				this._doc.body.innerHTML = html;
			break;
		case "textmode":
			this._textArea.value = html;
			break;
		default:
			alert("Mode <" + mode + "> not defined!");
		}
	} catch (err) {
		return true;
	}
	return false;
};

// sets the given doctype (useful when config.fullPage is true)
HTMLArea.prototype.setDoctype = function(doctype) {
	this.doctype = doctype;
};

/***************************************************
 *  Category: UTILITY FUNCTIONS
 ***************************************************/

// browser identification
HTMLArea.agt = navigator.userAgent.toLowerCase();
HTMLArea.is_ie = ((HTMLArea.agt.indexOf("msie") != -1) && (HTMLArea.agt
		.indexOf("opera") == -1));
HTMLArea.is_opera = (HTMLArea.agt.indexOf("opera") != -1);
HTMLArea.is_mac = (HTMLArea.agt.indexOf("mac") != -1);
HTMLArea.is_mac_ie = (HTMLArea.is_ie && HTMLArea.is_mac);
HTMLArea.is_win_ie = (HTMLArea.is_ie && !HTMLArea.is_mac);
HTMLArea.is_gecko = (navigator.product == "Gecko");
HTMLArea.is_ie7 = is_ie7;

// variable used to pass the object to the popup editor window.
HTMLArea._object = null;

// function that returns a clone of the given object
HTMLArea.cloneObject = function(obj) {
	var newObj = new Object;

	// check for array objects
	if (obj.constructor.toString().indexOf("function Array(") == 1) {
		newObj = obj.constructor();
	}

	// check for function objects (as usual, IE is fucked up)
	if (obj.constructor.toString().indexOf("function Function(") == 1) {
		newObj = obj; // just copy reference to it
	} else
		for ( var n in obj) {
			var node = obj[n];
			if (node == null)
				continue;
			if (typeof node == 'object') {
				newObj[n] = HTMLArea.cloneObject(node);
			} else {
				newObj[n] = node;
			}
		}

	return newObj;
};

// FIXME!!! this should return false for IE < 5.5
HTMLArea.checkSupportedBrowser = function() {

	if (checkSupportedBrowser_val == null) {
		if (E_MODE_TEXT) {
			checkSupportedBrowser_val = false;
			return false;
		}
		var detect = navigator.userAgent.toLowerCase();
		if (detect.indexOf("safari") != -1) {
			var version = parseInt(BrowserDetect.version);

			checkSupportedBrowser_val = true;
			return checkSupportedBrowser_val;
		}
		if (HTMLArea.is_gecko) {
			if (navigator.productSub < 20021201) {
				alert("You need at least Mozilla-1.3 Alpha.\n"
						+ "Sorry, your Gecko is not supported.");
				checkSupportedBrowser_val = false;
				return false;
			}
			if (navigator.productSub < 20030210) {
				alert("Mozilla < 1.3 Beta is not supported!\n"
						+ "I'll try, though, but it might not work.");
				checkSupportedBrowser_val = false;
				return false;
			}
		}
		checkSupportedBrowser_val = (HTMLArea.is_gecko || HTMLArea.is_ie);
		return checkSupportedBrowser_val;
	} else {
		return checkSupportedBrowser_val;
	}
};

// selection & ranges

// returns the current selection object
HTMLArea.prototype._getSelection = function() {
	if (HTMLArea.checkSupportedBrowser()) {
		if (HTMLArea.is_ie) {
			return this._doc.selection;
		} else {
			return this._iframe.contentWindow.getSelection();
		}
	}
};

// returns a range for the current selection
HTMLArea.prototype._createRange = function(sel) {
	try {
		if (HTMLArea.is_ie) {

			return sel.createRange();
		} else {
			this.focusEditor();
			if (typeof sel != "undefined") {
				try {
					return sel.getRangeAt(0);
				} catch (e) {
					return this._doc.createRange();
				}
			} else {
				return this._doc.createRange();
			}
		}
	} catch (err) {
	}
};

HTMLArea._addEvent = function(el, evname, func) {
	if (HTMLArea.is_ie) {
		el.attachEvent("on" + evname, func);
	} else {
		el.addEventListener(evname, func, true);
	}

};

HTMLArea._addEvents = function(el, evs, func) {
	for ( var i in evs) {
		HTMLArea._addEvent(el, evs[i], func);
	}
};

HTMLArea._removeEvent = function(el, evname, func) {
	if (HTMLArea.is_ie) {
		el.detachEvent("on" + evname, func);
	} else {
		el.removeEventListener(evname, func, true);
	}
};

HTMLArea._removeEvents = function(el, evs, func) {
	for ( var i in evs) {
		HTMLArea._removeEvent(el, evs[i], func);
	}
};

HTMLArea._stopEvent = function(ev) {

	if (HTMLArea.is_ie) {
		ev.keyCode = 0;
		ev.cancelBubble = true;
		ev.returnValue = false;
	} else {
		ev.preventDefault();
		ev.stopPropagation();
	}
};

HTMLArea._stopEventss = function(ev) {

	if (HTMLArea.is_ie) {
		ev.keyCode = 0;
		ev.cancelBubble = true;
		ev.returnValue = false;

	} else {
		ev.preventDefault();
		ev.stopPropagation();
	}
};

HTMLArea._removeClass = function(el, className) {
	if (!(el && el.className)) {
		return;
	}
	var cls = el.className.split(" ");
	var ar = new Array();
	for ( var i = cls.length; i > 0;) {
		if (cls[--i] != className) {
			ar[ar.length] = cls[i];
		}
	}
	el.className = ar.join(" ");
};

HTMLArea._addClass = function(el, className) {
	// remove the class first, if already there
	HTMLArea._removeClass(el, className);
	el.className += " " + className;
};

HTMLArea._hasClass = function(el, className) {
	if (!(el && el.className)) {
		return false;
	}
	var cls = el.className.split(" ");
	for ( var i = cls.length; i > 0;) {
		if (cls[--i] == className) {
			return true;
		}
	}
	return false;
};

HTMLArea.isBlockElement = function(el) {
	try {
		var blockTags = " body form textarea fieldset ul ol dl li div "
				+ "p h1 h2 h3 h4 h5 h6 quote pre table thead "
				+ "tbody tfoot tr td iframe address ";
		return (blockTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
	} catch (err) {
	}
	return false;
};

HTMLArea.needsClosingTag = function(el) {
	var closingTags = " head script style div span tr td tbody table em strong font a title ";
	return (closingTags.indexOf(" " + el.tagName.toLowerCase() + " ") != -1);
};

// performs HTML encoding of some given string
HTMLArea.htmlEncode = function(str) {
	// we don't need regexp for that, but.. so be it for now.
	str = str.replace(/&/ig, "&amp;");
	str = str.replace(/</ig, "&lt;");
	str = str.replace(/>/ig, "&gt;");
	str = str.replace(/\x22/ig, "&quot;");
	// \x22 means '"' -- we use hex reprezentation so that we don't disturb
	// JS compressors (well, at least mine fails.. ;)
	return str;
};

//performs HTML encoding of some given string
HTMLArea.htmlEncode2 = function(str) {
	try {
		var tempstr = str.replace(/^\s+/, '').replace(/\s+$/, '');
		if (tempstr == "")
			return str;
		// we don't need regexp for that, but.. so be it for now.
		str = str.replace(/&/ig, "&amp;");
		str = str.replace(/</ig, "&lt;");
		str = str.replace(/>/ig, "&gt;");
		str = str.replace(/\s\s/ig, "&nbsp;&nbsp;");
		str = str.replace(/\x22/ig, "&quot;");
		// \x22 means '"' -- we use hex reprezentation so that we don't disturb
		// JS compressors (well, at least mine fails.. ;)
	} catch (err) {
	}
	return str;
};

/*
 // Retrieves the HTML code from the given node.	 This is a replacement for
 // getting innerHTML, using standard DOM calls.
 HTMLArea.getHTML = function(root, outputRoot, editor) {
 var html =  new Array();
 switch (root.nodeType) {
 case 1: // Node.ELEMENT_NODE
 case 11: // Node.DOCUMENT_FRAGMENT_NODE
 var closed;
 var i;
 var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';
 if ( root_tag == "head") {

 break;
 } else if (outputRoot) {
 closed = (!(root.hasChildNodes() || HTMLArea.needsClosingTag(root)));
 html=null;
 html =  new Array();
 var tName = root.tagName.toLowerCase();
 if( tName == "script" || tName=="body" || tName=="meta" || tName=="iframe" 
 || tName=="frameset"  || tName=="frame" || tName=="textarea" || tName=="link" 
 || tName=="html" || tName=="formulas" || tName=="f" || tName=="lock" 
 || tName=="path" || tName=="shape" || tName=="stroke"
 || tName=="fill" || tName=="shapetype" || tName=="imagedata"
 || tName=="borderbottom" ||  tName=="borderright" ||  tName=="bordertop" ||  tName=="borderleft")
 {
 break;
 }
 html.push("<" + root.tagName.toLowerCase());
 var attrs = root.attributes;
 for (i = 0; i < attrs.length; ++i) {
 var a = attrs.item(i);
 if (!a.specified) {
 continue;
 }
 var name = a.nodeName.toLowerCase();
 if (/_moz|contenteditable|_msh|onclick|onmouseover|onmouseout|onload|onunload|onchange|onsubmit|onreset|onselect|onblur|onfocus|onkeydown|onkeypress|onkeyup|onmousemove|ondblclick|onmousedown|onbeforeunload|onstop|onselectstart|onselectionchange|onscroll|onrowsinserted|onmoveend|onmovestart|onmove|onmousewheel|onmouseup|onmouseleave|onfinish|ondragover|ondrag|ondragend|ondragenter|ondragexit|onresize|oncontextmenu|onerror|oninput|onpopupShowing|onpopupHiding|onpopupShown|onclose|onbroadcast|overflow|oncommand/.test(name)) {
 // avoid certain attributes
 continue;
 }
 var value;
 if (name != "style") {
 // IE5.5 reports 25 when cellSpacing is
 // 1; other values might be doomed too.
 // For this reason we extract the
 // values directly from the root node.
 // I'm starting to HATE JavaScript
 // development.  Browser differences
 // suck.
 //
 // Using Gecko the values of href and src are converted to absolute links
 // unless we get them using nodeValue()
 if (typeof root[a.nodeName] != "undefined" && name != "href" && name != "src") {
 value = root[a.nodeName];
 } else {
 value = a.nodeValue;
 // IE seems not willing to return the original values - it converts to absolute
 // links using a.nodeValue, a.value, a.stringValue, root.getAttribute("href")
 // So we have to strip the baseurl manually -/
 if (HTMLArea.is_ie && (name == "href" || name == "src")) {
 value = editor.stripBaseURL(value);
 }
 }
 } else { // IE fails to put style in attributes list
 // FIXME: cssText reported by IE is UPPERCASE
 value = root.style.cssText;
 }
 if (/(_moz|^$)/.test(value)) {
 // Mozilla reports some special tags
 // here; we don't need them.
 continue;
 }
 html.push(" " + name + '="' + value + '"');
 }
 html.push(closed ? " />" : ">");
 }
 for (i = root.firstChild; i; i = i.nextSibling) {
 html.push(HTMLArea.getHTML(i, true, editor));
 }
 if (outputRoot && !closed) {
 html.push("</" + root.tagName.toLowerCase() + ">");
 }
 break;
 case 3: // Node.TEXT_NODE
 // If a text node is alone in an element and all spaces, replace it with an non breaking one
 // This partially undoes the damage done by moz, which translates '&nbsp;'s into spaces in the data element
 if ( !root.previousSibling && !root.nextSibling && root.data.match(/^\s*$/i) ) 
 {
 html =  null;
 html =  new Array();
 html.push('&nbsp;');
 }
 else 
 {
 html =  null;
 html =  new Array();
 if(HTMLArea.is_gecko)
 {
 html.push(HTMLArea.htmlEncode2(root.data));
 }
 else
 {
 html.push(HTMLArea.htmlEncode(root.data));
 }
 }
 break;
 case 8: // Node.COMMENT_NODE
 html =  null;
 html =  new Array();
 html.push("<!--" + root.data + "-->");
 break;		// skip comments, for now.
 }
 return html.join("");
 };
 */
if (!is_safari) {
	HTMLArea.RegExpCache = [
			/*00*/new RegExp().compile(/<\s*\/?([^\s\/>]+)[\s*\/>]/gi),//lowercase tags
			/*01*/
			new RegExp().compile(/(\S*\s*=\s*)?_moz[^=>]*(=\s*[^>]*)?/gi),//strip _moz attributes
			/*02*/
			new RegExp()
					.compile(/\s*=\s*(([^'"][^>\s]*)([>\s])|"([^"]+)"|'([^']+)')/g),// find attributes
			/*03*/
			new RegExp().compile(/\/>/g),//strip singlet terminators
			/*04*/
			// new RegExp().compile(/<(br|hr|img|input|link|meta|param|embed)([^>]*)>/g),//terminate singlet tags
			/*04*/new RegExp()
					.compile(/<(br|hr|img|input|link|meta|param|embed|area)((\s*\S*="[^"]*")*)>/g),//terminate singlet tags
			/*05*/
			new RegExp()
					.compile(/(checked|compact|declare|defer|disabled|ismap|multiple|no(href|resize|shade|wrap)|readonly|selected)([\s>])/gi),//expand singlet attributes
			/*06*/
			new RegExp().compile(/(="[^']*)'([^'"]*")/),//check quote nesting
			/*07*/
			new RegExp().compile(/&(?=[^<]*>)/g),//expand query ampersands
			/*08*/
			new RegExp().compile(/<\s+/g),//strip tagstart whitespace
			/*09*/
			new RegExp().compile(/\s+(\/)?>/g),//trim whitespace
			/*10*/
			new RegExp().compile(/\s{2,}/g),//trim extra whitespace
			/*11*/
			new RegExp().compile(/\s+([^=\s]+)(="[^"]+")/g),// lowercase attribute names
			/*12*/
			new RegExp()
					.compile(/(\S*\s*=\s*)?contenteditable[^=>]*(=\s*[^>\s\/]*)?/gi),//strip contenteditable
			/*13*/
			new RegExp().compile(/((href|src)=")([^\s]*)"/g), //find href and src for stripBaseHref()
			/*14*/
			new RegExp()
					.compile(/<\/?(div|p|h[1-6]|table|tr|td|th|ul|ol|li|blockquote|object|br|hr|img|embed|param|pre|script|html|head|body|meta|link|title|area)[^>]*>/g),
			/*15*/new RegExp()
					.compile(/<\/(div|p|h[1-6]|table|tr|td|th|ul|ol|li|blockquote|object|html|head|body|script)( [^>]*)?>/g),//blocklevel closing tag
			/*16*/
			new RegExp()
					.compile(/<(div|p|h[1-6]|table|tr|td|th|ul|ol|li|blockquote|object|html|head|body|script)( [^>]*)?>/g),//blocklevel opening tag
			/*17*/
			new RegExp()
					.compile(/<(br|hr|img|embed|param|pre|meta|link|title|area)[^>]*>/g),//singlet tag
			/*18*/
			new RegExp()
					.compile(/(^|<\/(pre|script)>)(\s|[^\s])*?(<(pre|script)[^>]*>|$)/g),//find content NOT inside pre and script tags
			/*19*/
			new RegExp().compile(/(<pre[^>]*>)(\s|[^\s])*?(<\/pre>)/g),//find content inside pre tags
			/*20*/
			new RegExp()
					.compile(/(^|<!--(\s|\S)*?-->)((\s|\S)*?)(?=<!--(\s|\S)*?-->|$)/g),//find content NOT inside comments
			/*21*/new RegExp().compile(/\S*=""/g) //find empty attributes
	];
}
/** 
 * Cleans HTML into wellformed xhtml
 */
HTMLArea.prototype.cleanHTML = function(sHtml) {
	if (!is_safari) {
		var c = HTMLArea.RegExpCache;
		sHtml = sHtml.replace(c[0], function(str) {
			return str.toLowerCase();
		}).//lowercase tags/attribute names
				replace(c[1], ' ').//strip _moz attributes
				replace(c[12], ' ').//strip contenteditable
				replace(c[2], '="$2$4$5"$3').//add attribute quotes
				replace(c[21], ' ').//strip empty attributes
				replace(c[11], function(str, p1, p2) {
					return ' ' + p1.toLowerCase() + p2;
				}).//lowercase attribute names
				replace(c[3], '>').//strip singlet terminators
				replace(c[9], '$1>').//trim whitespace
				replace(c[5], '$1="$1"$3').//expand singlet attributes
				replace(c[4], '<$1$2 />').//terminate singlet tags
				replace(c[6], '$1$2').//check quote nesting
				//	replace(c[7], '&amp;').//expand query ampersands
				replace(c[8], '<').//strip tagstart whitespace
				replace(c[10], ' ');//trim extra whitespace

		if (HTMLArea.is_ie && c[13].test(sHtml)) {//
			sHtml = sHtml.replace(c[13],
					'$1' + this.stripBaseURL(RegExp.$3) + '"');
		}
		if (this.config.only7BitPrintablesInURLs && c[13].test(sHtml)) {
			sHtml = sHtml.replace(c[13], '$1' + RegExp.$3.replace(/([^!-~]+)/g,
					function(chr) {
						return escape(chr);
					}) + '"');
		}
	}
	return sHtml;
};

/**
 * Prettyfies html by inserting linebreaks before tags, and indenting blocklevel tags
 */
HTMLArea.indent = function(s, sindentChar) {
	if (!is_safari) {
		HTMLArea.__nindent = 0;
		HTMLArea.__sindent = "";
		HTMLArea.__sindentChar = (typeof sindentChar == "undefined") ? "  "
				: sindentChar;
		var c = HTMLArea.RegExpCache;
		if (HTMLArea.is_gecko) { //moz changes returns into <br> inside <pre> tags
			s = s.replace(c[19], function(str) {
				return str.replace(/<br \/>/g, "\n")
			});
		}
		s = s
				.replace(
						c[18],
						function(strn) { //skip pre and script tags
							strn = strn
									.replace(
											c[20],
											function(st, $1, $2, $3) { //exclude comments
												string = $3
														.replace(/[\n\r]/gi,
																" ")
														.replace(/\s+/gi, " ")
														.replace(
																c[14],
																function(str) {
																	if (str
																			.match(c[16])) {
																		var s = "\n"
																				+ HTMLArea.__sindent
																				+ str;
																		// blocklevel openingtag - increase indent
																		HTMLArea.__sindent += HTMLArea.__sindentChar;
																		++HTMLArea.__nindent;
																		return s;
																	} else if (str
																			.match(c[15])) {
																		// blocklevel closingtag - decrease indent
																		--HTMLArea.__nindent;
																		HTMLArea.__sindent = "";
																		for ( var i = HTMLArea.__nindent; i > 0; --i) {
																			HTMLArea.__sindent += HTMLArea.__sindentChar;
																		}
																		return "\n"
																				+ HTMLArea.__sindent
																				+ str;
																	} else if (str
																			.match(c[17])) {
																		// singlet tag
																		return "\n"
																				+ HTMLArea.__sindent
																				+ str;
																	}
																	return str; // this won't actually happen
																});
												return $1 + string;
											});
							return strn;
						});
	}
	if (s.charAt(0) == "\n") {
		return s.substring(1, s.length);
	}
	s = s.replace(/ *\n/g, '\n');//strip spaces at end of lines
	alert(s)
	return s;
};

HTMLArea.getHTML = function(root, outputRoot, editor) {
	var html = "";
	if (root.nodeType == 11) {//document fragment
		//we can't get innerHTML from the root (type 11) node, so we 
		//copy all the child nodes into a new div and get innerHTML from the div
		var div = document.createElement("div");
		var temp = root.insertBefore(div, root.firstChild);
		for (j = temp.nextSibling; j; j = j.nextSibling) {
			temp.appendChild(j.cloneNode(true));
		}
		html += temp.innerHTML.replace(/<[^\?!][^>]*>/gi, function(tag) {
			return editor.cleanHTML(tag)
		});

	} else {

		var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';

		if (outputRoot) { //only happens with <html> tag in fullpage mode

			html += "<" + root_tag;
			var attrs = root.attributes; // strangely, this doesn't work in moz
			for (i = 0; i < attrs.length; ++i) {
				var a = attrs.item(i);
				if (!a.specified) {
					continue;
				}
				var name = a.nodeName.toLowerCase();
				var value = a.nodeValue;
				html += " " + name + '="' + value + '"';
			}
			html += ">";
		}
		if (root_tag == "html") {
			innerhtml = editor._doc.documentElement.innerHTML;
		} else {
			innerhtml = root.innerHTML;
		}
		//pass tags to cleanHTML() one at a time
		//includes support for htmlRemoveTags config option
		/* Commented by amit because of content corruption issue 02/12/2009
		html += innerhtml.replace(/<((<[^>]*>)*|[^<>]*)*>/gi, function(tag){
			if(/^<[!\?]/.test(tag)) return tag; //skip comments and php tags
			else if(!(editor.config.htmlRemoveTags && editor.config.htmlRemoveTags.test(tag.replace(/<([^\s>\/]+)/,'$1'))))
				return editor.cleanHTML(tag);
			else return ''});
		 */
		//IE drops  all </li> tags in a list except the last one
		if (HTMLArea.is_ie) {
			html = html.replace(/<li( [^>]*)?>/g, '</li><li$1>').replace(
					/(<(ul|ol)[^>]*>)[\s\n]*<\/li>/g, '$1').replace(
					/<\/li>([\s\n]*<\/li>)+/g, '<\/li>');
		}
		if (HTMLArea.is_gecko)
			html = html.replace(/(.*)<br \/>\n$/, '$1'). //strip trailing <br> added by moz
					replace(/^\n(.*)/, '$1'); //strip leading newline added by moz
		if (outputRoot) {
			html += "</" + root_tag + ">";
		}
		html = html.replace(/<body[^>]*>/, "");
		html = html.replace(/<\/body[^>]*>/, "");
		//html = HTMLArea.indent(html);
	}
	;
	//	html = HTMLArea.htmlEncode(html);

	return html;
};

//override (hack) outwardHtml() to handle onclick suppression
HTMLArea.prototype._origOutwardHtml = HTMLArea.prototype.outwardHtml;
HTMLArea.prototype.outwardHtml = function(html) {
	html = html
			.replace(
					"onclick=\"try{if(document.designMode && document.designMode == 'on') return false;}catch(e){} window.open(",
					"onclick=\"window.open(");
	html = html
			.replace(
					"onclick=\"try{if(document.designMode &amp;&amp; document.designMode == 'on') return false;}catch(e){} window.open(",
					"onclick=\"window.open(");
	this._origOutwardHtml(html);
	return html;
};
HTMLArea.prototype.stripBaseURL = function(string) {

	if (!this.stripBase) {
		return string;
	}

	/** sanjay **/
	var baseurl = this.config.baseURL;
	if (string.indexOf("/" + appContext + "/") != -1) {
		try {
			// if domain is different don't make any changes..
			var cmDomain = document.domain;
			var prePart = string.substring(0, string.indexOf("/" + appContext
					+ "/"));
			if (prePart.trim() != "" && prePart.indexOf(cmDomain) == -1) {
				return string;
			}
		} catch (err) {
		}
		try {
			//if url is pointing to an ancher don't replace any thing.
			var tmp = string.substring(string.lastIndexOf("/") + 1);
			if (tmp.trim().charAt(0) == '#') {
				return tmp;
			}
		} catch (err) {
		}
		string = string.substring(string.indexOf("/" + appContext + "/"));
	}
	/**
	// strip to last directory in case baseurl points to a file
	baseurl = baseurl.replace(/[^\/]+$/, '');
	var basere = new RegExp(baseurl);
	string = string.replace(basere, "");

	// strip host-part of URL which is added by MSIE to links relative to server root
	baseurl = baseurl.replace(/^(https?:\/\/[^\/]+)(.*)$/, '$1');
	basere = new RegExp(baseurl);
	return string.replace(basere, "");
	 **/
	/** sanjay **/
	return string;
};

HTMLArea.prototype._toggleBorders = function() {

	tables = this._doc.getElementsByTagName('TABLE');
	if (tables.length != 0) {
		if (!this.borders) {
			name = "bordered";
			this.borders = true;
		} else {
			name = "";
			this.borders = false;
		}
		for ( var ix = 0; ix < tables.length; ix++) {

			if (this.borders) {
				//if(tables[ix].className != "")
				{

					if (tables[ix].style.borderTopWidth == "0px") {
						this._addClasses(tables[ix], 'htmtableborders');
						var trs = tables[ix].getElementsByTagName("tr");
						if (trs.length > 0) {
							for ( var ij = 0; ij < trs.length; ij++) {
								var tds = trs[ij].getElementsByTagName("td");
								if (tds.length > 0) {
									for ( var iy = 0; iy < tds.length; iy++) {
										if (tds[iy].style.borderTopWidth == "0px") {
											this._addClasses(tds[iy],
													'htmtableborders');
										}

									}
								}
							}
						}
						if (!HTMLArea.is_ie) {
							this._iframe.style.display = "block";
							this._textArea.style.display = "none";
						}
					}
				}
			} else {
				this._removeClasses(tables[ix], 'htmtableborders');
				var trs = tables[ix].getElementsByTagName("tr");
				if (trs.length > 0) {
					for ( var ij = 0; ij < trs.length; ij++) {
						var tds = trs[ij].getElementsByTagName("td");
						if (tds.length > 0) {
							for ( var iy = 0; iy < tds.length; iy++) {
								this._removeClasses(tds[iy], 'htmtableborders');
							}
						}
					}
				}

			}
		}
	}

	return true;
};

HTMLArea.prototype._removeClasses = function(el, classes) {

	if (el != null) {
		var thiers = el.className.trim().split(' ');
		var new_thiers = [];
		var ours = classes.split(' ');
		for ( var x = 0; x < thiers.length; x++) {
			var exists = false;
			for ( var i = 0; exists == false && i < ours.length; i++) {
				if (ours == thiers[x]) {
					exists = true;
				}
			}
			if (exists == false) {
				new_thiers[new_thiers.length] = thiers[x];
			}
		}

		if (new_thiers.length == 0
				&& el._stylist_usedToBe
				&& el._stylist_usedToBe.length > 0
				&& el._stylist_usedToBe[el._stylist_usedToBe.length - 1].className != null) {
			// Revert back to what we were IF the classes are identical 
			var last_el = el._stylist_usedToBe[el._stylist_usedToBe.length - 1];
			var last_classes = HTMLArea.arrayFilter(last_el.className.trim()
					.split(' '), function(c) {
				if (c == null || c.trim() == '') {
					return false;
				}
				return true;
			});

			if ((new_thiers.length == 0)
					|| (HTMLArea.arrayContainsArray(new_thiers, last_classes) && HTMLArea
							.arrayContainsArray(last_classes, new_thiers))) {
				el = this.switchElementTag(el, last_el.tagName);
				new_thiers = last_classes;
			} else {
				// We can't rely on the remembered tags any more 
				el._stylist_usedToBe = [];
			}
		}

		if (new_thiers.length > 0 || el.tagName.toLowerCase() != 'span'
				|| (el.id && el.id != '')) {
			el.className = new_thiers.join(' ').trim();
		} else {
			// Must be a span with no classes and no id, so we can splice it out 
			var prnt = el.parentNode;
			var childs = el.childNodes;
			for ( var x = 0; x < childs.length; x++) {
				prnt.insertBefore(childs[x], el);
			}
			prnt.removeChild(el);
		}
	}
};

HTMLArea.prototype._addClasses = function(el, classes) {

	if (el != null) {

		var thiers = el.className.trim().split(' ');
		var ours = classes.split(' ');

		for ( var x = 0; x < ours.length; x++) {
			var exists = false;
			for ( var i = 0; exists == false && i < thiers.length; i++) {
				if (thiers == ours[x]) {
					exists = true;
				}
			}
			if (exists == false) {
				thiers[thiers.length] = ours[x];
			}
		}

		el.className = thiers.join(' ').trim();
	}
};

String.prototype.trim = function() {
	a = this.replace(/^\s+/, '');
	return a.replace(/\s+$/, '');
};

// creates a rgb-style color from a number
HTMLArea._makeColor = function(v) {
	if (typeof v != "number") {
		// already in rgb (hopefully); IE doesn't get here.
		return v;
	}
	// IE sends number; convert to rgb.
	var r = v & 0xFF;
	var g = (v >> 8) & 0xFF;
	var b = (v >> 16) & 0xFF;
	return "rgb(" + r + "," + g + "," + b + ")";
};

// returns hexadecimal color representation from a number or a rgb-style color.
HTMLArea._colorToRgb = function(v) {
	if (!v)
		return '';

	// returns the hex representation of one byte (2 digits)
	function hex(d) {
		return (d < 16) ? ("0" + d.toString(16)) : d.toString(16);
	}
	;

	if (typeof v == "number") {
		// we're talking to IE here
		var r = v & 0xFF;
		var g = (v >> 8) & 0xFF;
		var b = (v >> 16) & 0xFF;
		return "#" + hex(r) + hex(g) + hex(b);
	}

	if (v.substr(0, 3) == "rgb") {
		// in rgb(...) form -- Mozilla
		var re = /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;
		if (v.match(re)) {
			var r = parseInt(RegExp.$1);
			var g = parseInt(RegExp.$2);
			var b = parseInt(RegExp.$3);
			return "#" + hex(r) + hex(g) + hex(b);
		}
		// doesn't match RE?!  maybe uses percentages or float numbers
		// -- FIXME: not yet implemented.
		return null;
	}

	if (v.substr(0, 1) == "#") {
		// already hex rgb (hopefully :D )
		return v;
	}

	// if everything else fails ;)
	return null;
};

// modal dialogs for Mozilla (for IE we're using the showModalDialog() call).

// receives an URL to the popup dialog and a function that receives one value;
// this function will get called after the dialog is closed, with the return
// value of the dialog.
HTMLArea.prototype._popupDialog = function(url, action, init, height, width) {
	Dialog(this.popupURL(url), action, init, height, width);
};

// paths

HTMLArea.prototype.imgURL = function(file, plugin) {
	if (typeof plugin == "undefined")
		return _editor_url + file;
	else
		return _editor_url + "plugins/" + plugin + "/img/" + file;
};

HTMLArea.prototype.popupURL = function(file) {
	var url = "";
	if (file.match(/^plugin:\/\/(.*?)\/(.*)/)) {
		var plugin = RegExp.$1;
		var popup = RegExp.$2;
		if (!/\.html$/.test(popup))
			popup += ".html";
		url = _editor_url + "plugins/" + plugin + "/popups/" + popup;
	} else
		url = _editor_url + this.config.popupURL + file;

	return url;

};

/**
 * FIX: Internet Explorer returns an item having the _name_ equal to the given
 * id, even if it's not having any id.  This way it can return a different form
 * field even if it's not a textarea.  This workarounds the problem by
 * specifically looking to search only elements having a certain tag name.
 */
HTMLArea.getElementById = function(tag, id) {
	var el, i, objs = document.getElementsByTagName(tag);
	for (i = objs.length; --i >= 0 && (el = objs[i]);)
		if (el.id == id)
			return el;
	return null;
};

HTMLArea._lc = function(string, context, replace) {
	var ret;
	if (_editor_lang == "en") {
		if (typeof string == 'object' && string.string) {
			ret = string.string;
		} else {
			ret = string;
		}
	} else {
		if (typeof HTMLArea._lc_catalog == 'undefined') {
			HTMLArea._lc_catalog = [];
		}

		if (typeof context == 'undefined') {
			context = 'HTMLArea';
		}

		if (typeof HTMLArea._lc_catalog[context] == 'undefined') {
			HTMLArea._lc_catalog[context] = HTMLArea._loadlang(context);
		}

		var key;
		if (typeof string == 'object' && string.key) {
			key = string.key;
		} else if (typeof string == 'object' && string.string) {
			key = string.string;
		} else {
			key = string;
		}

		if (typeof HTMLArea._lc_catalog[context][key] == 'undefined') {
			if (context == 'HTMLArea') {
				// Indicate it's untranslated
				if (typeof string == 'object' && string.string) {
					ret = string.string;
				} else {
					ret = string;
				}
			} else {
				//if string is not found and context is not HTMLArea try if it is in HTMLArea
				return HTMLArea._lc(string, 'HTMLArea', replace);
			}
		} else {
			ret = HTMLArea._lc_catalog[context][key];
		}
	}

	if (typeof string == 'object' && string.replace) {
		replace = string.replace;
	}
	if (typeof replace != "undefined") {
		for ( var i in replace) {
			ret = ret.replace('$' + i, replace[i]);
		}
	}

	return ret;
};

function checkFullScreenWin() {
	try {
		if (fullScreenWin != null && fullScreenWin.closed) {
			HTMLArea._object._htmlArea.style.visibility = "visible";
			HTMLArea._object._iframe.style.height = HTMLArea._object._iframe
					.getAttribute("initheight");
			HTMLArea._object._iframe.style.visibility = "visible";
			fullScreenWin = null;
			if ((typeof saveClicked != "undefined") && saveClicked) {
				//HTMLArea._object._toolbarObjects["cust_save"].state("enabled", false);
				HTMLArea._object.changeEditorState(false);
			}
			return;
		} else if (fullScreenWin != null) {
			setTimeout("checkFullScreenWin()", 500);
		}
	} catch (err) {
	}
}

// Returns the deepest ancestor of the selection that is of the current type
HTMLArea.prototype._getFirstAncestor = function(sel, types) {

	//var prnt = this._activeElement(sel);
	var prnt = null;
	if (prnt == null) {
		try {

			prnt = (HTMLArea.is_ie ? this._createRange(sel).parentElement()
					: this._createRange(sel).commonAncestorContainer);
		} catch (e) {
			return null;
		}
	}

	if (typeof types == 'string') {
		types = [ types ];
	}

	while (prnt) {
		if (prnt.nodeType == 1) {

			if (types == null) {
				return prnt;
			}
			for ( var i = 0; i < types.length; i++) {
				if (prnt.tagName.toLowerCase() == types[i]) {
					return prnt;
				}
			}

			if (prnt.tagName.toLowerCase() == 'body')
				break;
			if (prnt.tagName.toLowerCase() == 'table')
				break;
		}
		prnt = prnt.parentNode;
	}

	return null;
};

/**
 * Returns the selected element, if any.  That is,
 * the element that you have last selected in the "path"
 * at the bottom of the editor, or a "control" (eg image)
 *
 * @returns null | element
 */
HTMLArea.prototype._activeElement = function(sel) {
	if (sel == null)
		return null;
	if (this._selectionEmpty(sel))
		return null;

	if (HTMLArea.is_ie) {
		if (sel.type.toLowerCase() == "control") {
			return sel.createRange().item(0);
		} else {

			// If it's not a control, then we need to see if
			// the selection is the _entire_ text of a parent node
			// (this happens when a node is clicked in the tree)
			var range = sel.createRange();
			var p_elm = this.getParentElement(sel);
			if (p_elm.innerHTML == range.htmlText) {
				return p_elm;
			}
			/*
			if(p_elm)
			{
			  var p_rng = this._doc.body.createTextRange();
			  p_rng.moveToElementText(p_elm);
			  if(p_rng.isEqual(range))
			  {
			    return p_elm;
			  }
			}

			if(range.parentElement())
			{
			  var prnt_range = this._doc.body.createTextRange();
			  prnt_range.moveToElementText(range.parentElement());
			  if(prnt_range.isEqual(range))
			  {
			    return range.parentElement();
			  }
			}
			 */
			return null;
		}
	} else {
		// For Mozilla we just see if the selection is not collapsed (something is selected)
		// and that the anchor (start of selection) is an element.  This might not be totally
		// correct, we possibly should do a simlar check to IE?
		if (!sel.isCollapsed) {
			if (sel.anchorNode.childNodes.length > sel.anchorOffset
					&& sel.anchorNode.childNodes[sel.anchorOffset].nodeType == 1) {
				return sel.anchorNode.childNodes[sel.anchorOffset];
			} else if (sel.anchorNode.nodeType == 1) {
				return sel.anchorNode;
			} else {
				return sel.anchorNode.parentNode;
			}
		}
		return null;
	}
};

HTMLArea.prototype._getAncestorBlock = function(sel) {
	// Scan upwards to find a block level element that we can change or apply to
	var prnt = (HTMLArea.is_ie ? this._createRange(sel).parentElement : this
			._createRange(sel).commonAncestorContainer);

	while (prnt && (prnt.nodeType == 1)) {
		switch (prnt.tagName.toLowerCase()) {
		case 'div':
		case 'p':
		case 'address':
		case 'blockquote':
		case 'center':
		case 'del':
		case 'ins':
		case 'pre':
		case 'h1':
		case 'h2':
		case 'h3':
		case 'h4':
		case 'h5':
		case 'h6':
		case 'h7':
			// Block Element
			return prnt;

		case 'body':
		case 'noframes':
		case 'dd':
		case 'li':
		case 'th':
		case 'td':
		case 'noscript':
			// Halting element (stop searching)
			return null;

		default:
			// Keep lookin
			break;
		}
	}

	return null;
};

function focusHelpWindow() {
	try {
		if (winPopupWindow != null) {
			winPopupWindow.focus();
		}
	} catch (err) {
	}
}

HTMLArea.prototype._openFullScreen = function() {
	// this object will be passed to the newly opened window
	HTMLArea._object = this;
	var width = screen.availWidth;
	var height = screen.availHeight;
	if (HTMLArea.is_ie) {
		//if (confirm(HTMLArea.I18N.msg["IE-sucks-full-screen"]))
		{

			fullScreenWin = window.open(this.popupURL("fullscreen.html"),
					"ha_fullscreen",
					"toolbar=no,location=no,directories=no,status=no,menubar=no,"
							+ "scrollbars=no,resizable=yes,width=" + width
							+ ",height=" + height);
		}
	} else {
		fullScreenWin = window.open(this.popupURL("fullscreen.html"),
				"ha_fullscreen", "toolbar=no,menubar=no,personalbar=no,width="
						+ width + ",height=" + height + ","
						+ "scrollbars=no,resizable=yes");
	}
	setTimeout("checkFullScreenWin()", 500);
}

HTMLArea.prototype._createCommentLink = function(link) {
	var editor = this;
	editor.focusEditor();
	var outparam = null;
	if (typeof link == "undefined") {
		link = this.getParentElement();
		if (link) {
			while (link && !/^a$/i.test(link.tagName))
				link = link.parentNode;
		}
	}
	if (!link) {
		var sel = editor._getSelection();
		var range = editor._createRange(sel);
		var compare = 0;

		outparam = {
			f_href :'',
			f_title :'',
			f_target :'',
			f_usetarget :editor.config.makeLinkShowsTarget
		};
	} else
		outparam = {
			f_href :HTMLArea.is_ie ? editor.stripBaseURL(link.href) : link
					.getAttribute("href"),
			f_title :link.title,
			f_target :link.target,
			f_usetarget :editor.config.makeLinkShowsTarget
		};
	this
			._popupDialog(
					"comments_link.jsp",
					function(param) {
						if (!param)
							return false;
						var a = link;
						if (!a)
							try {
								if (!HTMLArea.is_ie) {
									if (range == "") {
										var selHtml = editor.getSelectedHTML();
										if (/^<img(.*)$/i.test(selHtml)) {
											editor.insertHTML("<a target='"
													+ param.f_target.trim()
													+ "' href='" + param.f_href
													+ "'>" + selHtml + "</a>");
										} else {
											if (param.f_title
													&& param.f_title.length > 0) {
												editor.insertHTML("<a target='"
														+ param.f_target.trim()
														+ "' href='"
														+ param.f_href + "'>"
														+ param.f_title
														+ "</a>");
											} else if (param.f_href
													&& param.f_href.length > 0) {
												editor
														.insertHTML("<a target='"
																+ param.f_target
																		.trim()
																+ "' href='"
																+ param.f_href
																+ "'>"
																+ param.f_href
																+ "</a>");
											}
										}
									} else {
										if (range.startContainer
												&& range.startContainer.nodeType == 1)
											editor._doc.execCommand(
													"createlink", false,
													param.f_href);
										else
											editor.insertHTML("<a target='"
													+ param.f_target.trim()
													+ "' href='" + param.f_href
													+ "'>" + range + "</a>");
									}

								} else {

									var tt = range.text;
									var sHtml = editor.getSelectedHTML();
									if (sHtml == "") {
										sHtml = param.f_href;
									}
									if (/^<img(.*)$/i.test(sHtml)) {
										editor.insertHTML("<a target='"
												+ param.f_target.trim()
												+ "' class='internal' href='"
												+ param.f_href + "'>" + sHtml
												+ "</a>");
									} else {
										if (tt != "") {
											range.pasteHTML("<a target='" + param.f_target.trim()
													+ "'  href='"
													+ param.f_href + "'>" + tt + "</a>");
										} else if (param.f_title && param.f_title.length > 0) {
											range.pasteHTML("<a target='" + param.f_target.trim()
													+ "'  href='"
													+ param.f_href + "'>" + param.f_title
													+ "</a>");
										} else if (param.f_href
												&& param.f_href.length > 0) {
											range.pasteHTML("<a target='" + param.f_target.trim()
													+ "'  href='"
													+ param.f_href + "'>"
													+ param.f_href + "</a>");
										}
									}

								}
							} catch (e) {
							}
						else {
							var href = param.f_href.trim();
							editor.selectNodeContents(a);
							if (href == "") {
								editor._doc.execCommand("unlink", false, null);
								editor.updateToolbar();
								return false;
							} else {
								a.href = href;
							}
						}
						if (!(a && /^a$/i.test(a.tagName)))
							return false;
						a.target = param.f_target.trim();
						a.title = param.f_title.trim();
						editor.selectNodeContents(a);
						editor.updateToolbar();
					}, outparam, 200, 400);
};

HTMLArea.prototype._linkAttachment = function(link) {
	var editor = this;
	var outparam = null;
	if (typeof link == "undefined") {
		link = this.getParentElement();
		if (link && !/^a$/i.test(link.tagName))
			link = null;
	}
	var hyperlink = "";
	var valinternal = "";
	var valexternal = "";
	if (link) {
		var className = HTMLArea.is_ie ? link.getAttribute("className") : link
				.getAttribute("class");
		hyperlink = HTMLArea.is_ie ? editor.stripBaseURL(link.href) : link
				.getAttribute("href");
		if (className == "internal") {
			valinternal = hyperlink;
		} else {
			valexternal = hyperlink;
		}
	}
	if (link)
		outparam = {
			f_url :valinternal,
			f_title :link.title

		};
	var wikiLinkDialogUrl = "insert_attachment.jsp";
	var isNewAsset = false;
	var pageId = page_id;
	var projectName = "";
	var parentpage = "";
	if (!window.opener) {
		projectName = getProjectTitle();
		pageTitle = getPageTitle();
		if (pageTitle == null) {
			pageTitle = getNewPageTitle();
			isNewAsset = (document.getElementById("pagetitle") == null ? true
					: false);
		}
		if (document.getElementById("parentpage") != null) {
			parentpage = document.getElementById("parentpage").value;
		}
		wikiLinkDialogUrl += "?projectname=" + escape(projectName)
				+ "&pagetitle=" + pageTitle + "&family="
				+ document.getElementById("family").value + "&parentpage="
				+ escape(parentpage) + "&newasset="
				+ (isNewAsset ? "true" : "false") + "&pageid=" + pageId;
	} else {
		if (document.getElementById("pop") != null
				&& document.getElementById("pop").value == "true") {
			projectName = getProjectTitle();
			pageTitle = getPageTitle();
			if (pageTitle == null) {
				pageTitle = getNewPageTitle();
				isNewAsset = (document.getElementById("pagetitle") == null ? true
						: false);
			}
			if (document.getElementById("parentpage") != null) {
				parentpage = document.getElementById("parentpage").value;
			}
			wikiLinkDialogUrl += "?projectname=" + escape(projectName)
					+ "&pagetitle=" + pageTitle + "&family="
					+ document.getElementById("family").value + "&parentpage="
					+ escape(parentpage) + "&newasset="
					+ (isNewAsset ? "true" : "false") + "&pageid=" + pageId;
		} else {
			if (document.getElementById("projectname")) {
				projectName = document.getElementById("projectname").value;
			} else {
				projectName = window.opener.document
						.getElementById("projectname").value;
			}
			try {
				if (document.getElementById("pagetitle")) {
					pageTitle = document.getElementById("pagetitle").value;
				} else {
					pageTitle = window.opener.document
							.getElementById("pagetitle").value;
				}
			} catch (e) {
				pageTitle = document.getElementById("editpage_title").value;
				isNewAsset = true;
			}
			;
			if (pageTitle == null) {
				if (document.getElementById("editpage_title")) {
					pageTitle = document.getElementById("editpage_title").value;
				} else {
					pageTitle = window.opener.document
							.getElementById("editpage_title").value;
				}

				if (document.getElementById("pagetitle")) {
					isNewAsset = (document.getElementById("pagetitle") == null ? true
							: false);
				} else {
					isNewAsset = (window.opener.document
							.getElementById("pagetitle") == null ? true : false);

				}
			}
			if (document.getElementById("parentpage")) {
				parentpage = document.getElementById("parentpage").value;

			} else {
				parentpage = window.opener.document
						.getElementById("parentpage").value;
			}
			var family = "";
			if (document.getElementById("family")) {
				family = document.getElementById("family").value;
			} else {
				family = window.opener.document.getElementById("family").value;
			}
			wikiLinkDialogUrl += "?projectname=" + escape(projectName)
					+ "&pagetitle=" + pageTitle + "&family=" + family
					+ "&parentpage=" + escape(parentpage) + "&newasset="
					+ (isNewAsset ? "true" : "false") + "&pageid=" + pageId;
			useOpener = true;
		}
	}
	if (pageTitle == null || pageTitle == "") {
		alert(HTMLArea.I18N.msg["please_enter_title"]);
		return;
	}

	//this._popupDialog("link.html", function(param) {
	this._popupDialog(wikiLinkDialogUrl, function(param) {
		try {
			if (!param) {
				return false;
			}

			var a = link;
			if (!a) {
				var sel = editor._getSelection();
				var range = editor._createRange(sel);
				if (!HTMLArea.is_ie) {
					if (range == "") {
						var selHtml = editor.getSelectedHTML();
						if (/^<img(.*)$/i.test(selHtml)) {
							editor.insertHTML("<a href='" + param.f_url + "'>"
									+ selHtml + "</a>");
						} else {
							if (param.f_title && param.f_title.length > 0) {
								editor.insertHTML("<a href='" + param.f_url
										+ "'>" + param.f_title + "</a>");
							} else if (param.f_url && param.f_url.length > 0) {
								editor.insertHTML("<a href='" + param.f_url
										+ "'>" + param.f_url + "</a>");
							}
						}
					} else {
						if (range.startContainer
								&& range.startContainer.nodeType == 1)
							editor._doc.execCommand("createlink", false,
									param.f_url);
						else
							editor.insertHTML("<a href='" + param.f_url + "'>"
									+ range + "</a>");
					}
					a = editor.getParentElement();

					a.setAttribute("class", "internal");

				} else {
					var tt = range.text;
					var sHtml = editor.getSelectedHTML();
					if (/^<img(.*)$/i.test(sHtml)) {
						editor.insertHTML("<a class='internal' href='"
								+ param.f_url + "'>" + sHtml + "</a>");
					} else {
						range.pasteHTML("<a class='internal' href='"
								+ param.f_url + "'>" + tt + "</a>");
					}
				}
				if (!HTMLArea.is_ie) {
					a = range.startContainer;
					if (a && !/^a$/i.test(a.tagName))
						a = a.nextSibling;
				}

			} else {

				a.href = param.f_url.trim();

			}

			if (!/^a$/i.test(a.tagName)) {
				return false;
			}

			a.title = param.f_title.trim();
			editor.selectNodeContents(a);
			editor.updateToolbar();
		} catch (er) {
		}
	}, outparam, 350, 750);
};

/**
 * enableDisable :- true enables all, false - disable all
 */
HTMLArea.prototype.changeEditorState = function(enableDisable) {
	this.globalStateChange = !enableDisable;
	var doc = this._iframe.contentWindow.document;
	if (HTMLArea.is_ie) {
		doc.body.contentEditable = enableDisable;
	}
	if (HTMLArea.is_gecko) {
		// enable editable mode for Mozilla
		doc.designMode = (enableDisable ? "on" : "off");
	}
	for ( var i in this._toolbarObjects) {
		var btn = this._toolbarObjects[i];
		btn.state("enabled", enableDisable);
	}
}

function printStackTrace() {
	var callstack = [];
	var isCallstackPopulated = false;
	try {
		i.dont.exist += 0; //doesn't exist- that's the point
	} catch (e) {
		if (e.stack) { //Firefox
			var lines = e.stack.split("\n");
			for ( var i = 0, len = lines.length; i < len; i++) {
				if (lines[i].match(/^\s*[A-Za-z0-9\-_\$]+\(/)) {
					callstack.push(lines[i]);
				}
			}
			//Remove call to printStackTrace()
			callstack.shift();
			isCallstackPopulated = true;
		} else if (window.opera && e.message) { //Opera
			var lines = e.message.split("\n");
			for ( var i = 0, len = lines.length; i < len; i++) {
				if (lines[i].match(/^\s*[A-Za-z0-9\-_\$]+\(/)) {
					var entry = lines[i];
					//Append next line also since it has the file info
					if (lines[i + 1]) {
						entry += " at " + lines[i + 1];
						i++;
					}
					callstack.push(entry);
				}
			}
			//Remove call to printStackTrace()
			callstack.shift();
			isCallstackPopulated = true;
		}
	}
	if (!isCallstackPopulated) { //IE and Safari
		var currentFunction = arguments.callee.caller;
		while (currentFunction) {
			var fn = currentFunction.toString();
			var fname = fn.substring(fn.indexOf("function") + 8, fn
					.indexOf("("))
					|| "anonymous";
			callstack.push(fname);
			currentFunction = currentFunction.caller;
		}
	}
	output(callstack);
}

function output(arr) {
	//Optput however you want
	alert(arr.join("nn"));
}

/** Performs various transformations of the HTML used internally, complement to Xinha.prototype.inwardHtml()  
 *  Plugins can provide their own, additional transformations by defining a plugin.prototype.outwardHtml() implematation,
 *  which is called by this function
 *
 *  @private
 *  @see HTMLArea#inwardHtml
 *  @param {String} html
 *  @returns {String} HTML content
 */
HTMLArea.prototype.outwardHtml = function(html) {

	html = html.replace(/<(\/?)b(\s|>|\/)/ig, "<$1strong$2");
	html = html.replace(/<(\/?)i(\s|>|\/)/ig, "<$1em$2");
	html = html.replace(/<(\/?)strike(\s|>|\/)/ig, "<$1del$2");

	return html;
};

/** Performs various transformations of the HTML to be edited 
 *  Plugins can provide their own, additional transformations by defining a plugin.prototype.inwardHtml() implematation,
 *  which is called by this function
 *  
 *  @private
 *  @see HTMLArea#outwardHtml
 *  @param {String} html  
 *  @returns {String} transformed HTML
 */
HTMLArea.prototype.inwardHtml = function(html) {

	// Both IE and Gecko use strike instead of del (#523)
	html = html.replace(/<(\/?)del(\s|>|\/)/ig, "<$1strike$2");

	return html;
};
