//<SCRIPT> - InterDev Hack

// GENERAL DISCLAIMER
// ---------------------------------------------------------------------------
// This code was developed at http://www.3fingeredsalute.com/ for educational
// purposes, and is based on code existing in the public domain.
// 
// You may use the code in any application  / website you wish, commericial or
// otherwise. Permission is not required to use the control, however no 
// guarantees or warranties are made on the code, you use it at your own risk.
// By using this code, you accept that 3FingeredSalute cannot be held 
// responsible for any damages or loss or data due to your use of the code.
//
// This code cannot be copyrighted by a company or individual for commercial 
// purposes or otherwise.
//
// Please mention 3FingeredSalute.Com when using this code in your sites.
// ---------------------------------------------------------------------------


// #####################################################################3
//		COMMAND ID's & GLOBALS REQUIRED
// #####################################################################3

DECMD_BOLD =                      5000
DECMD_COPY =                      5002
DECMD_CUT =                       5003
DECMD_DELETE =                    5004
DECMD_DELETECELLS =               5005
DECMD_DELETECOLS =                5006
DECMD_DELETEROWS =                5007
DECMD_FINDTEXT =                  5008
DECMD_FONT =                      5009
DECMD_GETBACKCOLOR =              5010
DECMD_GETBLOCKFMT =               5011
DECMD_GETBLOCKFMTNAMES =          5012
DECMD_GETFONTNAME =               5013
DECMD_GETFONTSIZE =               5014
DECMD_GETFORECOLOR =              5015
DECMD_HYPERLINK =                 5016
DECMD_IMAGE =                     5017
DECMD_INDENT =                    5018
DECMD_INSERTCELL =                5019
DECMD_INSERTCOL =                 5020
DECMD_INSERTROW =                 5021
DECMD_INSERTTABLE =               5022
DECMD_ITALIC =                    5023
DECMD_JUSTIFYCENTER =             5024
DECMD_JUSTIFYLEFT =               5025
DECMD_JUSTIFYRIGHT =              5026
DECMD_LOCK_ELEMENT =              5027
DECMD_MAKE_ABSOLUTE =             5028
DECMD_MERGECELLS =                5029
DECMD_ORDERLIST =                 5030
DECMD_OUTDENT =                   5031
DECMD_PASTE =                     5032
DECMD_REDO =                      5033
DECMD_REMOVEFORMAT =              5034
DECMD_SELECTALL =                 5035
DECMD_SEND_BACKWARD =             5036
DECMD_BRING_FORWARD =             5037
DECMD_SEND_BELOW_TEXT =           5038
DECMD_BRING_ABOVE_TEXT =          5039
DECMD_SEND_TO_BACK =              5040
DECMD_BRING_TO_FRONT =            5041
DECMD_SETBACKCOLOR =              5042
DECMD_SETBLOCKFMT =               5043
DECMD_SETFONTNAME =               5044
DECMD_SETFONTSIZE =               5045
DECMD_SETFORECOLOR =              5046
DECMD_SPLITCELL =                 5047
DECMD_UNDERLINE =                 5048
DECMD_UNDO =                      5049
DECMD_UNLINK =                    5050
DECMD_UNORDERLIST =               5051
DECMD_PROPERTIES =                5052
//
// Enums
//

// OLECMDEXECOPT  
OLECMDEXECOPT_DODEFAULT =         0 
OLECMDEXECOPT_PROMPTUSER =        1
OLECMDEXECOPT_DONTPROMPTUSER =    2

// DHTMLEDITCMDF
DECMDF_NOTSUPPORTED =             0 
DECMDF_DISABLED =                 1 
DECMDF_ENABLED =                  3
DECMDF_LATCHED =                  7
DECMDF_NINCHED =                  11

// DHTMLEDITAPPEARANCE
DEAPPEARANCE_FLAT =               0
DEAPPEARANCE_3D =                 1 

// OLE_TRISTATE
OLE_TRISTATE_UNCHECKED =          0
OLE_TRISTATE_CHECKED =            1
OLE_TRISTATE_GRAY =               2

//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

//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


// #####################################################################3
//		OBJECT CONSTRUCTOR
// #####################################################################3

// HTMLEditor
//
// DESC		:	Object Constructor
function HTMLEditor(strFormElName, strW, strH, strDefaultCont, strCSSURL, intLimit, blIncSRC, blIncTable){
	
	intEditorCount += 1;
	
	this.CtrlRef = "HTMLEditor"+intEditorCount;	// reference to HTML ID of AX Control
	this.height = strH;							// control height
	this.width = strW;							// control width
	this.HTMLContent = strDefaultCont;			// default HTML String
	this.stylesheet = strCSSURL;				// CSS URL for editor.
	this.ImgDir = "../JavaScripts/edit_toolbar/";
	this.FormElName = strFormElName;
	
	this.IncSRC = blIncSRC;
	this.IncTable = blIncTable;
	this.CharLimit = intLimit;

	//assign last
	this.ToolbarBtns = this.ToolbarButtonArray();
}


