/*
	License Agreement
	
	Refer to your email receipt as to whether you have a Single Domain License or a 
	Multiple Domain License.

	Evaluation Version
	
	If you have not yet purchased HTML Rich Text Area then you are running the 
	Evaluation version.	The evaluation version may be installed on a development 
	server and used for a period of 30 days. Thereafter it must be uninstalled 
	or purchased. It may not be installed on any production servers.
	You cannot make any modifications to the source code of HTML Rich Text Area.
	
	
	Single Domain License

	If you have purchased the Single Domain License you are licensed to run the HTML 
	Rich Text Area on one production domain.  
	A domain is defined as a web site associated with a particular Internet Domain Name
	or an Intranet site. One license grants you the use of HTML Rich Text Area on an 
	unlimited number of web pages belonging to that domain or Intranet site.  The 
	license is not limited by the number of users, hits on the web site, servers 
	in a web farm or the number of CPUs in the web server. HTML Rich Text Area may also
	be used on internal development workstations or development servers.
	Additional licenses can be purchased for additional domains.
	
	You are licensed to modify the source code of HTML Rich Text Area.
	

	Multiple Domain License

	If you have purchased the Multiple Domain License you are licensed to run the HTML 
	Rich Text Area on more than one production domain managed by your company.
	A domain is defined as a web site associated with a particular Internet Domain Name
	or an Intranet site. This license grants you the use of HTML Rich Text Area on an 
	unlimited number of web pages belonging to multiple domains or Intranet sites
	managed by your company.  The license is not limited by the number of users, 
	hits on the web site, servers in a web farm or the number of CPUs in the web server. 
	HTML Rich Text Area may also be used on internal development workstations or development 
	servers.
	
	You are licensed to modify the source code of HTML Rich Text Area.


	Product Integration License
		
	If you have purchased the Product Integration License you are licensed to incorporate 
	the HTML Rich Text Area into an application that may be sold or distributed.  
	An application is defined as a single software package designed perform a particular 
	task including its various versions. This license grants you the use of the HTML  
	Rich Text Area in an unlimited number of distributions of the application. Any source 
	code modifications to the HTML Rich Text Area must be agreed to by 
	tcpIQ/Sigma Solutions.  Your application's licensing agreement must indicate that 
	the end users may not change the HTML Rich Text Area software, distribute it 
	or reverse engineer it.  The wording of the licensing agreement must be agreed to 
	by tcpIQ/Sigma Solutions. Only the obfuscated version of the HTML Rich Text Area
	can be distributed within the application.
		
		

	Distribution of this software

	Other than the serving of web pages that contain the HTML Rich Text Area, 
	you are not allowed to redistribute this software or any modifications that 
	are made to the source code. You are specifically prohibited from charging, 
	or requesting donations, for any such copies, however made; and from
	distributing the software and/or documentation with other products
	(commercial or otherwise) without prior written permission.
	The transfer of this license to other parties is not allowed.


	Disclaimer of Warranty

	This software and the accompanying files are sold "as is" and 
	without warranties as to performance or merchantability or any other 
	warranties whether expressed or implied. Because of the various 
	hardware and software environments into which HTML Rich Text Area
	may be put, no warranty of fitness for a particular purpose is 
	offered.

	The user must assume the entire risk of using the program. 
	Any liability of the seller will be limited exclusively to product 
	replacement or refund of purchase price.

	(c) Copyright 2003 tcpIQ (Sigma Solutions)
	
*/


// *********************
// VARIABLE DECLARATIONS
// *********************

// This the level of opacity when the toolbar button is disabled. Default is 25%
var DISABLEDOPACITY = 25;


//Button groups for toolbar
var BTN_TYPE_STANDARD = 0;
var BTN_TYPE_PRESENTATION = 1;
var BTN_TYPE_SRC = 2;
var BTN_TYPE_TABLE = 3;
var BTN_TYPE_INPUT = 4;
var BTN_TYPE_DROPDOWN = 5;
var BTN_TYPE_SPACER = 6;
var BTN_TYPE_SPECIAL = 7;

//Button Array Indexes
//ImageURL, Name, function, type,status, width, CMDID
var BTN_PROP_IMGURL = 0;
var BTN_PROP_TITLE = 1;
var BTN_PROP_FUNC = 2;
var BTN_PROP_TYPE = 3;
var BTN_PROP_DEFSTATUS = 4;
var BTN_PROP_WIDTH = 5;
var BTN_PROP_CMDID = 6;

var intEditorCount = 0;		//Global to track object creation count

// Whether the table guidelines are on or off - off by default
var guidelinesOn = false;


// ************************************
// CONSTRUCTION AND INITIALISATION CODE
// ************************************

// HTMLRichTextArea
// Constructor.  Passes in the name, width, height and default string.  
// If SIZESINPERCENT == true then the strWidth is the size in percent that the 
// HTML RTA should fill its parent.  Otherwise it is the size in pixels
function HTMLRichTextArea(strFormElName, strW, strH, strDefaultHTML){

	try 
	{
		IMG_DIRECTORY = IMG_DIRECTORY;
//		IMG_DIRECTORY = "/inc/HTMLRTAImages/";
	}
	catch(e)
	{
		alert('PROGRAMMING ERROR: You have not included a reference to the HTMLRichTextAreaFactorySettings.js file (or similiar).  The HTML Rich Text Area will not be displayed until you do.');
		return;
	}

	// Record the number used of HTML RTAs used on this page	
	intEditorCount += 1;
		
	this.ImgDir = IMG_DIRECTORY;
	this.stylesheet = CSS_FILE;
	
	// The changes are always recorded incase they go over the character limit
	this.OldText = strDefaultHTML;
	
	// Name of the IFRAME in which the editing takes place
	// Remove any spaces the user may haved used in the name - these are not allowed
	this.iframeId = ("HTMLRichTextArea"+intEditorCount+strFormElName).replace(' ', '');	
												
	this.height = strH;					// control height
	this.width = strW;					// control width
	this.defaultHTML = strDefaultHTML;			// default HTML String
	this.FormElementName = strFormElName;			// the name of the form element used in posting
	
	// Create all of the information about the tool bar buttons
	this.ToolbarBtns = this.CreateToolbarButtonArray();
}


// HTMLRichTextArea.prototype.Draw
// Draws the HTML Rich Text Area. It is made up of a surrounding table if SHOWHTMLRTABORDER == true,
// containing the toolbar, iframe, a HTML text box, a read-only iframe and the status bar.
HTMLRichTextArea.prototype.Draw = function()
{		
	try 
	{
		IMG_DIRECTORY = IMG_DIRECTORY;
	}
	catch(e)
	{
		return;
	}

	if ((navigator.appName.indexOf("Microsoft Internet Explorer") >= 0) && (navigator.appVersion.indexOf("MSIE 4") == -1) && (navigator.appVersion.indexOf("MSIE 3") == -1)) {
		//Event Handlers for the control..

		// Start the border
		if (SHOWHTMLRTABORDER == true)
		{
			if (SIZESINPERCENT == false)
			{
				document.write("<table cellpadding='" + HTMLRTABORDERSIZE + "' bgcolor='" + HTMLRTABORDERCOLOR + "' width='"+this.width+"' style='" + HTMLRTABORDERSTYLE + "'><tr><td>");
			}
			else {	
				document.write("<table cellpadding='" + HTMLRTABORDERSIZE + "' bgcolor='" + HTMLRTABORDERCOLOR + "' width='"+this.width+"%' style='" + HTMLRTABORDERSTYLE + "'><tr><td>");
			}				
		}

		document.write("<style TYPE='text/css'>\n");
		document.write(".BUTTONLATCHED {\n");
		document.write("	background-color: #c1d2ee;\n");
		document.write("	border-right: #316ac5 1px solid;\n");
		document.write("	border-top: #316ac5 1px solid;\n");
		document.write("	border-left: #316ac5 1px solid;\n");
		document.write("	border-bottom: #316ac5 1px solid;\n");
		if (SHOWCURSORASHAND == true)	document.write("	cursor:hand;\n");
		document.write("	disabled:false;\n");		
		document.write("}\n");
			
		document.write(".BUTTONENABLED {\n");
		document.write("	border-right: #efefde 1px solid;\n");
		document.write("	border-top: #efefde 1px solid;\n");
		document.write("	border-left: #efefde 1px solid;\n");
		document.write("	border-bottom: #efefde 1px solid;\n");
		if (SHOWCURSORASHAND == true)	document.write("	cursor:hand;\n");
		document.write("	disabled:false;\n");		
		document.write("}\n");

		document.write(".BUTTONDISABLED {\n");
		document.write("	border-right: #efefde 1px solid;\n");
		document.write("	border-top: #efefde 1px solid;\n");
		document.write("	border-left: #efefde 1px solid;\n");
		document.write("	border-bottom: #efefde 1px solid;\n");
		document.write("	cursor:default;\n");
		document.write("	disabled:true;\n");		
		document.write("	filter:alpha(opacity=" + DISABLEDOPACITY + ");\n");		
		document.write("}\n");

		document.write(".SUNKEN {\n");
		document.write("	border-top: #a0a0a0 1px solid;\n");
		document.write("	border-left: #a0a0a0 1px solid;\n");
		document.write("	border-bottom: #f0f0f0 1px solid;\n");
		document.write("	border-right: #f0f0f0 1px solid;\n");
		document.write("	cursor:default;\n");
		document.write("	font-size:xx-small;\n");
		document.write("}\n");

		document.write("</style>\n");
	
		if (SHOWHTMLRTABORDER == false)
		{
			if (SIZESINPERCENT == false)
			{
				document.write("<TABLE cellspacing=0 border=0 cellpadding=1 ondragstart='return false;' width='"+this.width+"'><TR><TD bgcolor='" + HTMLRTABORDERCOLOR + "'>");
			}
			else {
				document.write("<TABLE cellspacing=0 border=0 cellpadding=1 ondragstart='return false;' width='"+this.width+"%'><TR><TD bgcolor='" + HTMLRTABORDERCOLOR + "'>");
			}
		}
		else {
			document.write("<TABLE cellspacing=0 border=0 cellpadding=1 width='100%' ondragstart='return false;'><TR><TD bgcolor='" + HTMLRTABORDERCOLOR + "'>");
		}

		// Draw the tool bar
		this.DrawToolBar();

		// We need to escape any double quotes as it will stuff up the javascript below
		var strDefault;
		strDefault = this.defaultHTML.replace(/\"/gi, "\\\"");
		strDefault = strDefault.replace(/\n/gi, "\\n");
								
		// draw the read-only version 
		// this is hidden by default and turn on when the user calls MakeReadOnly()
		if (SHOWHTMLRTABORDER == false)
		{
			if (SIZESINPERCENT == false)
			{
				document.write("<iframe ID='RO"+this.iframeId+"' style='display:none;width:"+(this.width)+"px;height:"+(this.height)+"px;'></iframe>");
			}
			else {
				document.write("<iframe ID='RO"+this.iframeId+"' style='display:none;width:100%;height:"+(this.height)+"px;'></iframe>");
			}
		}
		else {
			document.write("<iframe ID='RO"+this.iframeId+"' style='display:none;width:100%;height:"+(this.height)+"px;'></iframe>");
		}
			
			
		// Draw the html output form - this is the thing that gets submitted
		if (SHOWHTMLRTABORDER == false)
		{
			if (SIZESINPERCENT == false)
			{
				document.write("<TEXTAREA Name='"+this.FormElementName+"' ID='TXT"+this.iframeId+"' style='display:none;width:"+(this.width)+"px;height:"+(this.height)+"px;'></TEXTAREA>");
			}
			else {
				document.write("<TEXTAREA Name='"+this.FormElementName+"' ID='TXT"+this.iframeId+"' style='display:none;width:100%;height:"+(this.height)+"px;'></TEXTAREA>");
			}
		} 
		else {
			document.write("<TEXTAREA Name='"+this.FormElementName+"' ID='TXT"+this.iframeId+"' style='display:none;height:"+(this.height)+"px;'></TEXTAREA>");
		}
			
			
		// Create an event handler calls 'EditorLoaded' when the frame is loaded initially
		// This event handler then sets the default HTML, and hooks into the various events.
		// Apologies for the ugly code. There is no way to really improve the aesthetics here.
		document.write(""+
			"<scr" + "ipt LANGUAGE=\"javascript\" FOR=\""+this.iframeId+"\" EVENT=\"onload\">"+
			"<!--\n"+
			"return EditorLoaded(\""+this.iframeId+"\",\""+strDefault+"\")\n"+
			"/" + "/-->\n"+
			"</script>");
				
		// Draw the IFRAME
		// Start the border
		if (SHOWHTMLRTABORDER == false)
		{
			if (SIZESINPERCENT == false)
			{
				document.write("<iframe ID='"+this.iframeId+"' STYLE='background-color:white; height:"+this.height+";width:"+ (this.width + 5)+"'></iframe>");
			}
			else {	
				document.write("<iframe ID='"+this.iframeId+"' height="+this.height+" width='100%' bgcolor='white'></iframe>");
			}				
		}
		else {
			document.write("<iframe ID='"+this.iframeId+"' height="+this.height+" width='100%' bgcolor='white'></iframe>");
		}

		DrawStatusBar(this.iframeId);

		document.write("</TD></TR></TABLE>");

		// Stop the border
		if (SHOWHTMLRTABORDER == true)
		{
			document.write("</td></tr></table>");
		}
				
		// initialise Screen Editor with defaults and Content
		var DHTMLCtrl = eval("document.all."+this.iframeId);
		DHTMLCtrl.toolbarArray = this.ToolbarBtns;
	}
	else
	{
		if (SIZESINPERCENT == false)
		{
			document.write("<TEXTAREA Name='"+this.FormElementName+"' ID='TXT"+this.iframeId+"' style='width:"+(this.width)+"px;height:"+(this.height)+"px;'></TEXTAREA>");
		}
		else {
			document.write("<TEXTAREA Name='"+this.FormElementName+"' ID='TXT"+this.iframeId+"' style='width:100%;height:"+(this.height)+"px;'></TEXTAREA>");
		}
	}
}


