// 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.88 2008/09/27 00:56:13 ajain 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 skin = "gray";
var collabapplication = "wiki";
var E_MODE_TEXT = false;
var checkSupportedBrowser_val = null;
var setEventFlag = "false";

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;
		
		//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");
			}
			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, .htmtableborders td, .htmtableborders th {border : 1px dashed #000000 ! important;} \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.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) {
	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);
		document.write("<script type='text/javascript' src='" + plugin_file + "'></script>");
		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.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);
		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() {
	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=="")
				{
					if(param.f_title = "")
					{
						editor.insertHTML("<a href='"+ param.f_href+"'>"+ param.f_href+"</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 =="")
				{
					if(param.f_title = "")
					{
						editor.insertHTML("<a href='"+ param.f_href+"'>"+ param.f_href+"</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);
};

HTMLArea.prototype._createLink = 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_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
		{
			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
		{
			if( window.opener.document.getElementById("pagetitle") != null )
			{
				pageTitle = window.opener.document.getElementById("pagetitle").value;
			}
		}
	}	
	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 (/^<img(.*)$/i.test(sHtml))
						{
							editor.insertHTML("<a target='"+param.f_target.trim()+"' class='external' href='"+param.f_external_href+"'>" + 
								sHtml + "</a>");
						}
						else
						{
							range.pasteHTML("<a target='"+param.f_target.trim()+"' class='external' href='"+param.f_external_href+"'>"+tt+"</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 (/^<img(.*)$/i.test(sHtml))
						{
							editor.insertHTML("<a target='"+param.f_target.trim()+"' class='internal' href='"+param.f_internal_href+"'>" + 
									 sHtml + "</a>");
						}
						else
						{
							range.pasteHTML("<a target='"+param.f_target.trim()+"' class='internal' href='"+param.f_internal_href+"'>"+tt+"</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);
};

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
	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
		{
			
			if(window.opener.document.getElementById("parentpage") != null)
			{
				parentpage=window.opener.document.getElementById("parentpage").value;
			}
			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" : 
					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
	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;
	
	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;
	}
	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
		{
			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="+pageTitle+"&family="+window.opener.document.getElementById("family").value+"&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);
};

// 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");
		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);
};

// 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");
		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);
};


// 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);
};


//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);
};


//  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
		{
			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;
			}

			wikiWordDialogUrl+="?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(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);
};

//  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
		{
			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;
			}
			wikiWordDialogUrl+="?projectname="+escape(projectName)+"&pagetitle="+escape(pageTitle)+"&family="+window.opener.document.getElementById("family").value+"&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);
};

// 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);
};

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

	var editor = this;	// for nested functions
	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);
		 if (HTMLArea.is_ie) {
			range.pasteHTML("<a name=\""+param+"\" class=\"anchor\" alt=\""+param+"\"></a>");
		 } else {
			editor.insertNodeAtSelection(anchor);
		 }
		 editor.focusEditor();
		return true;	
	}, outparam);
};


//Called when the user clicks on "InsertPanel" button. 
HTMLArea.prototype._insertPanel = 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 table = doc.createElement("table");

	table.style.height="80px";
	table.style.width="95%";

	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);
	}
	return true;

};