// HTMLEditor.prototype.Draw
//
// DESC		:	Puts ActiveX Control on screen
HTMLEditor.prototype.Draw = function(){
	
	//Event Handlers for the control..
	document.write(""+
		"<script LANGUAGE=\"javascript\" FOR=\""+this.CtrlRef+"\" EVENT=\"DisplayChanged\">"+
		"<!--\n"+
		"return EditorDisplayChanged('"+this.CtrlRef+"')\n"+
		"//-->\n"+
		"</scr"+"ipt>"+
		"<script LANGUAGE=\"javascript\" FOR=\""+this.CtrlRef+"\" EVENT=\"ShowContextMenu\">\n"+
		"<!--\n"+
		"return ShowContextMenu('"+this.CtrlRef+"')\n"+
		"//-->\n"+
		"</scr"+"ipt>"+
		"<script LANGUAGE=\"javascript\" FOR=\""+this.CtrlRef+"\" EVENT=\"ContextMenuAction(itemIndex)\">\n"+
		"<!--\n"+
		"return ContextMenuAction(itemIndex, '"+this.CtrlRef+"')\n"+
		"//-->\n"+
		"</scr"+"ipt>");
	
	//toolbar HTML
	this.ToolBar();
		
	//write Active X control with set properties
	document.write("<OBJECT classid=\"clsid:2D360201-FFF5-11d1-8D03-00A0C959BC0A\" defval='"+this.CharLimit+"' ID="+this.CtrlRef+" height="+this.height+" width="+this.width+" VIEWASTEXT>"+
		"	<PARAM name=Scrollbars value=true>"+
		"	<PARAM name=UseDivOnCarriageReturn value=true>"+
		"	<PARAM name=SourceCodePreservation value=false>"+
		"	<PARAM name=ScrollbarAppearance value=0>"+
		"	<PARAM name=Appearance value=0>"+
		"	<PARAM name=ActivateApplets value=false>"+
		"	<PARAM name=ActivateActiveXControls value=false>"+
		"	<PARAM name=ShowBorders value=false>"+
		"</OBJECT>"+
		"<object style=\"display:none\" ID=\""+this.CtrlRef+"ObjTableInfo\" CLASSID=\"clsid:47B0DFC7-B7A3-11D1-ADC5-006008A5848C\" VIEWASTEXT>"+
		"</object>"+
		"<TEXTAREA Name='"+this.FormElName+"' ID=TXT"+this.CtrlRef+" style='display:none;width:"+(this.width)+"px;height:"+(this.height)+"px;'></TEXTAREA>");
	//initialise Screen Editor with defaults and Content
	this.InitEditor();
}