// *******************
// EXTERNAL INTERFACES
// *******************

// HTMLRichTextArea.prototype.GetHTML
// Returns the HTML that has been generated.  
HTMLRichTextArea.prototype.GetHTML = function(){
	
	// Ensure that we get latest changes
	EditorDisplayChanged(this.iframeId);
	
	// Get the source code object
	ctrlText = eval("document.all.TXT"+this.iframeId);		
	return(ctrlText.value);	
}
 

// HTMLRichTextArea.prototype.SetHTML
// Sets the HTML within the text
HTMLRichTextArea.prototype.SetHTML = function(strHTML){
	
	// Set the HTML
	var editorObject = GetEditorRef(this.iframeId);

	editorObject.body.innerHTML = strHTML;
	
	// Ensure that we get latest changes
	EditorDisplayChanged(this.iframeId);	
}


// HTMLRichTextArea.prototype.InsertHTML
// Inserts the HTML at the insertion point
HTMLRichTextArea.prototype.InsertHTML = function(strHTML){
	
	var editorObject = GetEditorRef(this.iframeId);
	PutHTML(this.iframeId, strHTML);
}


// HTMLRichTextArea.prototype.MakeReadOnly
// Makes the HTML RTA read only or write enabled.
HTMLRichTextArea.prototype.MakeReadOnly = function(blnReadOnly){

	var editorObject = GetEditorRef(this.iframeId);
	ctrlHTML = eval("document.all."+this.iframeId);
	ctrlReadOnly = eval("document.all.RO"+this.iframeId);
	ctrlToolBar = eval("document.all.TB"+this.iframeId);
	ctrlStatusBar = eval("document.all.SB"+this.iframeId);

	if (blnReadOnly == true)
	{	
		ctrlReadOnly.contentWindow.document.body.innerHTML = editorObject.body.innerHTML;
		ctrlHTML.style.display = 'none';
		ctrlToolBar.style.display = 'none';
		ctrlStatusBar.style.display = 'none';
		ctrlReadOnly.style.display = 'inline';
	}
	else {
		ctrlHTML.style.display = 'inline';
		ctrlToolBar.style.display = 'inline';
		ctrlStatusBar.style.display = 'inline';
		ctrlReadOnly.style.display = 'none';
	}
}



// *************
// TOOL BAR CODE
// *************