//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._insertPlugin = function(anchorName) {
   
	var editor = this;	// for nested functions
	var doc = editor._doc;
	//Added by Amit Jain
	editor.focusEditor();
	var outparam = null;
	this._popupDialog("create_plugin.jsp", function(param) {
		
		if (!param) {	// user must have pressed Cancel
			return false;
		}
		
		var sel = editor._getSelection();
		var range = editor._createRange(sel);
		//editor.focusEditor();
		
		var wiki = doc.createElement("div");
		
		wiki.className="plugin";
		//alert(param)
		var plugintext="Enter plugin here";
		if(param == "rssin")
		{
			plugintext="$feed{ref=\"listtype=a2z:count=10:projectname=\"}"
		}
		else if(param == "rssex")
		{
			plugintext = "$feed{ref=\"\", title=\"\", width=\"\", height=\"\", show_desc=\"true\", show_heading=\"true\",show_date=\"true\"}";
		}
		else if(param == "toc")
		{
			plugintext="$toc{show_div=\"yes\" show_number=\"no\" show_header=\"yes\" show_anchor=\"no\" div_border_width=\"\" div_border_style=\"\" div_border_color=\"\" div_bgcolor=\"\"}"
		}
		else if(param == "evcal")
		{
			plugintext="$CAL{month=\"\" year=\"\" view=\"full\" events=\"mm-dd-yyyy(time;event1|time2;event2|event3)\" }";
		}
		else if(param == "ctree")
		{
			plugintext="$children{title=\"\" projectname=\"\"}";
		}
		else if(param == "redirectin")
		{
			plugintext="$redirect{title=\"\" projectname=\"\"}";
		}
		else if(param == "redirectex")
		{
			plugintext="$redirect{src=\"\"}";
		}
		else if(param == "flash")
		{
			plugintext="$flash{src=\"\" height=\"200\" width=\"500\"}";
		}
		else if(param == "youtube")
		{
			plugintext="$youtube{src=\"\"}"
		}
		else if(param == "gvideo")
		{
			plugintext="$gvideo{id=\"\"}"
		}
		else if(param == "gcalendar")
		{
			plugintext="$gcalendar{src=\"\" width=\"100%\" height=\"480\" mode=\"month\" title=\"\"}"
		}
		else if(param == "30boxes")
		{
			plugintext="$30boxes{src=\"\" width=\"800\" height=\"590\"} ";
		}
		else if(param == "googlegadgets")
		{
			plugintext="#ggadget{src=\"\"} ";
		}
		else if(param == "dbplugin")
		{
			plugintext="#dbdata{datasource=\"\" query=\"\" }   ";
		}
		else if(param == "chartplugin")
		{
			plugintext="#chart{chart=\"\" title=\"\" category=\"\" data=\"\"}  ";
		}
		
		wiki.innerHTML=plugintext;
		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();	
			
		}
		 editor.focusEditor();
		return true;	
	}, outparam);
};
//Called when the user clicks on "InsertWiki" button. 
/*
HTMLArea.prototype._insertPlugin = 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","plugin");
	wiki.innerHTML="Enter plugin 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;

};
*/
// Called when the user clicks the Insert Table button
/*
HTMLArea.prototype._insertTable = function() {
	var sel = this._getSelection();
	var range = this._createRange(sel);
	var editor = this;	// for nested functions
	this._popupDialog("insert_table.html", function(param) {
		if (!param) {	// user must have pressed Cancel
			return false;
		}
		var doc = editor._doc;
		// create the table element
		var table = doc.createElement("table");
		// assign the given arguments
		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"  : table.setAttribute("border",parseInt(value)); table.style.borderCollapse = "collapse";break;
			   	//case "f_border"  : table.style.emptyCells = "show";table.setAttribute("border", "1px"); table.style.border = value +"px solid #000"; table.style.borderCollapse = "collapse";break;
			    case "f_spacing" : table.setAttribute("cellspacing",parseInt(value)); break;
			    case "f_padding" : table.setAttribute("cellpadding",parseInt(value));break;
				//case "f_border"  : table.border	 = parseInt(value); break;
				//case "f_spacing" : table.cellspacing = parseInt(value); break;
			    //case "f_padding" : table.cellpadding = parseInt(value); break;
			}
		}
		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");
				//td.style.border = "1px solid #000"; 
				
				tr.appendChild(td);
				// Mozilla likes to see something inside the cell.
				(HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));
			}
		}
		if (HTMLArea.is_ie) {
			range.pasteHTML(table.outerHTML);
		} else {
			// insert the table
			editor.insertNodeAtSelection(table);
		}
		return true;
	}, null);
};
*/

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)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(value == "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"));
	   }
	 }
	 table.__msh_globalStyle=true;
	 if(HTMLArea.is_ie)
	 {
	   range.pasteHTML(table.outerHTML);
	 }
	 else
	 {
	   editor.insertNodeAtSelection(table);
	  }
	  return true;
	  }
	  ,null);
};


/***************************************************
 *  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
	this.focusEditor();
	cmdID = cmdID.toLowerCase();
	switch (cmdID) {
	    case "htmlmode" : this.setMode(); break;
	    case "hilitecolor":
		(HTMLArea.is_ie) && (cmdID = "backcolor");
	    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)));
		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 = (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 ? 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)
						window.opener.savePage();
					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)
{

	switch(ev.keyCode)
	{
		
		/*
		case 13:
		if(HTMLArea.is_gecko&&!ev.shiftKey)
		if(this.dom_checkInsertP(true))
		HTMLArea._stopEvent(ev);
		break;
		case 8:
	
		case 46:
		if(HTMLArea.is_gecko&&!ev.shiftKey)
		{
			if(this.dom_checkBackspace())
			HTMLArea._stopEvent(ev);
		}
		else if(HTMLArea.is_ie)
		{
			if(this.ie_checkBackspace())
			HTMLArea._stopEvent(ev);
		}
		break;
		*/
		case 112:
			if(!is_safari)
			{
				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:
			if(!is_safari)
			{
				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))
			
			var parents=this.getAncestorsHash();
		   	var editor = this;
			var tr = this.getClosest("tr");
			var nextTR = tr.nextSibling;
			
			if(nextTR && nextTR.nodeName != "TR")
			{
				nextTR = nextTR.nextSibling;
			}
			var td = this.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
			{
				editor.moz_tabPressed(ev.shiftKey)
			}
			/*
			var otr = lastTR.cloneNode(true);
			editor.clearRow(otr);
			var insertedRow = lastTR.parentNode.insertBefore(otr, lastTR.nextSibling);
			editor.forceRedraw();
			this.selectNodeContents(insertedRow.firstChild);
			editor.focusEditor();	
			*/
			//HTMLArea._stopEvent(ev);
			
		}
		break;
	}
}
	else
	{
		try
		{
			if(et_m_cancelMenus)
			{
				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;
};
// 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;
	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.moz_tabPressed=function(shift)
{
	
	var editor=this;
	setTimeout(function(){
		var parents=editor.getAncestorsHash();
		if(parents.table&&parents.td)
			editor.selectNodeContents(parents.td);
		},20);
return false;
};

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;
};

// 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 = HTMLArea.indent(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 (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
    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
		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].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) {
	Dialog(this.popupURL(url), action, init);
};

// 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;
			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;
  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;
    if (HTMLArea.is_ie) {
      if(sel.type == "Control")
      {
        compare = range.length;
      }
      else
      {
        compare = range.compareEndPoints("StartToEnd", range);
      }
    } else {
      compare = range.compareBoundaryPoints(range.START_TO_END, range);
    }
    if (compare == 0) {
      alert(HTMLArea.I18N.msg["select_text_to_create_link"]);
      return;
    }
    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 {
      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;
          if (a == null)
            a = range.startContainer.parentNode;
        }
      }
    } 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);
};

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
		{
			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;
			}
			wikiLinkDialogUrl+="?projectname="+escape(projectName)+"&pagetitle="+pageTitle+"&family="+window.opener.document.getElementById("family").value+"&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='"+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);
};