// HTMLEditor.prototype.InitEditor
//
// DESC		:	Creates Header HTML with CSS Reference for the editor
HTMLEditor.prototype.InitEditor = function(){
	// Stylesheet info to control initial presentation for user
	var sHeaderInfo = ""
	+ "<HTML>"
	+ "	<HEAD>"
	+ "		<LINK rel='stylesheet' type='text/css' href='"+this.stylesheet+"'>"
	+ "	</HEAD>"
	+ "	<BODY ID=DHTMLEditBody leftmargin=4 topmargin=4>"
	+ this.HTMLContent
	+ "</BODY>"
	+ "</HTML>";
	var DHTMLCtrl = eval("document.all."+this.CtrlRef);
	
	//loads default HTML string
	DHTMLCtrl.DocumentHTML = sHeaderInfo;
	
	// have to store toolbar button array as property of the control, so window 
	// callbacks can access data
	DHTMLCtrl.toolbarArray = this.ToolbarBtns;
	
	//right click menu arrays also stored as control properties
	DHTMLCtrl.ContextMenu = new Array();
	DHTMLCtrl.GeneralContextMenu = new Array();
	DHTMLCtrl.TableContextMenu = new Array();
	
	DHTMLCtrl.GeneralContextMenu[0] = new ContextMenuItem("Cut", DECMD_CUT);
	DHTMLCtrl.GeneralContextMenu[1] = new ContextMenuItem("Copy", DECMD_COPY);
	DHTMLCtrl.GeneralContextMenu[2] = new ContextMenuItem("Paste", DECMD_PASTE);
	DHTMLCtrl.GeneralContextMenu[3] = new ContextMenuItem("", 0);
	DHTMLCtrl.GeneralContextMenu[4] = new ContextMenuItem("Select All", DECMD_SELECTALL);
	DHTMLCtrl.GeneralContextMenu[5] = new ContextMenuItem("Find Text", DECMD_FINDTEXT);
	DHTMLCtrl.GeneralContextMenu[6] = new ContextMenuItem("", 0);
	DHTMLCtrl.GeneralContextMenu[7] = new ContextMenuItem("Insert Table", DECMD_INSERTTABLE);
	DHTMLCtrl.GeneralContextMenu[8] = new ContextMenuItem("", 0);
	DHTMLCtrl.GeneralContextMenu[9] = new ContextMenuItem("3FingeredSalute.Com", "3FS");
	
	
	DHTMLCtrl.TableContextMenu[0] = new ContextMenuItem("", 0);
	DHTMLCtrl.TableContextMenu[1] = new ContextMenuItem("Insert Row", DECMD_INSERTROW);
	DHTMLCtrl.TableContextMenu[2] = new ContextMenuItem("Delete Rows", DECMD_DELETEROWS);
	DHTMLCtrl.TableContextMenu[3] = new ContextMenuItem("", 0);
	DHTMLCtrl.TableContextMenu[4] = new ContextMenuItem("Insert Column", DECMD_INSERTCOL);
	DHTMLCtrl.TableContextMenu[5] = new ContextMenuItem("Delete Columns", DECMD_DELETECOLS);
	DHTMLCtrl.TableContextMenu[6] = new ContextMenuItem("", 0);
	DHTMLCtrl.TableContextMenu[7] = new ContextMenuItem("Insert Cell", DECMD_INSERTCELL);
	DHTMLCtrl.TableContextMenu[8] = new ContextMenuItem("Delete Cells", DECMD_DELETECELLS);
	DHTMLCtrl.TableContextMenu[9] = new ContextMenuItem("Merge Cells", DECMD_MERGECELLS);
	DHTMLCtrl.TableContextMenu[10] = new ContextMenuItem("Split Cell", DECMD_SPLITCELL);
}

// #####################################################################3
//		TOOL BAR ARRAY
// #####################################################################3