// HTMLRichTextArea.prototype.CreateToolbarButtonArray
// Creates array of toolbar controls with relevant parameters
HTMLRichTextArea.prototype.CreateToolbarButtonArray = function(){

	TbarBtns = new Array();
	
	// Array format for each button is...
	//ImageURL, Name, function, type, status, width, CMDID
	
	if (SHOWPRINTER == true)
	{
		pushItem(TbarBtns, new Array("print.gif", "Print", "document.all('" + this.iframeId + "').contentWindow.document.execCommand('Print');",BTN_TYPE_STANDARD,true,"25","Print"));
	}

	// Show the find button
	if (SHOWFINDBUTTON == true)
	{
		pushItem(TbarBtns, new Array("find.gif", "Find and Replace", "FindAndReplace('"+this.iframeId+"');", BTN_TYPE_SPECIAL,true,"25","FindAndReplace"));
	}
	
	// Show the spell check
	if (SHOWSPELLCHECKBUTTON == true)
	{
		pushItem(TbarBtns, new Array("SpellCheck.gif", "Check Spelling","window.showModalDialog(WBSC_FILE,document.all."+this.iframeId+".contentWindow.document.body,'dialogHeight: 300px; dialogWidth: 285px; center: Yes; help: No; resizable: No; status: No;');",BTN_TYPE_SPECIAL,true,"25","SpellCheck"));
		pushItem(TbarBtns, new Array("spacer.gif", "", "", BTN_TYPE_SPACER,true,"2","Spacer1"));
	}
 
	if (SHOWADDIMAGEBUTTON == true)
	{
		pushItem(TbarBtns, new Array("image.gif", "Insert image from hyperlink", "alert('WARNING : If you insert a local image from your hard drive, it will not be displayed. Enter Image URLs only!');"+"document.all('" + this.iframeId + "').contentWindow.document.execCommand('InsertImage', true);", BTN_TYPE_STANDARD,true,"25","InsertImage"));
	}

	if (SHOWADDFROMLIBRARY == true)
	{
		pushItem(TbarBtns, new Array("library.gif", "Insert image from library", "AddFromLibrary('"+this.iframeId+"');", BTN_TYPE_SPECIAL,true,"25","LoadFromLibrary"));
	}
		
	if (SHOWHYPERLINKBUTTON == true)
	{
		pushItem(TbarBtns, new Array("link.gif", "Insert HyperLink", "document.all('" + this.iframeId + "').contentWindow.document.execCommand('CreateLink'); UndoCheckPoint('" + this.iframeId + "', true);", BTN_TYPE_STANDARD,true,"25","CreateLink"));
		pushItem(TbarBtns, new Array("spacer.gif", "", "", BTN_TYPE_SPACER,true,"2","Spacer2"));
	}

	if (SHOWUNDOREDO == true)
	{
		pushItem(TbarBtns, new Array("undo.gif", "Undo", "UndoManager('" + this.iframeId + "');",BTN_TYPE_SPECIAL,true,"25","Undo"));
		pushItem(TbarBtns, new Array("redo.gif", "Redo", "RedoManager('" + this.iframeId + "');",BTN_TYPE_SPECIAL,true,"25","Redo"));
	}
	
	if (SHOWCUTCOPYPASTE == true)
	{
		pushItem(TbarBtns, new Array("cut.gif", "Cut", "document.all('" + this.iframeId + "').contentWindow.document.execCommand('Cut'); UndoCheckPoint('" + this.iframeId + "', true);", BTN_TYPE_STANDARD,true,"25","Cut"));
		pushItem(TbarBtns, new Array("copy.gif", "Copy", "document.all('" + this.iframeId + "').contentWindow.document.execCommand('Copy');", BTN_TYPE_STANDARD,true,"25","Copy"));
		pushItem(TbarBtns, new Array("paste.gif", "Paste", "ExecuteAPaste('" + this.iframeId + "');  UndoCheckPoint('" + this.iframeId + "', true);", BTN_TYPE_STANDARD,true,"25","Paste"));
		pushItem(TbarBtns, new Array("spacer.gif", "", "", BTN_TYPE_SPACER,true,"2","Spacer3"));
	}
	
	if (SHOWPRESENTATIONBUTTONS == true)
	{
		pushItem(TbarBtns, new Array("bold.gif","Bold","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('Bold'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","Bold"));
		pushItem(TbarBtns, new Array("italic.gif","Italic","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('Italic'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","Italic"));
		pushItem(TbarBtns, new Array("under.gif","Underline","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('Underline'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","Underline"));
		pushItem(TbarBtns, new Array("strikethrough.gif","Strike Through","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('Strikethrough'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","Strikethrough"));
	}
	
	if (SHOWSUPERSUBSCRIPT == true)
	{
		pushItem(TbarBtns, new Array("superscript.gif","Superscript","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('Superscript'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","Superscript"));
		pushItem(TbarBtns, new Array("subscript.gif","Subscript","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('Subscript'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","Subscript"));
		pushItem(TbarBtns, new Array("spacer.gif", "", "", BTN_TYPE_SPACER,true,"2","Spacer4"));
	}

	if (SHOWADDITIONALPRESENTATIONBUTTONS == true)
	{
		pushItem(TbarBtns, new Array("clearformatting.gif","Clear formatting","ClearFormatting('" + this.iframeId + "'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_STANDARD,true,"25","RemoveFormat"));
		pushItem(TbarBtns, new Array("spacer.gif", "", "", BTN_TYPE_SPACER,true,"2","Spacer20"));
		pushItem(TbarBtns, new Array("inindent.gif","Indent","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('Indent'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","Indent"));
		pushItem(TbarBtns, new Array("deindent.gif","De-Indent","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('Outdent'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","Outdent"));
		pushItem(TbarBtns, new Array("left.gif","Align Left","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('JustifyLeft'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","JustifyLeft"));	
		pushItem(TbarBtns, new Array("center.gif","Align Center","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('JustifyCenter'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","JustifyCenter"));
		pushItem(TbarBtns, new Array("right.gif","Align Right","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('JustifyRight'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","JustifyRight"));
		pushItem(TbarBtns, new Array("spacer.gif", "", "", BTN_TYPE_SPACER,true,"2","Spacer21"));
	}
	

	if (SHOWLIST == true)
	{
		pushItem(TbarBtns, new Array("numlist.gif","Numbered List","ActivateEditor('" + this.iframeId + "'); SetNumberedList('" + this.iframeId + "'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","InsertOrderedList"));
		pushItem(TbarBtns, new Array("bullist.gif","Bulletted List","ActivateEditor('" + this.iframeId + "'); SetUnOrderedList('" + this.iframeId + "'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","InsertUnorderedList"));
		pushItem(TbarBtns, new Array("spacer.gif", "", "", BTN_TYPE_SPACER,true,"2","Spacer5"));
	}

	if (SHOWHORIZONTALRULE == true)
	{
		pushItem(TbarBtns, new Array("horizontalrule.gif","Insert horizontal rule","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('InsertHorizontalRule'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_PRESENTATION,true,"25","InsertHorizontalRule"));
	}
	
	if (SHOWSPECIALCHARACTERS == true)
	{	
		pushItem(TbarBtns, new Array("symbol.gif","Insert symbol","ActivateEditor('" + this.iframeId + "'); InsertSymbol('" + this.iframeId + "'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_SPECIAL,true,"25","InsertSymbol"));
		pushItem(TbarBtns, new Array("emoticon.gif","Insert emoticon","ActivateEditor('" + this.iframeId + "'); InsertEmoticon('" + this.iframeId + "'); UndoCheckPoint('" + this.iframeId + "', true);",BTN_TYPE_SPECIAL,true,"25","InsertEmoticon"));
	}

	if (SHOWABSOLUTEPOSITIONING == true)
	{
		pushItem(TbarBtns, new Array("abspos.gif","Absolute positioning","ActivateEditor('" + this.iframeId + "'); document.all('" + this.iframeId + "').contentWindow.document.execCommand('AbsolutePosition');",BTN_TYPE_PRESENTATION,true,"25","AbsolutePosition"));
	}
	
	if (SHOWHEADINGDROPDOWN == true)
	{
		pushItem(TbarBtns, new Array(this.StyleDropDown(),"Font Name","",BTN_TYPE_DROPDOWN,true,"100","ParagraphType"));
	}

	if (SHOWFONTSTYLEMODIFICATION == true)
	{
		pushItem(TbarBtns, new Array(this.FontFamilyDropDowns(),"Style","",BTN_TYPE_DROPDOWN,true,"100","FontFamily"));
		pushItem(TbarBtns, new Array(this.FontSizeDropDowns(),"Font Size","",BTN_TYPE_DROPDOWN,true,"50","FontSize"));
		pushItem(TbarBtns, new Array("spacer.gif", "", "", BTN_TYPE_SPACER,true,"2","Spacer6"));
	}
	
	if (SHOWTABLESUPPORT == true)
	{
		pushItem(TbarBtns, new Array("instable.gif", "Insert Table","DisplayTableWindow('"+this.iframeId+"');",BTN_TYPE_TABLE,true,"25","InsertTable"));
		pushItem(TbarBtns, new Array("insrow.gif", "Insert Row","InsertRow('"+this.iframeId+"');",BTN_TYPE_TABLE,true,"25","InsertRow"));
		pushItem(TbarBtns, new Array("inscol.gif", "Insert Column","InsertColumn('"+this.iframeId+"');",BTN_TYPE_TABLE,true,"25","InsertColumn"));
		pushItem(TbarBtns, new Array("inscell.gif", "Insert Cell","InsertCell('"+this.iframeId+"');",BTN_TYPE_TABLE,true,"25","InsertCell"));
		pushItem(TbarBtns, new Array("delcell.gif","Delete Cell","DeleteCell('"+this.iframeId+"');",BTN_TYPE_TABLE,true,"25","DeleteCell"));
		pushItem(TbarBtns, new Array("delcol.gif", "Delete Column","DeleteColumn('"+this.iframeId+"');",BTN_TYPE_TABLE,true,"25","DeleteColumn"));
		pushItem(TbarBtns, new Array("delrow.gif", "Delete Row","DeleteRow('"+this.iframeId+"');",BTN_TYPE_TABLE,true,"25","DeleteRow"));
		// Not implemented pushItem(TbarBtns, new Array("spltcell.gif","Split Cell","xxxx;",BTN_TYPE_TABLE,true,"25","SplitCell"));
		// Not implemented pushItem(TbarBtns, new Array("mrgcell.gif", "Merge Cells","xxxx;",BTN_TYPE_TABLE,true,"25","MergeCells"));
		pushItem(TbarBtns, new Array("borders.gif", "Borders","ToggleGuideLines('"+this.iframeId+"');",BTN_TYPE_TABLE,true,"25","Borders"));
		pushItem(TbarBtns, new Array("spacer.gif", "", "", BTN_TYPE_SPACER,true,"2","Spacer7"));
	}
		
	if (SHOWCOLORSELECTION == true)
	{
		pushItem(TbarBtns, new Array("fgcolor.gif","Foreground Color","DisplayColorWindow('FG','"+this.iframeId+"')",BTN_TYPE_STANDARD,true,"25","ForeColor"));
		pushItem(TbarBtns, new Array("bgcolor.gif","Background Color","DisplayColorWindow('BG','"+this.iframeId+"')",BTN_TYPE_STANDARD,true,"25","BackColor"));
		pushItem(TbarBtns, new Array("spacer.gif", "", "", BTN_TYPE_SPACER,true,"2","Spacer8"));
	}


	if (SHOWDATETIME == true)
	{
		pushItem(TbarBtns, new Array("date.gif","Insert Date","InsertDate('"+this.iframeId+"')",BTN_TYPE_SPECIAL,true,"25","InsertDate"));
		pushItem(TbarBtns, new Array("time.gif","Insert Time","InsertTime('"+this.iframeId+"')",BTN_TYPE_SPECIAL,true,"25","InsertTime"));
		pushItem(TbarBtns, new Array("spacer.gif", "", "", BTN_TYPE_SPACER,true,"2","Spacer9"));
	}
	
	
	//special
	if (SHOWSOURCEBUTTON == true)
	{
		pushItem(TbarBtns, new Array("source.gif", "HTML Source","ToggleSourceView('"+this.iframeId+"');",BTN_TYPE_SRC,true,"25","ToggleSource"));
		pushItem(TbarBtns, new Array("spacer.gif", "", "", BTN_TYPE_SPACER,true,"2","Spacer10"));
	}


	// SHOWCUSTOMBUTTON1 shows custom button 1 if requested
	if (SHOWCUSTOMBUTTON1 == true)
	{
		pushItem(TbarBtns, new Array(CUSTOMBUTTON1IMAGE, CUSTOMBUTTON1CALLBACKTOOLTIP, CUSTOMBUTTON1CALLBACK + "('"+this.iframeId+"');",BTN_TYPE_SPECIAL,true,"25","CustomButton1"));
	}

	// SHOWCUSTOMBUTTON2 shows custom button 2 if requested
	if (SHOWCUSTOMBUTTON2 == true)
	{
		pushItem(TbarBtns, new Array(CUSTOMBUTTON2IMAGE, CUSTOMBUTTON2CALLBACKTOOLTIP, CUSTOMBUTTON2CALLBACK + "('"+this.iframeId+"');",BTN_TYPE_SPECIAL,true,"25","CustomButton2"));
	}

	// SHOWCUSTOMBUTTON3 shows custom button 3 if requested
	if (SHOWCUSTOMBUTTON3 == true)
	{
		pushItem(TbarBtns, new Array(CUSTOMBUTTON3IMAGE, CUSTOMBUTTON3CALLBACKTOOLTIP, CUSTOMBUTTON3CALLBACK + "('"+this.iframeId+"');",BTN_TYPE_SPECIAL,true,"25","CustomButton3"));
	}

	// Not implemented pushItem(TbarBtns, new Array("details.gif", "Show Details",""+this.iframeId+".ShowDetails = !"+this.iframeId+".ShowDetails;",BTN_TYPE_STANDARD,true,"25","ShowDetails"));
	
	
	return TbarBtns;
}


// HTMLRichTextArea.prototype.StyleDropDown
// This code is called when the style dropdown is rendered
HTMLRichTextArea.prototype.StyleDropDown = function(){
	var sDropDown = "<SELECT ID=\""+this.iframeId+"_ParagraphStyle\" unselectable='on' style='width:100px;font-size:xx-small' onchange=\"return ParagraphStyle('"+this.iframeId+"')\">"
			+ "<option value=\"Normal\">Normal</option>"
			+ "<option value=\"Heading 1\">Heading 1</option>"
			+ "<option value=\"Heading 2\">Heading 2</option>"
			+ "<option value=\"Heading 3\">Heading 3</option>"
			+ "<option value=\"Heading 4\">Heading 4</option>"
			+ "<option value=\"Heading 5\">Heading 5</option>"
			+ "<option value=\"Heading 6\">Heading 6</option>"
			+ "<option value=\"Address\">Address</option>"
			+ "<option value=\"Formatted\">Formatted</option>"
   			+ "</SELECT>";
	return sDropDown;
}


// HTMLRichTextArea.prototype.FontSizeDropDowns 
// This code is called when the font size drop down is rendered
HTMLRichTextArea.prototype.FontSizeDropDowns = function(){
	if (SHOWFONTSIZESINPOINTS == false)
	{
		var sDropDown = "<select ID='"+this.iframeId+"_FontSize' unselectable='on' style='width:50px;font-size:xx-small' onchange=\"return FontSize('"+this.iframeId+"')\">"
			+ "  <option value='1'>1</option>"
			+ "  <option value='2'>2</option>"
			+ "  <option value='3'>3</option>"
			+ "  <option value='4'>4</option>"
			+ "  <option value='5'>5</option>"
			+ "  <option value='6'>6</option>"
			+ "  <option value='7'>7</option>"
			+ "</select>";
			return sDropDown;
	}
	else {
		var sDropDown = "<select ID='"+this.iframeId+"_FontSize' unselectable='on' style='width:50px;font-size:xx-small' onchange=\"return FontSize('"+this.iframeId+"')\">"
			+ "  <option value='1'>8 pt</option>"
			+ "  <option value='2'>10 pt</option>"
			+ "  <option value='3'>12 pt</option>"
			+ "  <option value='4'>14 pt</option>"
			+ "  <option value='5'>18 pt</option>"
			+ "  <option value='6'>24 pt</option>"
			+ "  <option value='7'>36 pt</option>"
			+ "</select>";
			return sDropDown;
	}
}


// HTMLRichTextArea.prototype.FontFamilyDropDowns 
// This code is called when the font name drop down is rendered
HTMLRichTextArea.prototype.FontFamilyDropDowns = function(){
	var sDropDown = "<select ID='"+this.iframeId+"_FontName' unselectable='on' style='width:120px;font-size:xx-small' onchange=\"return FontName('"+this.iframeId+"')\">";

	for (index = 0; index < FONTLIST.length; index++)
	{
		sDropDown += "<option value='" + FONTLIST[index] + "'>" + FONTLIST[index] + "</option>";
	}
	sDropDown += "</select>";
		
	return sDropDown;
}


// HTMLRichTextArea.prototype.DrawToolBar
// Draws the toolbar
HTMLRichTextArea.prototype.DrawToolBar = function(){
	
	//buttonwidth
	var intButtonWidth = this.width;
	
	//..build toolbar
	strTBar = "<DIV ID='TB"+this.iframeId+"'>";
	strTBar += "<TABLE ID='TBTABLE"+this.iframeId+"' ondragstart=\"return false;\" WIDTH='"+this.width+"' onselectstart=\"return false\" CELLPADDING=0 CELLSPACING=0 BORDER=0>";
	strTBar += "<TR><TD>";
	
	//reset btn count
	var intBtnCount = 0;

	if (SHOWBOGUSTOOLBARHANDLES == true)
	{
		strTBar += "<img align='absbottom' SRC='" + this.ImgDir + "doublespacer.gif' unselectable='on'>";
		intBtnCount += 7;   // The width of the spacer
	}
	
	//loop through all buttons
	for (i=0;i<this.ToolbarBtns.length;i++){
		//include all buttons by default
		var blIncludeBtn = true;
		
		//examine button types...
		switch (this.ToolbarBtns[i][BTN_PROP_TYPE]){
			case BTN_TYPE_SRC:	//HTML Source buttons...
				if(!SHOWSOURCEBUTTON){	//Omit if set
					blIncludeBtn = false;
				}
				break;
			case BTN_TYPE_TABLE:
				if(!SHOWTABLESUPPORT){	//Table creation/editing
					blIncludeBtn = false;	//Omit if set
				}
				break;
			case BTN_TYPE_SPACER:
				if(!SHOWTOOLBARSPACERS){	//Spacers
					blIncludeBtn = false;	//Omit if set
				}
				break;
			default:
				//include all others by default
				break;
		}
		
		if(this.ToolbarBtns[i][BTN_PROP_TYPE] == BTN_TYPE_INPUT && CHARACTERLIMIT == ""){
			blIncludeBtn = false;	//Omit if set
		}
				
		//if button has not been excluded...
		if (blIncludeBtn){
			intBtnCount += parseInt(this.ToolbarBtns[i][BTN_PROP_WIDTH]);	//increase button row count
			strTBar += ""; //+ intBtnCount

			if (SIZESINPERCENT == false)
			{
				if (intBtnCount > intButtonWidth){	//if we have filled row...
					strTBar += "</TD></TR><TR><TD>";	//..start another
					intBtnCount = 0;
					if (SHOWBOGUSTOOLBARHANDLES == true)
					{
						strTBar += "<img align='absbottom' SRC='" + this.ImgDir + "doublespacer.gif' unselectable='on'>";
						intBtnCount += 7;   // The width of the spacer
					}
					intBtnCount += parseInt(this.ToolbarBtns[i][BTN_PROP_WIDTH]);	//reset button count
				}
			}
			else {
				if (intBtnCount > MINBUTTONROWWIDTH){		//if we have filled row...
					strTBar += "</TD></TR><TR><TD>";	//..start another
					intBtnCount = 0;
					if (SHOWBOGUSTOOLBARHANDLES == true)
					{
						strTBar += "<img align='absbottom' SRC='" + this.ImgDir + "doublespacer.gif' unselectable='on'>";
						intBtnCount += 7;   // The width of the spacer
					}
					intBtnCount += parseInt(this.ToolbarBtns[i][BTN_PROP_WIDTH]);	//reset button count
				}
			}
						
			//Display input box
			if(this.ToolbarBtns[i][BTN_PROP_TYPE] == BTN_TYPE_INPUT)
			{
				strTBar += this.ToolbarBtns[i][BTN_PROP_IMGURL];
			}
			//display dropdown
			else if(this.ToolbarBtns[i][BTN_PROP_TYPE] == BTN_TYPE_DROPDOWN)
			{
				strTBar += this.ToolbarBtns[i][BTN_PROP_IMGURL];			
			} 
			//display spacer if requested
			else if(this.ToolbarBtns[i][BTN_PROP_TYPE] == BTN_TYPE_SPACER)
			{
				if (SHOWTOOLBARSPACERS == true)
				{
					strTBar += "<IMG align=absmiddle unselectable='on' SRC='"+this.ImgDir+this.ToolbarBtns[i][BTN_PROP_IMGURL]+"'>";
				}
			} 
			//display button
			else
			{
				strTBar += "<IMG align=absmiddle ";
				
				//examine command ID ... needed for disabling controls
				if(this.ToolbarBtns[i][BTN_PROP_CMDID] !== "")
				{
					strTBar += "ID='"+this.iframeId+this.ToolbarBtns[i][BTN_PROP_CMDID]+"'";
				}
				strTBar += " unselectable='on' width=23 height=22 onclick=\""+this.ToolbarBtns[i][BTN_PROP_FUNC]+"; ButtonStates('"+this.iframeId+"');\" TITLE='"+this.ToolbarBtns[i][BTN_PROP_TITLE]+"' SRC='"+this.ImgDir+this.ToolbarBtns[i][BTN_PROP_IMGURL]+"' onmouseover='this.style.backgroundColor=\"#d1e2fe\";' onmouseout='this.style.backgroundColor=\"\";' class='BUTTONENABLED'>";
			}
		}
	}
	
	//finish toolbar
	strTBar += "</TD></TR>";
	strTBar += "</TABLE></DIV>";
	
	//write to screen
	document.write(strTBar);
}



// **************
// EVENT HANDLERS
// **************


// EditorDisplayChanged
// Called whenever the contents of the HTML RTA changes.  The HTML is updated and the button 
// states are set. Also, if the caller has requested a callback whenever the text changes
// then this happens here.
function EditorDisplayChanged(iframeId){
		
	// The IFrame contain all of the member variables like the toolbar
	var iframeObject = GetIFrameRef(iframeId);
	
	// The editor is the document within the IFrame that contains the HTML
	var editorObject = GetEditorRef(iframeId);

	ctrlText = eval("document.all.TXT"+iframeId);
	ctrlReadOnly = eval("document.all.RO"+iframeId);

	// as long as source view is off...
	if(ctrlText.style.display == "none")
	{

		// If the user has specifed an event cather routine that is to be called when 
		// the text changes then call it and update the text area with the HTML
		if (EVENTCATCHER != "")
		{
			if (ctrlText.value != editorObject.body.innerHTML)
			{
				eval(EVENTCATCHER);
			}
		}
		else {
			// Otherwise just update the source code with the HTML
			ctrlText.value = editorObject.body.innerHTML;
		}

		// Set the buttons to be either on, latched or disabled
		// depending on the text that the cursor is over.
		ButtonStates(iframeId);						
	} 
}

// ButtonStates
// Go through each tool bar button, get its associated command and see
// whether this command can be applied to the document. Set the state of the tool
// bar buttons depending on the result of the .queryCommandSupported function.
function ButtonStates(iframeId) {
	var i;
	var strStatus = "";

	// The IFrame contain all of the member variables like the toolbar
	var iframeObject = GetIFrameRef(iframeId);
	
	// The editor is the document within the IFrame that contains the HTML
	var editorObject = GetEditorRef(iframeId);

	// Get the source code object
	ctrlText = eval("document.all.TXT"+iframeId);		
	
	// Get the overwrite status bar
	ctrlOverwrite = eval("document.all.Overwrite"+iframeId);		

	// Get the insert status bar
	ctrlInsert = eval("document.all.Insert"+iframeId);		

	// as long as source view is off...
	if(ctrlText.style.display == "none")
	{
		//loop for most of the buttons that have COMMAND ID's
		for (i=0; i < iframeObject.toolbarArray.length; i++) 
		{
			try 
			{
				// The table options are always on
				if ((iframeObject.toolbarArray[i][BTN_PROP_TYPE] != BTN_TYPE_TABLE) && (iframeObject.toolbarArray[i][BTN_PROP_TYPE] != BTN_TYPE_SPECIAL)  && (iframeObject.toolbarArray[i][BTN_PROP_TYPE] != BTN_TYPE_SRC))
				{	
					// If this button has a command associated with it then
					if (iframeObject.toolbarArray[i][BTN_PROP_CMDID] != "")
					{	
						// Get the command associated with this button
						strCmd = iframeObject.toolbarArray[i][BTN_PROP_CMDID];

						// Get a reference tothe toolbar button based on the button number						
						var ImgRef = GetToolbarButtonRefFromNumber(iframeId, i);

						// Get whether IE thinks this command is available at the moment
						if (editorObject.queryCommandSupported(strCmd) == false)
						{
							// Set its class to be disabled. See the CSS defined at the top
							ImgRef.className = "BUTTONDISABLED";
							ImgRef.disabled = true;
						} 
						else 
						{
							// Check whether this command has already been applied...
							if (editorObject.queryCommandState(strCmd) == true)
							{
								// It has so set its class to be turned on. See the CSS defined at the top
								ImgRef.className = "BUTTONLATCHED";
								ImgRef.disabled = false;
								
								if (iframeObject.toolbarArray[i][BTN_PROP_TITLE] != null)
								{
									strStatus += iframeObject.toolbarArray[i][BTN_PROP_TITLE] + ' ';
								}
							} 
							else {
								// Otherwise simply enable it
								ImgRef.className = "BUTTONENABLED";
								ImgRef.disabled = false;
							}
						}			
					}		
				}		
			}
			catch(e)
			{
				// Not too much we can do here. Occurs only occasionally in very unusual circumstances
			}
		}

			
		// This is the paragraph / heading style.
		if (SHOWHEADINGDROPDOWN == true)
		{
			// Get the paragraph / heading style
			var ctrlPara = eval("document.all."+iframeId+"_ParagraphStyle");
			if (editorObject.queryCommandSupported("FormatBlock") == false)
			{
				ctrlPara.disabled = true;
			}
			else {
				ctrlPara.disabled = false;
				ctrlPara.value = editorObject.queryCommandValue("FormatBlock");
				if (editorObject.queryCommandValue("FormatBlock").indexOf("List") == -1)
				{
					if (editorObject.queryCommandValue("FormatBlock") != null)
					{
						strStatus += editorObject.queryCommandValue("FormatBlock") + ' ';
					}
				}
			}
		}
	
		// This is the font name and size
		if (SHOWFONTSTYLEMODIFICATION == true)
		{			
			// Get the font name
			var ctrlFontName = eval("document.all."+iframeId+"_FontName");		
			if (editorObject.queryCommandSupported("FontName") == false)
			{
				ctrlFontName.disabled = true;
			}
			else {
				ctrlFontName.disabled = false;
				ctrlFontName.value = editorObject.queryCommandValue("FontName");
				if (editorObject.queryCommandValue("FontName") != null)
				{
					strStatus += editorObject.queryCommandValue("FontName") + ' ';
				}
			}

			// Get the font size
			var ctrlSize = eval("document.all."+iframeId+"_FontSize");
			if (editorObject.queryCommandSupported("FontSize") == false)
			{
				ctrlSize.disabled = true;
			}
			else {
				ctrlSize.disabled = false;
				ctrlSize.value = editorObject.queryCommandValue("FontSize");
				if (editorObject.queryCommandValue("FontSize") != null)
				{
					strStatus += editorObject.queryCommandValue("FontSize") + ' ';
				}
			}
		} 
	
		// Set the state of the table buttons
		if (SHOWTABLESUPPORT == true)
		{
			var strClass = "";
			
			// Find out where the cusor is
			var objRange = editorObject.selection.createRange();	
	
			var blnInATable = false;
			var blnDisabled;
			try
			{
				// Find the element that that cursor is in
				var parentObject = objRange.parentElement();
				while (parentObject != null)
				{			
					// Go up the element tree until we find a row				
					if (parentObject.tagName.toUpperCase() == "TABLE")
					{			
						blnInATable = true;
						break;
					}	
					else {
						// Go up through the tree
						var parentObject = parentObject.parentElement;			
					}
				}
			
				if (blnInATable == true)
				{
					strClass = "BUTTONENABLED";
					blnDisabled = false;
				}
				else {
					strClass = "BUTTONDISABLED";
					blnDisabled = true;
				}
			}
			// objRange.parentElement() will throw an error during table resizes and the like
			catch(e)
			{
				blnInATable = false;
			}
			
			GetToolbarButtonRefFromAction(iframeId, "InsertTable").className = "BUTTONENABLED";
			
			// Set the state of the other table buttons to be enalbed or disabled depending on whether 
			// we are in a table or not
			GetToolbarButtonRefFromAction(iframeId, "InsertRow").className = strClass;
			GetToolbarButtonRefFromAction(iframeId, "InsertRow").disabled = blnDisabled;
			
			GetToolbarButtonRefFromAction(iframeId, "InsertColumn").className = strClass;
			GetToolbarButtonRefFromAction(iframeId, "InsertColumn").disabled = blnDisabled;
			
			GetToolbarButtonRefFromAction(iframeId, "InsertCell").className = strClass;
			GetToolbarButtonRefFromAction(iframeId, "InsertCell").disabled = blnDisabled;
			
			GetToolbarButtonRefFromAction(iframeId, "DeleteCell").className = strClass;
			GetToolbarButtonRefFromAction(iframeId, "DeleteCell").disabled = blnDisabled;
			
			GetToolbarButtonRefFromAction(iframeId, "DeleteColumn").className = strClass;
			GetToolbarButtonRefFromAction(iframeId, "DeleteColumn").disabled = blnDisabled;
			
			GetToolbarButtonRefFromAction(iframeId, "DeleteRow").className = strClass;
			GetToolbarButtonRefFromAction(iframeId, "DeleteRow").disabled = blnDisabled;
			
			// Not implemented GetToolbarButtonRefFromAction(iframeId, "SplitCell").className = strClass;
			// Not implemented GetToolbarButtonRefFromAction(iframeId, "MergeCells").className = strClass;
		}
				

		// If we have the redo/undo enabled then set their availability
		if (SHOWUNDOREDO == true)
		{
			if (IsUndoAvailable(iframeId))
			{
				GetToolbarButtonRefFromAction(iframeId, "Undo").className = "BUTTONENABLED";
				GetToolbarButtonRefFromAction(iframeId, "Undo").disabled = false;
			}		
			else {
				GetToolbarButtonRefFromAction(iframeId, "Undo").className = "BUTTONDISABLED";
				GetToolbarButtonRefFromAction(iframeId, "Undo").disabled = true;
			}

			if (IsRedoAvailable(iframeId))
			{
				GetToolbarButtonRefFromAction(iframeId, "Redo").className = "BUTTONENABLED";
				GetToolbarButtonRefFromAction(iframeId, "Redo").disabled = false;
			}		
			else {
				GetToolbarButtonRefFromAction(iframeId, "Redo").className = "BUTTONDISABLED";
				GetToolbarButtonRefFromAction(iframeId, "Redo").disabled = true;
			}
		}


		// Set the text in the status bar
		if (strStatus.length <= 4)
		{
			TextProperties.innerHTML = "&nbsp;";
		}
		else {
			TextProperties.innerText = strStatus;
		}

		if (editorObject.queryCommandState("OverWrite") == true)
		{
			ctrlInsert.style.color = 'gray';
			ctrlOverwrite.style.color = 'black';
		}
		else 
		{
			ctrlOverwrite.style.color = 'gray';
			ctrlInsert.style.color = 'black';
		}		
	}
}


// ParagraphStyle
// Called when the user changes the paragraph style
function ParagraphStyle(iframeId){
	// Get a reference to the paragraph style drop downlist 
	var objSelectRef = eval("document.all."+iframeId+"_ParagraphStyle");

	// The editor is the document within the IFrame that contains the HTML
	var editorObject = GetEditorRef(iframeId);

	editorObject.execCommand("FormatBlock", true, objSelectRef.value);

	// The IFrame contain all of the member variables like the toolbar
	var iframeObject = GetIFrameRef(iframeId);
	iframeObject.focus();
	
	UndoCheckPoint(iframeId, true);
	ButtonStates(iframeId);
}	


// FontSize
// Called when the user changes the font size
function FontSize(iframeId){
	// Get a reference to the font size drop downlist 
	var objSelectRef = eval("document.all."+iframeId+"_FontSize");
	
	// The editor is the document within the IFrame that contains the HTML
	var editorObject = GetEditorRef(iframeId);

	// The editor is the document within the IFrame that contains the HTML	
	editorObject.execCommand("FontSize", true, parseInt(objSelectRef.value));

	// The IFrame contain all of the member variables like the toolbar
	var iframeObject = GetIFrameRef(iframeId);
	iframeObject.focus();

	UndoCheckPoint(iframeId, true);
	ButtonStates(iframeId);

}	


// FontName
// Called when the user changes the font name
function FontName(iframeId){
	// Get a reference to the font name drop downlist 
	var objSelectRef = eval("document.all."+iframeId+"_FontName");
	
	// The editor is the document within the IFrame that contains the HTML
	var editorObject = GetEditorRef(iframeId);

	// The editor is the document within the IFrame that contains the HTML	
	editorObject.execCommand("FontName", true, objSelectRef.value);

	UndoCheckPoint(iframeId, true);
	ButtonStates(iframeId);

}	


// DisplayTableWindow
// Called by the toolbar to create a table for insertion in the editor.
// the entire window content is generated from this function, there is no extra HTML file.
var winTable = null;
function DisplayTableWindow(iframeId)
{

	strOP = "<HTML><HEAD><TITLE>Create Table</TITLE>"+
	"<STYLE>.txt{width:50px;}TD{font-size:8pt;letter-spacing:-0.5pt}</STYLE>"+
	"</HEAD><BODY bgcolor=buttonface topmargin=2 leftmargin=2 style='border:none;font-family:verdana;font-size:8pt;letter-spacing:-0.5pt'>"+
	"<SCR" + "IPT LANGUAGE=javascript>\n"+
	"<!--\n"+
	"function ValidateTable(){\n"+
	"	if (isNaN(parseInt(PAD.value))){alert(\"Cell Padding value not valid\");return false;}\n"+
	"	if (isNaN(parseInt(SPC.value))){alert(\"Cell Spacing value not valid\");return false;}\n"+
	"	if (isNaN(parseInt(BRD.value))){alert(\"Border value not valid\");return false;}\n"+
	"	if (isNaN(parseInt(ROW.value))){alert(\"Rows value not valid\");return false;}\n"+
	"	if (isNaN(parseInt(COL.value))){alert(\"Columns value not valid\");return false;}\n"+
	"	window.opener.InsertTable(PAD.value,SPC.value,BRD.value,ROW.value,COL.value,'"+iframeId+"',window);\n"+
	"}\n"+
	"/" + "/-->\n"+
	"</SC"+"RIPT><TABLE>"+
	"<TR><TD>Cell Padding : </TD><TD><INPUT class=txt VALUE=2 TYPE=TEXT ID=PAD></TD></TR>"+
	"<TR><TD>Cell Spacing : </TD><TD><INPUT class=txt VALUE=1 TYPE=TEXT ID=SPC></TD></TR>"+
	"<TR><TD>Border : </TD><TD><INPUT class=txt VALUE=1 TYPE=TEXT ID=BRD></TD></TR>"+
	"<TR><TD>Rows : </TD><TD><INPUT class=txt VALUE=2 TYPE=TEXT ID=ROW></TD></TR>"+
	"<TR><TD>Columns : </TD><TD><INPUT class=txt VALUE=3 TYPE=TEXT ID=COL></TD></TR>"+
	"<TR><TD></TD><TD><INPUT onclick=\"ValidateTable();\" TYPE=BUTTON VALUE=\"Insert Table\" id=BUTTON1 name=BUTTON1></TD></TR>"+
	"</TABLE></BODY></HTML>";

	try
	{
		winTable.focus();
	}
	catch(e)
	{
		winTable = null;
	}

	if (winTable == null)
	{
		winTable = window.open("about:blank", "wincolor", "width=250,height=180,toolbar=no,location=no,menubar=no,status=no,scrollbars=no,resizable=no");
		var myDoc = winTable.document;
		myDoc.open("text/html");
		myDoc.write(strOP);
		myDoc.close();
		myDoc.title = "Create Table";
	}	
}


// InsertTable
// This function is called by the HTML that was dynamically created in the DisplayTableWindow
// function.  It is called when the user creates a table.
function InsertTable(strPad,strSpace,strBord,strRows,strCols,iframeId,winRef) 
{
	try 
	{	
		winRef.close();
	
		var objiframeId = eval("document.all."+iframeId);
	
		// Create the table
		var strTable = "<table border='" + strBord + "' cellpadding='" + strPad + "' cellspacing='" + strSpace + "'>";
		for (intRows = 0; intRows < strRows; intRows++)
		{
			strTable += "<tr>";
			for (intCols = 0; intCols < strCols; intCols++)
			{
				strTable += "<td></td>";
			}
			strTable += "</tr>";
		}
		strTable += "</table>";
			
		PutHTML(iframeId, strTable);
	}
	catch(e)
	{
		alert("It was not possible to insert a table while this text is selected.");
	}
		
}


// InsertRow
// Inserts a row into the table
function InsertRow(iframeId) {

	try
	{	
		// The editor is the document within the IFrame that contains the HTML
		var editorObject = GetEditorRef(iframeId);

		// Get the TextRange object covering the current cursor location
		var objRange = editorObject.selection.createRange();
	
		// Get the element in which the cursor lies.
		var parentObject = objRange.parentElement();

		// Go up through the element tree until we hit the top or a table row.
		while (parentObject != null)
		{
			// Go up the element tree until we find a row
			if (parentObject.tagName.toUpperCase() == "TR")
			{
				// Get a reference to the row that we are on
				var objRow = parentObject;
				
				// Get a reference to the row's table
				var objTable = parentObject.parentElement;
												
				// Insert a row where the current row is
				var newRow = objTable.insertRow(objRow.sectionRowIndex);
				
				// Add the same number of cells as the adjacent row
				for (intCell = 0; intCell < Math.max(objTable.rows(objRow.sectionRowIndex).cells.length,1); intCell++)
				{
					newRow.insertCell();
				}
							
				break;
			}
			else {
				parentObject = parentObject.parentElement;
			}
		}		
		UndoCheckPoint(iframeId, true);
		ButtonStates(iframeId);

	}
	catch(e)
	{
		alert("It was not possible to insert a row while this text is selected.");
	}

}


// InsertColumn
// Inserts a column into the table
function InsertColumn(iframeId) {
	
	try 
	{
		// The editor is the document within the IFrame that contains the HTML
		var editorObject = GetEditorRef(iframeId);

		// Get the TextRange object covering the current cursor location
		var objRange = editorObject.selection.createRange();
	
		// Get the element in which the cursor lies.
		var parentObject = objRange.parentElement();

		// Go up through the element tree until we hit the top or a table row.
		while (parentObject != null)
		{
			// Go up the element tree until we find a row
			if (parentObject.tagName.toUpperCase() == "TD")
			{
				// Get a reference to the row that we are on
				objCell = parentObject;
			}
			else if (parentObject.tagName.toUpperCase() == "TR")
			{
				// Get a reference to the row that we are on
				objRow = parentObject;		
			}
			else if (parentObject.tagName.toUpperCase() == "TABLE")
			{
				// Get a reference to the row that we are on
				objTable = parentObject;		
				break;
			}
			
			// Keep going up the tree
			parentObject = parentObject.parentElement;
		}
												
		// Check that everything was found
		if ((objCell != null) && (objRow != null) && (objTable != null))
		{
			// Add a cell to each row.
			for (intRow = 0; intRow < objTable.rows.length; intRow++)
			{
				objTable.rows(intRow).insertCell(objCell.cellIndex);
			}
		}		

		UndoCheckPoint(iframeId, true);
		ButtonStates(iframeId);

	}
	catch(e)
	{
		alert("It was not possible to insert a column while this text is selected.");
	}
}


// InsertCell
// Inserts a cell into the table
function InsertCell(iframeId) {
	
	try 
	{
		// The editor is the document within the IFrame that contains the HTML
		var editorObject = GetEditorRef(iframeId);

		// Get the TextRange object covering the current cursor location
		var objRange = editorObject.selection.createRange();
	
		// Get the element in which the cursor lies.
		var parentObject = objRange.parentElement();

		// Go up through the element tree until we hit the top or a table row.
		while (parentObject != null)
		{
			// Go up the element tree until we find a row
			if (parentObject.tagName.toUpperCase() == "TD")
			{
				// Get a reference to the row that we are on
				objCell = parentObject;
			}
			else if (parentObject.tagName.toUpperCase() == "TR")
			{
				// Get a reference to the row that we are on
				objRow = parentObject;		
				break;
			}
			
			// Keep going up the tree
			parentObject = parentObject.parentElement;
		}
												
		// Check that everything was found
		if ((objCell != null) && (objRow != null))
		{
			// Insert the cell
			objRow.insertCell(objCell.cellIndex);
		}		

		UndoCheckPoint(iframeId, true);
		ButtonStates(iframeId);
	}
	catch(e)
	{
		alert("It was not possible to insert a cell while this text is selected.");
	}
}

// DeleteCell
// Delets a cell from the table
function DeleteCell(iframeId) {
	
	try
	{
		// The editor is the document within the IFrame that contains the HTML
		var editorObject = GetEditorRef(iframeId);

		// Get the TextRange object covering the current cursor location
		var objRange = editorObject.selection.createRange();
	
		// Get the element in which the cursor lies.
		var parentObject = objRange.parentElement();

		// Go up through the element tree until we hit the top or a table row.
		while (parentObject != null)
		{
			// Go up the element tree until we find a row
			if (parentObject.tagName.toUpperCase() == "TD")
			{
				// Get a reference to the row that we are on
				objCell = parentObject;
			}
			else if (parentObject.tagName.toUpperCase() == "TR")
			{
				// Get a reference to the row that we are on
				objRow = parentObject;		
				break;
			}
			
			// Keep going up the tree
			parentObject = parentObject.parentElement;
		}
												
		// Check that everything was found
		if ((objCell != null) && (objRow != null))
		{
			// Insert the cell
			objRow.deleteCell(objCell.cellIndex);
		}			

		UndoCheckPoint(iframeId, true);
		ButtonStates(iframeId);
	}
	catch(e)
	{
		alert("It was not possible to delete a cell while this text is selected.");
	}
}


// DeleteColumn
// Deletes a column from the table
function DeleteColumn(iframeId) 
{	
	try
	{
		// The editor is the document within the IFrame that contains the HTML
		var editorObject = GetEditorRef(iframeId);

		// Get the TextRange object covering the current cursor location
		var objRange = editorObject.selection.createRange();
	
		// Get the element in which the cursor lies.
		var parentObject = objRange.parentElement();

		// Go up through the element tree until we hit the top or a table row.
		while (parentObject != null)
		{
			// Go up the element tree until we find a row
			if (parentObject.tagName.toUpperCase() == "TD")
			{
				// Get a reference to the row that we are on
				objCell = parentObject;
			}
			else if (parentObject.tagName.toUpperCase() == "TR")
			{
				// Get a reference to the row that we are on
				objRow = parentObject;		
			}
			else if (parentObject.tagName.toUpperCase() == "TABLE")
			{
				// Get a reference to the row that we are on
				objTable = parentObject;		
				break;
			}
			
			// Keep going up the tree
			parentObject = parentObject.parentElement;
		}
												
		// Check that everything was found
		if ((objCell != null) && (objRow != null) && (objTable != null))
		{
			// Record the column of the cell that we are in
			intColumn = objCell.cellIndex;
			
			// Add a cell to each row.
			for (intRow = 0; intRow < objTable.rows.length; intRow++)
			{
				if (objTable.rows(intRow).cells.length > intColumn)
				{
					objTable.rows(intRow).deleteCell(intColumn);
				}
			}
		}		

		UndoCheckPoint(iframeId, true);
		ButtonStates(iframeId);
	}
	catch(e)
	{
		alert("It was not possible to delete a column while this text is selected.");
	}	
}


// DeleteRow
// Deletes a row from the table
function DeleteRow(iframeId) 
{	
	try
	{
		// The editor is the document within the IFrame that contains the HTML
		var editorObject = GetEditorRef(iframeId);

		// Get the TextRange object covering the current cursor location
		var objRange = editorObject.selection.createRange();
	
		// Get the element in which the cursor lies.
		var parentObject = objRange.parentElement();

		// Go up through the element tree until we hit the top or a table row.
		while (parentObject != null)
		{
			if (parentObject.tagName.toUpperCase() == "TR")
			{
				// Get a reference to the row that we are on
				objRow = parentObject;		
			}
			else if (parentObject.tagName.toUpperCase() == "TABLE")
			{
				// Get a reference to the row that we are on
				objTable = parentObject;		
				break;
			}
			
			// Keep going up the tree
			parentObject = parentObject.parentElement;
		}
												
		// Check that everything was found
		if ((objRow != null) && (objTable != null))
		{
			objTable.deleteRow(objRow.sectionRowIndex);		
		}		

		UndoCheckPoint(iframeId, true);
		ButtonStates(iframeId);
	}
	catch(e)
	{
		alert("It was not possible to delete a row while this text is selected.");
	}	
}


// DisplayColorWindow
// Called by the toolbar to change the colour of text or background colors.
// the entire window content is generated from this function, there is no extra HTML file.
var colorWindow = null;
function DisplayColorWindow(mode,iframeId){
    
	var colorWidth = 500;
	var colorHeight = 100;

	// colorWindow get set to null when a color is selected. However it may have been closed
	// by pressing the 'x'.  In which case we don't know about it.
	try 
	{
		colorWindow.focus();
	}	
	catch(e)
	{
		colorWindow = null;
	}
	
	if (colorWindow == null)
	{
		//mode : BG, FG
		colorWindow = window.open("about:blank", "wincolor", "width=" + colorWidth + ",height=" + colorHeight + ",left=" + ((screen.width / 2) - (colorWidth / 2)) + ",top=" + ((screen.height / 4) - (colorHeight / 2)) + ",toolbar=no,location=no,menubar=no,status=no,scrollbars=no,resizable=no");
		var myDoc = colorWindow.document;

		//color table
		colors = new Array('0','3','6','9','C','F');

		strColorTable = "<TABLE onclick='assign();' onmouseover='toggleClass();' onmouseout='toggleClass();' WIDTH=100% CELLPADDING=0 CELLSPACING=0 BORDER=0>";
		for(i=0;i<colors.length;i++){
			strColorTable += "<TR>";
			for(j=0;j<colors.length;j++){
				for(k=0;k<colors.length;k++){
					strColorTable += "<TD class=col bgcolor=#"+colors[k]+colors[k]+colors[i]+colors[i]+colors[j]+colors[j]+" title=#"+colors[k]+colors[k]+colors[i]+colors[i]+colors[j]+colors[j]+">&nbsp;</TD>";
				}			
			}
			strColorTable += "</TR>";
		}
		strColorTable += "</TABLE>";
	
		colorWindow.focus();
	
		myDoc.open("text/html");
		myDoc.write("<HTML><HEAD></HEAD>"+
		"<STYLE>TD{font-size:8pt;}.col{border:solid 1px buttonface;cursor:hand;}.colO{cursor:hand;border:solid 1px black;}</STYLE>"+
		"<SCRIPT>\n<!--\n"+
		"function toggleClass(){\n"+
		"	var el = window.event.srcElement;if(el.className=='col'){el.className='colO'}else if(el.className=='colO'){el.className='col'}\n"+
		"}\n"+
		"function assign(){\n"+
		"	var el = window.event.srcElement;if(el.className=='col'||el.className=='colO'){window.opener.SetColor('"+mode+"', el.bgColor, '"+iframeId+"',window);}\n"+
		"}\n--></SCR"+"IPT>"+
		"<BODY bgcolor=buttonface topmargin=2 leftmargin=2 style='border:none;font-family:verdana;font-size:8pt;letter-spacing:-0.5pt' onselectstart='return false'>"+
		strColorTable+
		"</BODY></HTML>");
		myDoc.close();

	}
	else {
		var myDoc = colorWindow.document;
	}	
	
	// Set the title of the window
	if(mode == "FG"){
		myDoc.title = "Foreground Color - Click To Assign";
	} else if(mode == "BG"){
		myDoc.title = "Background Color - Click To Assign";
	} else {
		//do nothing
	}

}

// SetColor
// callback from color window. refer to the HTML generated in DisplayColorWindow.
// Sets background/foreground color of selection
function SetColor(mode,color,iframeId,winRef){

	colorWindow.close();	//close popup
	colorWindow = null;
	
	var editorObject = GetEditorRef(iframeId);
		
	if (mode == "BG"){
		strCMD = "BackColor";
	} else if (mode == "FG"){
		strCMD = "ForeColor";
	} else{
		//not valid
	}
	
	editorObject.execCommand(strCMD,true, color);

	UndoCheckPoint(iframeId, true);
	ButtonStates(iframeId);
}


// ToggleSourceView
// Switch between HTML and design view
function ToggleSourceView(iframeId){

	// The IFrame contain all of the member variables like the toolbar
	var iframeObject = GetIFrameRef(iframeId);
	
	// The editor is the document within the IFrame that contains the HTML
	var editorObject = GetEditorRef(iframeId);

	ctrlText = eval("document.all.TXT"+iframeId);
	var ctrlStatusBar = eval("document.all.SB"+iframeId);
	
	//display TEXTAREA
	if(ctrlText.style.display == "none"){
		ctrlText.value = editorObject.body.innerHTML;
		ctrlText.style.width = iframeObject.clientWidth;
		ctrlText.style.display = "block";
		iframeObject.style.display = "none";
		ctrlStatusBar.style.display = "none";

		//knock out all toolbar controls except source view
		for(var i=0;i < iframeObject.toolbarArray.length; i++) {
		

			//knock out all toolbar controls except source view
			for(var i=0;i < iframeObject.toolbarArray.length; i++) {
		
				// Always show the source button
				if (iframeObject.toolbarArray[i][BTN_PROP_TYPE] != BTN_TYPE_SRC)
				{
					if ((iframeObject.toolbarArray[i][BTN_PROP_TYPE] != BTN_TYPE_DROPDOWN) && (iframeObject.toolbarArray[i][BTN_PROP_TYPE] != BTN_TYPE_SPACER))
					{
						var ImgRef = GetToolbarButtonRefFromNumber(iframeId, i);
						ImgRef.className = "BUTTONDISABLED";
						ImgRef.disabled = true;
					}
					else {
						ImgRef.disabled = true;
					}
				}
			}		
		}
	
		var ctrlPara = eval("document.all."+iframeId+"_ParagraphStyle");
		var ctrlSize = eval("document.all."+iframeId+"_FontSize");
		var ctrlName = eval("document.all."+iframeId+"_FontName");
		
		ctrlPara.disabled = true;
		ctrlSize.disabled = true;
		ctrlName.disabled = true;
		
	// display OBJECT - this will call the displayChanged() event which will inturn 
	// reinstate the appropriate toolbar buttons
	} else {
		ctrlText.style.display = "none";
		editorObject.body.innerHTML = ctrlText.value;
		iframeObject.style.display = "block";

		if (SHOWSTATUSBAR == true)
		{
			ctrlStatusBar.style.display = "inline";
		}
		else {
			ctrlStatusBar.style.display = "none";
		}

		//knock out all toolbar controls except source view
		for(var i=0;i < iframeObject.toolbarArray.length; i++) {
		
			if ((iframeObject.toolbarArray[i][BTN_PROP_TYPE] != BTN_TYPE_DROPDOWN) && (iframeObject.toolbarArray[i][BTN_PROP_TYPE] != BTN_TYPE_SPACER))
			{
				var ImgRef = GetToolbarButtonRefFromNumber(iframeId, i);
				ImgRef.disabled = false;
				ImgRef.className = "BUTTONENABLED";
			}
		}
	}	
}

// EditorLoaded
// Called when the IFRAME is loaded. Hook into the events of the IFrame's document
function EditorLoaded(iframeId, strDefaultText)
{
	// The IFrame contain all of the member variables like the toolbar
	var iframeObject = GetIFrameRef(iframeId);
	
	// Get a reference to the document in the IFrame
	var objEditor = GetEditorRef(iframeId);
	
	// Get a reference to the read only window
	var objReadOnly = eval("document.all('RO" + iframeId + "').contentWindow.document");
	
	// Set the default HTML
	objEditor.body.innerHTML = strDefaultText;
	objReadOnly.body.innerHTML = strDefaultText;
	
	// Set the style for the body if requested
	objEditor.body.style.cssText = BODYSTYLE;
	objReadOnly.body.innerHTML = BODYSTYLE;
	
	// Reference the CSS file if specified
	if (CSS_FILE != "")
	{
		// Set a reference to the specified CSS and put it in th head
		var oLink=objEditor.createElement("LINK");
		oLink.rel = 'stylesheet';
		oLink.type = 'text/css';
		oLink.href = CSS_FILE;			
		objEditor.getElementsByTagName('head')[0].appendChild(oLink);

		// Set a reference to the specified CSS and put it in th head
		var oLink=objReadOnly.createElement("LINK");
		oLink.rel = 'stylesheet';
		oLink.type = 'text/css';
		oLink.href = CSS_FILE;			
		objReadOnly.getElementsByTagName('head')[0].appendChild(oLink);

	}
	

	// Get a reference to the text area that contains the source code
	var ctrlText = eval("document.all.TXT"+iframeId);

	// Update the source code
	ctrlText.value = objEditor.body.innerHTML;
	
	// Hook into the keypress event 
	objEditor.onkeypress = function() { KeyPress(iframeId) };

	// Hook into the keydown event 
	objEditor.onkeydown = function() { KeyDown(iframeId) };

	// Hook into the mouse click event 
	objEditor.onclick = function() { EditorDisplayChanged(iframeId) };

	// Hook into ondeactivate event
	objEditor.ondeactivate = function() { EditorDisplayChanged(iframeId) };

	// Hook into the keyup event 
	objEditor.onkeyup = function() { KeyUp(iframeId) };

	// Hook into the onstop event
	objEditor.onstop  = function() { Unload(iframeId) };

	// Set the size of the margins
	objEditor.body.topMargin = EDITORMARGIN;
	objEditor.body.bottomMargin = EDITORMARGIN;
	objEditor.body.leftMargin = EDITORMARGIN;
	objEditor.body.rightMargin = EDITORMARGIN;

	// Set the size of the margins
	objReadOnly.body.topMargin = EDITORMARGIN;
	objReadOnly.body.bottomMargin = EDITORMARGIN;
	objReadOnly.body.leftMargin = EDITORMARGIN;
	objReadOnly.body.rightMargin = EDITORMARGIN;
	
	// Here is the magic statement that makes the UI editable.  Without this
	// statement your HTML RTA would just be a static web page.
	objEditor.body.contentEditable = true;

	// Start handling the undo/redo
	UndoInitialise(iframeId);
}


// ToggleGuideLines
// Shows and hides the table guidelines
function ToggleGuideLines(iframeId)
{		
	if (guidelinesOn == false)
	{
		guidelinesOn = true;
	}
	else {
		guidelinesOn = false;
	}	
	ApplyGuideLines(iframeId);
}


// RemoveGuidelines
// Hides the table guidelines
function RemoveGuidelines(iframeId)
{		
	guidelinesOn = false;
	ApplyGuideLines(iframeId);
}


// ApplyGuideLines
// Shows or hides the table guidelines
function ApplyGuideLines(iframeId)
{
	editorObject = GetEditorRef(iframeId);

	// Used to show the table guidelines
	var strStyle = ' style="BORDER-RIGHT: #7F7C75 1px dashed;BORDER-TOP: #7F7C75 1px dashed;BORDER-LEFT: #7F7C75 1px dashed;BORDER-BOTTOM: #7F7C75 1px dashed;BORDER-TOP: #7F7C75 1px dashed;" ';
		
	if (guidelinesOn == true)
	{
		// Make sure that it is removed first before putting it back on
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/BORDER-RIGHT: #7F7C75 1px dashed; /gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/BORDER-TOP: #7F7C75 1px dashed; /gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/BORDER-LEFT: #7F7C75 1px dashed; /gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/BORDER-BOTTOM: #7F7C75 1px dashed/gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/; BORDER-TOP: #7F7C75 1px dashed/gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/style=\"1: #7F7C75 1px dashed"/gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/style=\"" /gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/style=\""/gi, "");

		re = new RegExp("<TABLE ", "gim");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(re, "<TABLE" + strStyle);
		re = new RegExp("<TD", "gim");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(re, "<TD" + strStyle);
	}
	else {
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/BORDER-RIGHT: #7F7C75 1px dashed; /gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/BORDER-TOP: #7F7C75 1px dashed; /gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/BORDER-LEFT: #7F7C75 1px dashed; /gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/BORDER-BOTTOM: #7F7C75 1px dashed/gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/; BORDER-TOP: #7F7C75 1px dashed/gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/style=\"1: #7F7C75 1px dashed"/gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/style=\"" /gi, "");
		editorObject.body.innerHTML = editorObject.body.innerHTML.replace(/style=\""/gi, "");
	
	}	
	
	EditorDisplayChanged(iframeId);
}


// SetNumberedList
// Sets the text to be an ordered list and then to set its 'type' which 
// controls how it is displayed
function SetNumberedList(iframeId)
{
	// The editor is the document within the IFrame that contains the HTML
	var editorObject = GetEditorRef(iframeId);

	// The editor is the document within the IFrame that contains the HTML	
	editorObject.execCommand("InsertOrderedList", true);
	
	// Find out where the cusor is
	var objRange = editorObject.selection.createRange();	
	
	var blnInAList = false;
	try
	{
		// Find the element that that cursor is in
		var parentObject = objRange.parentElement();
		while (parentObject != null)
		{			
			// Go up the element tree until we find a row				
			if (parentObject.tagName.toUpperCase() == "OL")
			{			
				blnInAList = true;
				break;
			}	
			else {
				// Go up through the tree
				var parentObject = parentObject.parentElement;			
			}
		}
			
		if (blnInAList == true)
		{
			parentObject.type = strOrderedListType;
		}

		ButtonStates(iframeId);
	}
	// objRange.parentElement() will throw an error during table resizes and the like
	catch(e)
	{
		// Not much we can do here if something goes wrong
	}

}


// SetUnOrderedList
// To set the text to be an unordered list and then to set its 'type' which 
// controls how it is displayed
function SetUnOrderedList(iframeId)
{
	// The editor is the document within the IFrame that contains the HTML
	var editorObject = GetEditorRef(iframeId);

	// The editor is the document within the IFrame that contains the HTML	
	editorObject.execCommand("InsertUnorderedList", true);
	
	// Find out where the cusor is
	var objRange = editorObject.selection.createRange();	
	
	var blnInAList = false;
	try
	{
		// Find the element that that cursor is in
		var parentObject = objRange.parentElement();
		while (parentObject != null)
		{			
			// Go up the element tree until we find a row				
			if (parentObject.tagName.toUpperCase() == "UL")
			{			
				blnInAList = true;
				break;
			}	
			else {
				// Go up through the tree
				var parentObject = parentObject.parentElement;			
			}
		}
			
		if (blnInAList == true)
		{
			parentObject.type = strUnOrderedListType;
		}
		ButtonStates(iframeId);
	}
	// objRange.parentElement() will throw an error during table resizes and the like
	catch(e)
	{
		// Not much we can do here if something goes wrong
	}

}

// Records whether there was key press event. If there was then
// we will want to update the undo list
var keyPressed = false;

// KeyPress
// Called whenever a key is pressed.  Use this function to intercept 
// any keys whose behaviour you want to override
function KeyPress(iframeId)
{
	keyPressed = true;
	
	// Only do something is we are checking for INSERTBRTAGONENTER
	// otherwise KeyDown will handle it.
	if (INSERTBRTAGONENTER == true)
	{
		var editorObject = GetEditorRef(iframeId);
		var win = editorObject.parentWindow;
			
		// Check for an enter and remap to a <br> instead of a <p>
		if ((win.event.keyCode == 13) && (win.event.shiftKey == false))
		{
			var ev = win.event;
			var sel = editorObject.selection;  			
			var r = sel.createRange();							
			r.pasteHTML("<BR>"); 
			ev.cancelBubble = true;  
			ev.returnValue = false;  
			r.select(); 
			r.moveEnd("character", 1); 
			r.moveStart("character", 1); 
			r.collapse(false); 
			EditorDisplayChanged(iframeId);
			return false; 
			
		}
		// Check for a shift-enter and remap to a <p> if requested.
		else if ((win.event.keyCode == 13) && (win.event.shiftKey == true))
		{
			if (INSERTPTAGONSHIFTENTER == true)
			{
				var ev = win.event;
				var sel = editorObject.selection;  			
				var r = sel.createRange();							
				r.pasteHTML("<P>"); 
				ev.cancelBubble = true;  
				ev.returnValue = false;  
				r.select(); 
				r.moveEnd("character", 1); 
				r.moveStart("character", 1); 
				r.collapse(false); 
				EditorDisplayChanged(iframeId);
				return false; 
			}
		}
	}
}


// KeyDown
// This event is called frequently especially when doing a lot of cursor movement
// Create a timer so we are not hitting EditorDisplayChanged() all of the time.
var timeoutTimer = null; 
function KeyDown(iframeId)
{		
	var editorObject = GetEditorRef(iframeId);
	var win = editorObject.parentWindow;

	keyPressed = false;

	// Check for an enter and remap to a <br> instead of a <p>
	if ((win.event.keyCode == 86) && (win.event.ctrlKey == true))
	{
		ExecuteAPaste(iframeId);
	}

	// Check for a tab
	if (win.event.keyCode == 9) 
	{ 
		var ev = win.event;
		var sel = editorObject.selection;  			
		var r = sel.createRange();							
		r.pasteHTML("&nbsp;&nbsp;&nbsp;"); 
		ev.cancelBubble = true;  
		ev.returnValue = false;  
		r.select(); 
		r.moveEnd("character", 1); 
		r.moveStart("character", 1); 
		r.collapse(false); 
		EditorDisplayChanged(iframeId);
		return false; 
	}

	if (timeoutTimer != null)
	{
		window.clearTimeout(timeoutTimer);
	}
	
	timeoutTimer = window.setTimeout("EditorDisplayChanged('" + iframeId + "');", 300);

	
}


// Handles the onkeyup event
function KeyUp(iframeId)
{  

// Only uncomment out the following lines if needed
//	var editorObject = GetEditorRef(iframeId);
//	var win = editorObject.parentWindow;
//
	if (keyPressed == true)
	{	
		// Suggest an undo check point.  It is upto the undo manager to determine
		// whether it will be created or not.
		UndoCheckPoint(iframeId, false);
	}
	
}


// Handles the unloading of the web page. Hooked into the onstop event.
function Unload(iframeId)
{
	// Nothing to do here
}


// *************
// SYMBOL INSERT
// *************

var popupSymbol;
var popupSymbolWidth = 425;
var popupSymbolHeight = 400;

// InsertSymbol
// Inserts a symbol into the page
function InsertSymbol(iframeId)
{	
	popupSymbol = window.createPopup();
	var oPopupBody = popupSymbol.document.body;
	oPopupBody.innerHTML = GetSymbolWindow(iframeId);
	popupSymbol.show(event.clientX - popupSymbolWidth, event.clientY, popupSymbolWidth, popupSymbolHeight, document.body);
	popupSymbol.document.body.onmouseup = CloseSymbol;
}

// ChosenSymbol
// Called when a symbol is chosen
function ChosenSymbol(iframeId, strHTML)
{
	PutHTML(iframeId, strHTML);
}	

// CloseSymbol
// Closes the symbol popup
function CloseSymbol()
{
	popupSymbol.hide();
}


// GetSymbolWindow
// Displays the symbol window
function GetSymbolWindow(iframeId)
{
	var pop;	

	var WINGDINGSTART = 33;
	var WINGDINGSTOP = 255;
	var SYMBOLSPERLINE = 16;

	pop = "<table border='1' style='background-color:infobackground'><tr><td>";	
	pop += "<table>";	
	for (var index = WINGDINGSTART; index <= WINGDINGSTOP; index++)
	{		
		if (((index - WINGDINGSTART) % SYMBOLSPERLINE) == 0)
		{
			pop += ("<tr>");
		}		
		pop +=("<td style='cursor:hand;background-color:threedface;border-left: 1 solid threedlightshadow; border-top: 1 solid threedlightshadow; border-right: 1 solid threeddarkshadow; border-bottom: 1 solid threeddarkshadow' align='center' onmouseover='preview.innerHTML=this.innerHTML;' onmouseout='preview.innerHTML=\"\";' onmousedown='parent.ChosenSymbol(\"" + iframeId + "\", this.innerHTML);'>");
		pop +=("<font face='wingdings'>&#" + index + ";</font>");
		pop +=("</td>");
			
		if (((index - WINGDINGSTART) % SYMBOLSPERLINE) == (SYMBOLSPERLINE - 1))
		{
			pop +=("</tr>");
		}

	}
	pop +=("</font>");
	pop +=("</table>");

	pop +=("<table border='0' width='410'><tr height='60'>");
	pop +=("<td width='1'>Preview:</td><td width='1'><font face='wingdings' size='7' id='preview'></font></td>");
	pop +=("<td align='right' valign='bottom'><input type='button' value='close'></td>");
	pop +=("</tr></table>");
		
	pop += "</td></tr></table>";	
	return pop;
}


// ***************
// EMOTICON INSERT
// ***************

var popupEmoticon;
var popupEmoticonWidth = 198;
var popupEmoticonHeight = 220;

// InsertEmoticon
// Called from the toolbar to show the emoticon window
function InsertEmoticon(iframeId)
{	
	popupEmoticon = window.createPopup();
	var oPopupBody = popupEmoticon.document.body;
	oPopupBody.innerHTML = GetEmoticonWindow(iframeId);
	popupEmoticon.show(event.clientX - popupEmoticonWidth, event.clientY, popupEmoticonWidth, popupEmoticonHeight, document.body);
	popupEmoticon.document.body.onmouseup = CloseEmoticon;
}

// ChosenEmoticon
// Called when the user selects an emoticon
function ChosenEmoticon(iframeId, strHTML)
{
	PutHTML(iframeId, strHTML);
}	


// CloseEmoticon
// Called when the emoticon window is closed
function CloseEmoticon()
{
	popupEmoticon.hide();
}


// GetEmoticonWindow
// Get the popup showing the various emoticons
function GetEmoticonWindow(iframeId)
{
	// The editor is the document within the IFrame that contains the HTML
	var editorObject = GetEditorRef(iframeId);

	pop = "<table border='1' style='background-color:infobackground'><tr><TD>";		
	pop += "<table><tr>";	
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/47_47.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/48_48.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/49_49.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/50_50.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/51_51.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/52_52.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/53_53.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/55_55.gif'></TD>"); 
	pop +=("</TR><TR>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/56_56.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/57_57.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/58_58.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/59_59.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/60_60.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/61_61.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/62_62.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/63_63.gif'></TD>"); 
	pop +=("</TR><TR>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/64_64.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/66_66.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/69_69.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/70_70.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/71_71.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/72_72.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/73_73.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/74_74.gif'></TD>"); 
	pop +=("</TR><TR>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/75_75.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/77_77.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/angel_smile.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/angry_smile.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/bat.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/beer_mug.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/bigsmile.png'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/broken_heart.gif'></TD>"); 
	pop +=("</TR><TR>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/cake.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/camera.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/cat.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/clock.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/coffee.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/confused_smile.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/cry_smile.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/devil_smile.gif'></TD>"); 
	pop +=("</TR><TR>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/dog.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/envelope.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/film.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/girl.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/girl_hug.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/guy.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/guy_hug.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/heart.gif'></TD>"); 
	pop +=("</TR><TR>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/kiss.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/lightbulb.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/martini.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/moon.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/note.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/omg_smile.gif'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/phone.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/present.gif'></TD>");
	pop +=("</TR><TR>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/red_smile.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/regular_smile.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/rose.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/sad_smile.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/shades_smile.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/star.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/surprised.png'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/teeth_smile.gif'></TD>");
	pop +=("</TR><TR>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/thumbs_down.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/thumbs_up.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/tongue_smile.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/what_smile.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/wilted_rose.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/wink.png'></TD>"); 
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);'><IMG src='" + IMG_DIRECTORY + "Emoticons/wink_smile.gif'></TD>");
	pop +=("<TD style='cursor:hand' onmousedown='parent.ChosenEmoticon(\"" + iframeId + "\", this.innerHTML);''></TD>");
	pop += "</tr></table>";	
	pop += "</tr></table>";	
	return pop;
}


// **********
// Status Bar
// **********

// DrawStatusBar
// Draws the status bar.  This is always present even if it is not requested.  It is just
// hidden if SHOWSTATUSBAR == true
function DrawStatusBar(iframeid)
{
	if (SHOWSTATUSBAR == true)
	{
		document.write("<table width='100%' id='SB" + iframeid + "' style='display:block'>");
	}
	else 
	{
		document.write("<table width='100%' id='SB" + iframeid + "' style='display:none'>");
	}
	
	document.write("<tr>");
	
	document.write("<td width='' id='TextProperties' class='SUNKEN'>&nbsp;</td>");	
	document.write("<td id='Overwrite" + iframeid + "' class='SUNKEN' width='40' align='center'>OVR</td><td id='Insert" + iframeid + "' class='SUNKEN' width='40' align='center'>INS</td>");
	document.write("</tr></table>");
}


// ****************
// Find and Replace
// ****************

var searchWin;

// FindAndReplace
// Called from the toolbar when the user click on the find and replace button
function FindAndReplace(iframeId)
{
	var findWidth = 410;
	var findHeight = 120;
	
	try
	{
		searchWin.focus();
	}
	catch(e)
	{
		searchWin = null;
	}
	
	if (searchWin == null)
	{
		strOP = "<HTML><HEAD><TITLE>Find and Replace</TITLE>"+
			"<SCR" + "IPT LANGUAGE=javascript>\n"+
			"<!--\n"+
			"var doco = eval(\"window.opener.document.all('" + iframeId + "').contentWindow.document;\");\n" +
			"var oRange = doco.body.createTextRange(); \n" + 
			"oRange.collapse(true);\n" + 
			"var blnFound = false; \n" + 
			"function FindText(blnShowWarning){\n"+
			"	if (Find.value == '') { \n" +
			"           alert('You must enter some text to search for.');\n" +
			"	    return;\n" + 
			"	}\n" +
			"	oRange.collapse(false); \n" +
			"	if (MatchCase.checked == true) iFlag = 4; \n" +
			"	else iFlag = 0; \n" + 
			"	if (oRange.findText(Find.value, 1000000, iFlag)) {   \n" +
			"		oRange.select(); \n" +
			"		blnFound = true; \n" +
			"	} \n" +
			"	else { \n " +
			"		blnFound = false; \n" +
			"		if (blnShowWarning == true) { \n" +
			"			alert(\"Cannot find '\" + Find.value + \"'\"); \n" +
			"		}\n" +
			"	} \n" +
			"}\n" +
			"function Replace(){\n"+
			"	if (blnFound == false) { \n" + 
			"		FindText(true); \n " +
			"	} \n" +
			"	else { \n" +
			"		oRange.pasteHTML(ReplaceWith.value); \n" + 
			"		FindText(true); \n" +
			"	}\n" +
			"}\n" +
			"function ReplaceAll(){\n"+
			"	if (Find.value == '') { \n" +
			"           alert('You must enter some text to search for.');\n" +
			"	    return;\n" + 
			"	}\n" +
			"	oRange = doco.body.createTextRange(); \n" + 
			"	oRange.collapse(true);\n" + 			
			"	FindText(true); \n " +
			"	while (blnFound == true) \n " +
			"	{ \n" +
			"		oRange.pasteHTML(ReplaceWith.value);\n" + 
			"		FindText(false); \n " +
			"	} \n" +
			"}\n" +
			"/" + "/-->\n"+
			"</SC"+"RIPT>" +
			"<body leftmargin='2' topmargin='2' rightmargin='2' bottommargin='2' bgcolor='ButtonFace'>" +
			"<table bgcolor='ButtonFace'>" +
			"	<tr>" +
			"		<td>Find what:</td>" +
			"		<td><input type='text' id='Find' style='width:200'></td>" +
			"		<td><input type='button' value='Find Next' id='FindNext' style='width:100' onclick=\"FindText(true);\"></td>" +
			"	</tr>" +
			"	<tr>" +
			"		<td>Replace with:</td>" +
			"		<td><input type='text' size='20' id='ReplaceWith' style='width:200'></td>" +
			"		<td><input type='button' value='Replace' id='Replace' style='width:100' onclick='Replace();'></td>" +
			"	</tr>" +
			"	<tr>" +
			"		<td></td>" +
			"		<td></td>" +
			"		<td><input type='button' value='Replace All' id='ReplaceAll' style='width:100' onclick='ReplaceAll();'></td>" +
			"	</tr>" +
			"	<tr>" +
			"		<td nowrap><input type='checkbox' id='MatchCase'>Match case</td>" +
			"		<td></td>" +
			"		<td><input type='button' value='Cancel' id='Cancel' style='width:100' onclick='window.close();'></td>" +
			"	</tr>" +
			"</table>" +
			"</body>" +
			"</html>";
			
		searchWin = window.open("about:blank", "wincolor", "width=" + findWidth + ",height=" + findHeight + ",left=" + ((screen.width / 2) - (findWidth / 2)) + ",top=" + ((screen.height / 4) - (findHeight / 2)) + ",toolbar=no,location=no,menubar=no,status=no,scrollbars=no,resizable=no");
		var myDoc = searchWin.document;
		myDoc.open("text/html");
		myDoc.write(strOP);
		myDoc.close();
		myDoc.title = "Find and Replace";

		UndoCheckPoint(iframeId, true);
		ButtonStates(iframeId);

	}	
}


// *****************
// Load From Library
// *****************

// AddFromLibrary
// called by the toolbar to show the image library 
var winLibrary;
function AddFromLibrary(iframeId)
{
	if (window.location.href.substring(0,5).toLowerCase() != 'file:')
	{
		// Attempt to put the focus in the window that may already be open
		try
		{
			winLibrary.focus();
		}
		catch(e)
		{
			winLibrary = null;
		}
	
		if (winLibrary == null)
		{
			winLibrary = window.open(IMAGELIBRARY + '?iframeid=' + iframeId, null, "width=560,height=440,toolbar=no,location=no,menubar=no,status=no,scrollbars=no,resizable=no");
		}
	}
	else {
		alert("This functionality is not available while the HTML Rich Text Area is running off your hard drive.  It must be deployed to an IIS web server for it to work.");
	}
}


// InsertImageFromLibrary
// Called when the user selects an image
function InsertImageFromLibrary(iframeId, strURL)
{
	PutHTML(iframeId, "<img src='" + strURL + "'>");	
}


// ***************
// ClearFormatting
// ***************

// ClearFormatting
// Clears the HTML markups around the selected text and also removes any hyperlinks
function ClearFormatting(iframeId)
{
	// The editor is the document within the IFrame that contains the HTML
	var editorObject = GetEditorRef(iframeId);

	// Remove the formatting
	editorObject.execCommand('RemoveFormat');
	
	// Check to see if it part of a hyperlink and remove that too.
	if (editorObject.queryCommandSupported("Unlink") == true)
	{
		editorObject.execCommand("Unlink");
	}

	UndoCheckPoint(iframeId, true);
	ButtonStates(iframeId);
}


// ********************
// Insert Date and Time
// ********************

// InsertDate
// Inserts the current date using the user's locale settings
function InsertDate(iframeId)
{
	var d = new Date();
	var s = d.toLocaleDateString();	
	PutHTML(iframeId, s);
}


// InsertTime
// Inserts the current time using the user's locale settings
function InsertTime(iframeId)
{
	var d = new Date();
	var s = d.toLocaleTimeString();	
	PutHTML(iframeId, s);
}



// ********************
// SUPPORTING FUNCTIONS
// ********************

// GetEditorRef
// Returns a reference to the editor. This allows interfacing into the raw HTML
function GetEditorRef(iframeId)
{
	return eval("document.all('" + iframeId + "').contentWindow.document");
}


// GetIFrameRef
// Returns a reference to the IFRAME objec which has most of the HTML RTA logic
// associated with it.
function GetIFrameRef(iframeId) 
{
	return eval("document.all('" + iframeId + "')");
}


// ActivateEditor
// Ensures that the editor is active and not the surrounding web page.
function ActivateEditor(iframeId)
{
	// Make sure that the contents of the editor is selected - and 
	// not the surrounding web page.
	var editorObject = GetEditorRef(iframeId);			
	var editorRange = editorObject.body.createTextRange();           
	var curRange = editorObject.selection.createRange();          
	if (curRange.length == null &&  !editorRange.inRange(curRange)) {                       
		editorRange.collapse();                                   
		editorRange.select();                                     
	}			    
}


// PutHTML
// To write the HTML into the editor
function PutHTML(iframeId, strHTML)
{
	try {
		ActivateEditor(iframeId);
		
		var editorObject = GetEditorRef(iframeId);			
		var objRange = editorObject.selection.createRange();
		objRange.pasteHTML(strHTML); 
	}
	catch(e)
	{
		alert("It was not possible to insert the text at this place in the document.");
	}

	UndoCheckPoint(iframeId, true);
	ButtonStates(iframeId);
}


// GetToolbarButtonRefFromNumber
// Gets a reference to the toolbar button from the button number
function GetToolbarButtonRefFromNumber(iframeId, buttonNumber)
{
	var iframeObject = GetIFrameRef(iframeId);
	var strCmd = iframeObject.toolbarArray[buttonNumber][BTN_PROP_CMDID];	
	return eval("document.all."+iframeId+strCmd);
}


// GetToolbarButtonRefFromAction
// Gets a reference to the toolbar button from an action
function GetToolbarButtonRefFromAction(iframeId, strAction)
{
	return eval("document.all."+iframeId+strAction);
}


// ***************************
// SPECIAL PASTE HANDLING CODE 
// ***************************

// ExecuteAPaste
// Handles the reformatting and pasting of data
function ExecuteAPaste(iframeId)
{
	var editorObject = GetEditorRef(iframeId);
	var win = editorObject.parentWindow;

	var ev = win.event;
	var sel = editorObject.selection;  			
	var r = sel.createRange();							

	if (CheckPaste() == true)
	{
		r.pasteHTML(GetFormattedClipboardData()); 
	}
	else {
		r.pasteHTML(clipboardData.getData("Text")); 
	}

	// This function can be called because of a keyboard event (ctrl-v)
	// in which case we have access to an event object.  Otherwise it 
	// happened through the toolbar and there is no event object
	if (ev != null)
	{
		ev.cancelBubble = true;  
		ev.returnValue = false;  
	}

	r.select(); 
	r.moveEnd("character", 1); 
	r.moveStart("character", 1); 
	r.collapse(false); 

	UndoCheckPoint(iframeId, true);

	EditorDisplayChanged(iframeId);
	return false; 
}


// CheckPaste();
// Checks the contents of the clipboard prior to pasting the data. Check for 
// presents of Word-like docs and offer the user to opportunity to scrub it
// prior to the paste.
function CheckPaste(formattedClipboardData)
{
	return true;
}


// GetFormattedClipboardData
// Takes and CR coming in through the clipboard and adds a <BR> instead.
function GetFormattedClipboardData()
{
	var strText = clipboardData.getData("Text");
	while (strText.indexOf("\n") > 0)
	{
		strText = strText.replace("\n","<br>");
	}
	return strText;
}


// ********************
// UNDO/REDO MANAGEMENT
// ********************

// UndoManager
// Called when the user clicks undo on the toolbar or CTRL-Z
function UndoManager(iframeId)
{
	var objIframe = GetIFrameRef(iframeId);
	var objEditor = GetEditorRef(iframeId);

	if (objIframe.undoPosition == 0)
	{
		alert('It is not possible to undo any further.');
	}
	else {
		objIframe.undoPosition--;
		objEditor.body.innerHTML = objIframe.undoData[objIframe.undoPosition];		
	}
}


// UndoManager
// Called when the user clicks redo 
function RedoManager(iframeId)
{
	var objIframe = GetIFrameRef(iframeId);
	var objEditor = GetEditorRef(iframeId);
	
	if (objIframe.undoPosition == objIframe.undoData.length - 1)
	{
		alert('There is nothing to redo.');
	}
	else {
		objIframe.undoPosition++;
		objEditor.body.innerHTML = objIframe.undoData[objIframe.undoPosition];		
	}
}


// IsUndoAvailable
// Returns TRUE if the undo is currently available
function IsUndoAvailable(iframeId)
{
	var objIframe = GetIFrameRef(iframeId);
	
	if (objIframe.undoPosition == 0)
	{
		return false;
	}
	else 
	{
		return true;
	}	
}


// IsRedoAvailable
// Returns TRUE if the redo is currently available
function IsRedoAvailable(iframeId)
{
	var objIframe = GetIFrameRef(iframeId);
	
	if (objIframe.undoPosition == objIframe.undoData.length - 1)
	{
		return false;
	}
	else 
	{
		return true;
	}	
}


// UndoCheckPoint
// Called whenever the HTML changes.  It can happen becuase of two reasons:
// the user has pressed a key in which case we don't want to record every change,
// only once every second.  In this case set blnForce = false. Or because 
// they did something signficant like changed the formatting or pasted an 
// object. In this case blnForce == true.
var undoTimer = null;
function UndoCheckPoint(iframeId, blnForce)
{
	var objIframe = GetIFrameRef(iframeId);
	var objEditor = GetEditorRef(iframeId);

	if (blnForce == true)
	{	
		// When the UndoCheckPoint is not forced a timer is started.  If the timer is currently
		// runing then stop it now as we are about to do what it was going to do after its interval.		
		if (undoTimer != null)
		{
			window.clearTimeout(undoTimer);
			undoTimer = null;
		}
		
		// If we have made undo and now we have made a change then 
		// we need to discard all other undos that we have just gone through
		if (objIframe.undoPosition < objIframe.undoData.length - 1)
		{
			objIframe.undoData = objIframe.undoData.slice(0, objIframe.undoPosition + 1);
		}
	
		// Record the new innerHTML 
		objIframe.undoData.push(objEditor.body.innerHTML);
		objIframe.undoPosition = objIframe.undoData.length - 1;
					
		// If we have exceeded the maximum undo size then get rid of the first one
		if (objIframe.undoData.length > MAXUNDOSIZE)
		{
			objIframe.undoData.shift();
			objIframe.undoPosition--;
			
			if (objIframe.undoPosition < 0)
			{
				objIframe.undoPosition = 0;
			}
		}
	
		ButtonStates(iframeId);
	}
	else {
		// If the timer that we are about to create is already running then stop it.
		if (undoTimer != null)
		{
			window.clearTimeout(undoTimer);
			undoTimer = null;
		}

		// Start a timer to create this checkpoint after 500mSecs
		undoTimer = window.setTimeout("UndoCheckPoint('" + iframeId + "', true);", 500);
	}
}


// UndoInitialise
// Initialises the undo/redo functionality
function UndoInitialise(iframeId)
{
	var objIframe = GetIFrameRef(iframeId);
	
	// Create an index into the current undo position
	objIframe.undoPosition = -1;
	
	// Create an array of the data
	objIframe.undoData = new Array();
	
	// Create a check point at the beginning
	UndoCheckPoint(iframeId, true);
}


// pushItem
// Internal array handling for the toolbar
function pushItem(array, item){
	array[array.length] = item;
}