// HTMLEditor.prototype.ToolbarButtonArray
//
// DESC		:	Creates Array of toolbar controls with relevant parameters
HTMLEditor.prototype.ToolbarButtonArray = function(){

	TbarBtns = new Array();
	
	//ImageURL, Name, function, type, status, width, CMDID
	
	pushItem(TbarBtns, new Array("image.gif", "Insert Image", "alert('WARNING : If you insert a local image from your hard drive, it will not be displayed. Enter Image URLs only!');"+this.CtrlRef+".ExecCommand(DECMD_IMAGE,OLECMDEXECOPT_PROMPTUSER);", BTN_TYPE_STANDARD,true,"25","DECMD_IMAGE"));
	pushItem(TbarBtns, new Array("link.gif", "Insert HyperLink", this.CtrlRef+".ExecCommand(DECMD_HYPERLINK,OLECMDEXECOPT_PROMPTUSER);", BTN_TYPE_STANDARD,true,"25","DECMD_HYPERLINK"));
	pushItem(TbarBtns, new Array("undo.gif", "Undo", this.CtrlRef+".ExecCommand(DECMD_UNDO,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_STANDARD,true,"25","DECMD_UNDO"));
	pushItem(TbarBtns, new Array("redo.gif", "Redo", this.CtrlRef+".ExecCommand(DECMD_REDO,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_STANDARD,true,"25","DECMD_REDO"));
	pushItem(TbarBtns, new Array("cut.gif", "Cut", this.CtrlRef+".ExecCommand(DECMD_CUT,OLECMDEXECOPT_DODEFAULT);", BTN_TYPE_STANDARD,true,"25","DECMD_CUT"));
	pushItem(TbarBtns, new Array("copy.gif", "Copy", this.CtrlRef+".ExecCommand(DECMD_COPY,OLECMDEXECOPT_DODEFAULT);", BTN_TYPE_STANDARD,true,"25","DECMD_COPY"));
	pushItem(TbarBtns, new Array("paste.gif", "Paste", this.CtrlRef+".ExecCommand(DECMD_PASTE,OLECMDEXECOPT_DODEFAULT);"+this.CtrlRef+".Refresh();"+this.CtrlRef+".focus()", BTN_TYPE_STANDARD,true,"25","DECMD_PASTE"));

	//Presentation
	pushItem(TbarBtns, new Array("bold.gif","Bold",this.CtrlRef+".ExecCommand(DECMD_BOLD,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_PRESENTATION,true,"25","DECMD_BOLD"));
	pushItem(TbarBtns, new Array("italic.gif","Italic",this.CtrlRef+".ExecCommand(DECMD_ITALIC,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_PRESENTATION,true,"25","DECMD_ITALIC"));
	pushItem(TbarBtns, new Array("under.gif","Underline",this.CtrlRef+".ExecCommand(DECMD_UNDERLINE,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_PRESENTATION,true,"25","DECMD_UNDERLINE"));
	pushItem(TbarBtns, new Array("inindent.gif","Indent",this.CtrlRef+".ExecCommand(DECMD_INDENT,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_PRESENTATION,true,"25","DECMD_INDENT"));
	pushItem(TbarBtns, new Array("deindent.gif","De-Indent",this.CtrlRef+".ExecCommand(DECMD_OUTDENT,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_PRESENTATION,true,"25","DECMD_OUTDENT"));
	pushItem(TbarBtns, new Array("left.gif","Align Left",this.CtrlRef+".ExecCommand(DECMD_JUSTIFYLEFT,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_PRESENTATION,true,"25","DECMD_JUSTIFYLEFT"));
	pushItem(TbarBtns, new Array("center.gif","Align Center",this.CtrlRef+".ExecCommand(DECMD_JUSTIFYCENTER,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_PRESENTATION,true,"25","DECMD_JUSTIFYCENTER"));
	pushItem(TbarBtns, new Array("right.gif","Align Right",this.CtrlRef+".ExecCommand(DECMD_JUSTIFYRIGHT,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_PRESENTATION,true,"25","DECMD_JUSTIFYRIGHT"));
	pushItem(TbarBtns, new Array("numlist.gif","Numbered List",this.CtrlRef+".ExecCommand(DECMD_ORDERLIST,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_PRESENTATION,true,"25","DECMD_ORDERLIST"));
	pushItem(TbarBtns, new Array("bullist.gif","Bulletted List",this.CtrlRef+".ExecCommand(DECMD_UNORDERLIST,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_PRESENTATION,true,"25","DECMD_UNORDERLIST"));
	pushItem(TbarBtns, new Array("fgcolor.gif","Foreground Color","DisplayColorWindow('FG','"+this.CtrlRef+"')",BTN_TYPE_STANDARD,true,"25","DECMD_SETFORECOLOR"));
	pushItem(TbarBtns, new Array("bgcolor.gif","Background Color","DisplayColorWindow('BG','"+this.CtrlRef+"')",BTN_TYPE_STANDARD,true,"25","DECMD_SETBACKCOLOR"));
	pushItem(TbarBtns, new Array(this.StyleDropDown(),"Font Name","",BTN_TYPE_DROPDOWN,true,"100",""));
	pushItem(TbarBtns, new Array(this.FontSizeDropDowns(),"Font Size","",BTN_TYPE_DROPDOWN,true,"50",""));
	pushItem(TbarBtns, new Array(this.FontFamilyDropDowns(),"Style","",BTN_TYPE_DROPDOWN,true,"100",""));

	//Table
	pushItem(TbarBtns, new Array("instable.gif","Insert Table","DisplayTableWindow('"+this.CtrlRef+"');",BTN_TYPE_TABLE,true,"25","DECMD_INSERTTABLE"));
	pushItem(TbarBtns, new Array("insrow.gif","Insert Row",this.CtrlRef+".ExecCommand(DECMD_INSERTROW,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_TABLE,true,"25","DECMD_INSERTROW"));
	pushItem(TbarBtns, new Array("inscol.gif","Insert Column",this.CtrlRef+".ExecCommand(DECMD_INSERTCOL,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_TABLE,true,"25","DECMD_INSERTCOL"));
	pushItem(TbarBtns, new Array("inscell.gif","Insert Cell",this.CtrlRef+".ExecCommand(DECMD_INSERTCELL,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_TABLE,true,"25","DECMD_INSERTCELL"));
	pushItem(TbarBtns, new Array("delcell.gif","Delete Cell",this.CtrlRef+".ExecCommand(DECMD_DELETECELLS,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_TABLE,true,"25","DECMD_DELETECELLS"));
	pushItem(TbarBtns, new Array("delcol.gif","Delete Column",this.CtrlRef+".ExecCommand(DECMD_DELETECOLS,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_TABLE,true,"25","DECMD_DELETECOLS"));
	pushItem(TbarBtns, new Array("delrow.gif","Delete Row",this.CtrlRef+".ExecCommand(DECMD_DELETEROWS,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_TABLE,true,"25","DECMD_DELETEROWS"));
	pushItem(TbarBtns, new Array("spltcell.gif","Split Cell",this.CtrlRef+".ExecCommand(DECMD_SPLITCELL,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_TABLE,true,"25","DECMD_SPLITCELL"));
	pushItem(TbarBtns, new Array("mrgcell.gif","Merge Cells",this.CtrlRef+".ExecCommand(DECMD_MERGECELLS,OLECMDEXECOPT_DODEFAULT)",BTN_TYPE_TABLE,true,"25","DECMD_MERGECELLS"));

	//special
	pushItem(TbarBtns, new Array("source.gif","HTML Source","toggleView('"+this.CtrlRef+"');",BTN_TYPE_SRC,true,"25",""));
	pushItem(TbarBtns, new Array("find.gif","Find Text in document",this.CtrlRef+".ExecCommand(DECMD_FINDTEXT,OLECMDEXECOPT_PROMPTUSER);",BTN_TYPE_STANDARD,true,"25","DECMD_FINDTEXT"));
	pushItem(TbarBtns, new Array("borders.gif","Borders",this.CtrlRef+".ShowBorders = !"+this.CtrlRef+".ShowBorders;",BTN_TYPE_STANDARD,true,"25",""));
	pushItem(TbarBtns, new Array("details.gif","Show Details",""+this.CtrlRef+".ShowDetails = !"+this.CtrlRef+".ShowDetails;",BTN_TYPE_STANDARD,true,"25",""));
	pushItem(TbarBtns, new Array("abspos.gif","Absolute Mode",this.CtrlRef+".ExecCommand(DECMD_MAKE_ABSOLUTE,OLECMDEXECOPT_DODEFAULT);",BTN_TYPE_STANDARD,true,"25","DECMD_MAKE_ABSOLUTE"));
	pushItem(TbarBtns, new Array("snapgrid.gif","Snap To Grid",""+this.CtrlRef+".SnapToGrid = !"+this.CtrlRef+".SnapToGrid;",BTN_TYPE_STANDARD,true,"25",""));
	
	strLimit = "Limit: <SPAN ID=LIMIT"+this.CtrlRef+" class=inputtext defval='"+this.CharLimit+"' style='width:30px'>"+this.CharLimit+"</SPAN>"
	pushItem(TbarBtns, new Array(strLimit,"","",BTN_TYPE_INPUT,true,"60",""));
	
	return TbarBtns;
}

//push function - not reliant on script engine v5.5 push()
function pushItem(array, item){
	array[array.length] = item;
}

HTMLEditor.prototype.StyleDropDown = function(){
	var sDropDown = "<SELECT ID=\""+this.CtrlRef+"_ParagraphStyle\" style='width:100px' onchange=\"return ParagraphStyle("+this.CtrlRef+")\">"
    + "<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;
}

HTMLEditor.prototype.FontSizeDropDowns = function(){
  var sDropDown = "<select ID='"+this.CtrlRef+"_FontSize' style='width:50px' onchange='return FontSize("+this.CtrlRef+")'>"
	+ "  <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;
}

HTMLEditor.prototype.FontFamilyDropDowns = function(){
  var sDropDown = "<select ID='"+this.CtrlRef+"_FontName' style='width:100px' onchange='return FontName("+this.CtrlRef+")'>"
	+ "  <option value='Arial'>Arial</option>"
	+ "  <option value='Times New Roman'>Times New Roman</option>"
	+ "  <option value='Verdana'>Verdana</option>"
	+ "</select>";
	return sDropDown;
}

// HTMLEditor.prototype.ToolBar
//
// DESC		:	Creates Toolbar to manipulate editor
HTMLEditor.prototype.ToolBar = function(){
	//buttonwidth
	var intButtonWidth = this.width;
	
	//..build toolbar
	strTBar = "<DIV >"
	strTBar += "<TABLE ondragstart=\"return false;\" class=tbar WIDTH='"+this.width+"' onmouseup=\"tbarhilite('u');\" onmousedown=\"tbarhilite('d');\" onmouseout=\"tbarhilite('o');\" onmouseover=\"tbarhilite('v');\" onselectstart=\"return false\" CELLPADDING=0 CELLSPACING=0 BORDER=0>";
	strTBar += "<TR><TD>";
	
	//reset btn count
	var intBtnCount = 0;


	//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(!this.IncSRC){	//Omit if set
					blIncludeBtn = false;
				}
				break;
			case BTN_TYPE_TABLE:
				if(!this.IncTable){	//Table creation/editing
					blIncludeBtn = false;	//Omit if set
				}
				break;
			default:
				//include all others by default
				break;
		}
		
		if(this.ToolbarBtns[i][BTN_PROP_TYPE] == BTN_TYPE_INPUT && this.CharLimit == ""){
			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 (intBtnCount > intButtonWidth){	//if we have filled row...
				strTBar += "</TD></TR><TR><TD>";	//..start another
				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];
			//dispaly dropdown
			} else if(this.ToolbarBtns[i][BTN_PROP_TYPE] == BTN_TYPE_DROPDOWN){
				strTBar += this.ToolbarBtns[i][BTN_PROP_IMGURL];
			//disaply button
			}else{
				strTBar += "<IMG align=absmiddle "
				//examine command ID ... needed for disabling controls
				if(this.ToolbarBtns[i][BTN_PROP_CMDID] !== ""){
					strTBar += "ID='"+this.CtrlRef+this.ToolbarBtns[i][BTN_PROP_CMDID]+"'";
				}
				strTBar += " width=23 height=22 onclick=\""+this.ToolbarBtns[i][BTN_PROP_FUNC]+"\" TITLE='"+this.ToolbarBtns[i][BTN_PROP_TITLE]+"' SRC='"+this.ImgDir+this.ToolbarBtns[i][BTN_PROP_IMGURL]+"' class=tbarBtn>";
			}
		}
	}
	
	//finish toolbar
	strTBar += "</TD></TR>";
	strTBar += "</TABLE></DIV>";
	
	//write to screen
	document.write(strTBar);
}

// #####################################################################3
//		EVENT HANDLERS
// #####################################################################3

//Updated Textarea when HTML Edit control changes
function EditorDisplayChanged(ctrlRef){
	ctrlHTML = eval("document.all."+ctrlRef);
	ctrlText = eval("document.all.TXT"+ctrlRef);
	ctrlLIMIT = eval("document.all.LIMIT"+ctrlRef);
	
	//as long as source view is off...
	if(ctrlText.style.display == "none"){
		if (ctrlHTML.Busy == false){
			//update TEXTAREA with HTML to keep form alive
			ctrlText.value = ctrlHTML.DOM.body.innerHTML;
			if (ctrlHTML.defval !== ""){
				ctrlLIMIT.innerHTML = ctrlLIMIT.defval - ctrlHTML.DOM.body.innerHTML.length;
		
				if(parseInt(ctrlLIMIT.innerHTML) < 0){
					ctrlHTML.ExecCommand(DECMD_UNDO,OLECMDEXECOPT_DODEFAULT);
				}
			}		
			ButtonStates(ctrlHTML);
		}
	}
}

// loops through toolbar controls and updates based on editor state
// this is a very time critical function - it executes every time a change
// is made in the editor
function ButtonStates(ctrlHTML) {
	var i, s;
	
	//loop for most of the buttons that have COMMAND ID's
	for (i=0; i < ctrlHTML.toolbarArray.length; i++) {
		if(ctrlHTML.toolbarArray[i][BTN_PROP_CMDID] !== ""){
			strCmd = ctrlHTML.toolbarArray[i][BTN_PROP_CMDID];
			intCmd = eval(strCmd);
			s = ctrlHTML.QueryStatus(intCmd);
			
			var ImgRef = eval("document.all."+ctrlHTML.id+ctrlHTML.toolbarArray[i][BTN_PROP_CMDID]);
				
			if (s == DECMDF_DISABLED || s == DECMDF_NOTSUPPORTED) {
				ImgRef.className = "tbarBtn"
				ImgRef.style.filter = "alpha(opacity=25)"
				ImgRef.disabled = true
			} else if (s == DECMDF_ENABLED  || s == DECMDF_NINCHED) {
				ImgRef.className = "tbarBtn"
				ImgRef.style.filter = ""
				ImgRef.disabled = false
			} else { // DECMDF_LATCHED
				ImgRef.className = "tbarBtnSelected"
				ImgRef.style.filter = ""
				ImgRef.disabled = false
			}
		}
		
		
	}
	
	/*
	if(ctrlHTML.ShowBorders){
	
	}
	
	if(ctrlHTML.ShowDetails){
	
	}
	*/
	
	//font drop down states
	
	s = ctrlHTML.QueryStatus(DECMD_GETBLOCKFMT);
	
	var ctrlPara = eval("document.all."+ctrlHTML.id+"_ParagraphStyle");
	var ctrlSize = eval("document.all."+ctrlHTML.id+"_FontSize");
	var ctrlName = eval("document.all."+ctrlHTML.id+"_FontName");
	
	if (s == DECMDF_DISABLED || s == DECMDF_NOTSUPPORTED) {
		ctrlPara.disabled = true;
		
	} else {
		ctrlPara.disabled = false;
		ctrlPara.value = ctrlHTML.ExecCommand(DECMD_GETBLOCKFMT, OLECMDEXECOPT_DODEFAULT);
	}
	
	s = ctrlHTML.QueryStatus(DECMD_GETFONTNAME);
	
	if (s == DECMDF_DISABLED || s == DECMDF_NOTSUPPORTED) {
		ctrlName.disabled = true;
	} else {
		ctrlName.disabled = false;
		ctrlName.value = ctrlHTML.ExecCommand(DECMD_GETFONTNAME, OLECMDEXECOPT_DODEFAULT);
	}
	  
	if (s == DECMDF_DISABLED || s == DECMDF_NOTSUPPORTED) {
		ctrlSize.disabled = true;		
	} else {
		ctrlSize.disabled = false;
		ctrlSize.value = ctrlHTML.ExecCommand(DECMD_GETFONTSIZE, OLECMDEXECOPT_DODEFAULT);
	}
}

//toolbar presentation function
function tbarhilite(ev){
	var el=window.event.srcElement;
	if(el.tagName=="IMG"){
		if (el.disabled !== true){
			if (el.className !== "tbarBtnSelected"){
				switch(ev){
					case "o":el.className="tbarBtn";break;
					case "u":el.className="tbarBtnOutset";break;
					case "v":el.className="tbarBtnOutset";break;
					case "d":el.className="tbarBtnInset";break;
				}
			}
		}
	}
}


//sets paragraph style
function ParagraphStyle(objCtrlRef){
	var objSelectRef = eval("document.all."+objCtrlRef.id+"_ParagraphStyle");
	objCtrlRef.ExecCommand(DECMD_SETBLOCKFMT, OLECMDEXECOPT_DODEFAULT, objSelectRef.value);
	objCtrlRef.focus();
}	

//set font size for selection
function FontSize(objCtrlRef){
	var objSelectRef = eval("document.all."+objCtrlRef.id+"_FontSize");
	objCtrlRef.ExecCommand(DECMD_SETFONTSIZE, OLECMDEXECOPT_DODEFAULT, parseInt(objSelectRef.value));
	objCtrlRef.focus();
}	

// sets font face for selection
function FontName(objCtrlRef){
	var objSelectRef = eval("document.all."+objCtrlRef.id+"_FontName");
	objCtrlRef.ExecCommand(DECMD_SETFONTNAME, OLECMDEXECOPT_DODEFAULT, objSelectRef.value);
	objCtrlRef.focus();
}	

// DisplayColorWindow
// 
// 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.
function DisplayTableWindow(ctrlref){
	strOP = "<HTML><HEAD><TITLE>Create Table</TITLE>"+
	"<STYLE>.txt{width:50px;}TD{font-size:8pt;letter-spacing:-0.5pt}INPUT{border:solid 1px;font-family:verdana;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'>"+
	"<SCRIPT 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,'"+ctrlref+"',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=0 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>"

	var mywin = window.open("about:blank", "wincolor", "width=250,height=150,toolbar=no,location=no,menubar=no,status=no,scrollbars=no,resizable=no");
	var myDoc = mywin.document;
	myDoc.open("text/html");
	myDoc.write(strOP);
	myDoc.close();
	myDoc.title = "Create Table";

}

// Uses ObjTableInfo ActiveX control to create a table object - doesn't seem
// to do anything except build the table HTML string from the values provided,
// which is obvioucly easy to do. The one thing it does do of use is to insert
// the table in the right place - I could find no documentation on this AX control
function InsertTable(strPad,strSpace,strBord,strRows,strCols,ctrlRef,winRef) {
	
	winRef.close();
	
	var objTable = eval("document.all."+ctrlRef+"ObjTableInfo");
	var objCtrlRef = eval("document.all."+ctrlRef);
	
	objTable.NumRows = strRows;
	objTable.NumCols = strCols;
	objTable.TableAttrs = " border="+strBord+" cellspacing="+strSpace+" cellpadding="+strPad+" width=100% ";
	objTable.CellAttrs = " valign=top ";
	
	objCtrlRef.ExecCommand(DECMD_INSERTTABLE,OLECMDEXECOPT_DODEFAULT, objTable);  

}


// 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.
function DisplayColorWindow(mode,ctrlref){
    
	//mode : BG, FG
	var mywin = window.open("about:blank", "wincolor", "width=500,height=100,toolbar=no,location=no,menubar=no,status=no,scrollbars=no,resizable=no");
	var myDoc = mywin.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]+">&nbsp;</TD>"		
			}			
		}
		strColorTable += "</TR>"
	}
	strColorTable += "</TABLE>"
	
	
	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, '"+ctrlref+"',window);}\n"+
	"}\n--></SCR"+"IPT></TABLE>"+
	"<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();

	if(mode == "FG"){
		myDoc.title = "Foreground Color - Click To Assign";
	} else if(mode == "BG"){
		myDoc.title = "Background Color - Click To Assign";
	} else {
		//do nothing
	}
	
}

// callback from color window, sets background/foreground color of
// selection
function SetColor(mode,color,ctrl,winRef){

	winRef.close();	//close popup
	
	var ctrlRef = eval("document.all."+ctrl);
		
	if (mode == "BG"){
		strCMD = DECMD_SETBACKCOLOR;
	} else if (mode == "FG"){
		strCMD = DECMD_SETFORECOLOR;
	} else{
		//not valid
	}
    ctrlRef.ExecCommand(strCMD,OLECMDEXECOPT_DODEFAULT, color);
}

//switched between HTML and Design View
function toggleView(ctrlRef){
	ctrlHTML = eval("document.all."+ctrlRef);
	ctrlText = eval("document.all.TXT"+ctrlRef);
	
	//display TEXTAREA
	if(ctrlText.style.display == "none"){
		ctrlText.style.display = "block";
		ctrlHTML.style.display = "none";
		
		//knock out all toolbar controls except source view
		for(var i=0;i < ctrlHTML.toolbarArray.length; i++) {
		
			var ImgRef = eval("document.all."+ctrlHTML.id+ctrlHTML.toolbarArray[i][BTN_PROP_CMDID]);
			
			if(ctrlHTML.toolbarArray[i][BTN_PROP_TITLE] !== "HTML Source"){
				ImgRef.className = "tbarBtn"
				ImgRef.style.filter = "alpha(opacity=25)"
				ImgRef.disabled = true
			}
		}
	
		var ctrlPara = eval("document.all."+ctrlHTML.id+"_ParagraphStyle");
		var ctrlSize = eval("document.all."+ctrlHTML.id+"_FontSize");
		var ctrlName = eval("document.all."+ctrlHTML.id+"_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";
		ctrlHTML.DOM.body.innerHTML = ctrlText.value;
		ctrlHTML.style.display = "block";
		ctrlHTML.Appearance = 0;
	}
}

// #####################################################################3
//		CONTEXT MENUS
// #####################################################################3

// Constructor for custom object that represents an item on the context menu
function ContextMenuItem(string, cmdId) {
  this.string = string;
  this.cmdId = cmdId;
}

//item selected from right click menu
function ContextMenuAction(itemIndex, ctrlRef){
	
	var objCtrlRef = eval("document.all."+ctrlRef);
	
	if (objCtrlRef.ContextMenu[itemIndex].cmdId == DECMD_INSERTTABLE) {
		DisplayTableWindow(ctrlRef);
	} else {
		if (objCtrlRef.ContextMenu[itemIndex].cmdId == "3FS") {
			location.href = "http://www.3fingeredsalute.com/"
		} else {
			objCtrlRef.ExecCommand(objCtrlRef.ContextMenu[itemIndex].cmdId, OLECMDEXECOPT_DODEFAULT);
		}
	}
}

// shows right click menu with various options 
// depending on what's clicked on and what state it is in
function ShowContextMenu(ctrlRef){
	var menuStrings = new Array();
	var menuStates = new Array();
	var state;
	var i;
	var idx = 0;

	var objCtrlRef = eval("document.all."+ctrlRef);

	// Rebuild the context menu. 
	objCtrlRef.ContextMenu.length = 0;

	// Always show general menu
	for (i=0; i<objCtrlRef.GeneralContextMenu.length; i++) {
		objCtrlRef.ContextMenu[idx++] = objCtrlRef.GeneralContextMenu[i];
	}

	// Is the selection inside a table? Add table menu if so
	if (objCtrlRef.QueryStatus(DECMD_INSERTROW) != DECMDF_DISABLED) {
		for (i=0; i<objCtrlRef.TableContextMenu.length; i++) {
			objCtrlRef.ContextMenu[idx++] = objCtrlRef.TableContextMenu[i];
		}
	}

	// Set up the actual arrays that get passed to SetContextMenu
	for (i=0; i<objCtrlRef.ContextMenu.length; i++) {
		menuStrings[i] = objCtrlRef.ContextMenu[i].string;
		if (menuStrings[i] != "") {
			if(objCtrlRef.ContextMenu[i].cmdId == "3FS") {
				state = DECMDF_ENABLED;
			} else {
				state = objCtrlRef.QueryStatus(objCtrlRef.ContextMenu[i].cmdId);
			}
		} else {
			state = DECMDF_ENABLED;
		}
		if (state == DECMDF_DISABLED || state == DECMDF_NOTSUPPORTED) {
			menuStates[i] = OLE_TRISTATE_GRAY;
		} else if (state == DECMDF_ENABLED || state == DECMDF_NINCHED) {
			menuStates[i] = OLE_TRISTATE_UNCHECKED;
		} else { // DECMDF_LATCHED
			menuStates[i] = OLE_TRISTATE_CHECKED;
		}
	}
  
	// Set the context menu
	objCtrlRef.SetContextMenu(menuStrings, menuStates);

}