// 2.1.1	 1 May 02
// 2.1.2	 1 May 02
// 3.0.0	10 Jul 03
// 4.0.0	25 Mar 04
//			27 Mar 04
//			31 Mar 04
//			 1 Apr 04
//			 3 Apr 04
//			 6 Apr 04
//			16 Apr 04
//			18 Apr 04
//			20 Apr 04
//			27 Apr 04
//			23 May 0
//			24 May 04
//			 1 Jun 04
//			 3 Jun 04
//			21 Jun 04
//			28 Jun 04
//			 3 Jul 04
//			 9 Jul 04
//			21 Jul 04
//			23 Aug 04
//			 7 Sep 04
//			12 Sep 04
//			 1 Jan 05
//			16 Dec 05	Version 2
//			23 Feb 06	Version 3

// Include this line before any other code:
//<script src = "../GenSubs.js">	</script> (but make sure the level is right)

// This version - v3_core - has had redundant code removed. Use this version for any programs being amended or set up. If any code grom v1 or v2 *must*
// be used, put into an extra module call v3_compatability.

var _					= null;
var __					= "undefined";
var SP					= "&nbsp;";
var SP2					= SP + SP;
var SP3					= SP2 + SP;
var GAP					= SP + SP + SP + SP;
var GAP2				= GAP + GAP;			//   8 spaces
var GAP3				= GAP2 + GAP;			//  12 spaces
var GAP4				= GAP2 + GAP2;			//  16 spaces
var GAP5				= GAP4 + GAP;			//  20 spaces
var GAP6				= GAP4 + GAP2;			//  24 spaces
var GAP8				= GAP4 + GAP4;			//  32 spaces
var GAP16				= GAP8 + GAP8;			//  64 spaces
var GAP24				= GAP16 + GAP8;			//  96 spaces
var GAP32				= GAP16 + GAP16;		// 128 spaces
var LT					= "&lt;";
var NL					= "<br>";
var NL2					= "<br><br>";
var NL3					= "<br><br><br>";
var NL4					= NL2 + NL2;

// Measurements should never be normalised in initialisation. Use PxH and PxW at point of final assignment. This allows arithmetic to be done with any declared dimension.

var UNIT_BASE			= 1000;
var USEABLE_HEIGHT		= screen.availHeight * .82;
var USEABLE_WIDTH		= screen.availWidth  * .98;

var HEIGHT_UNIT			= USEABLE_HEIGHT / UNIT_BASE;
var WIDTH_UNIT			= USEABLE_WIDTH  / UNIT_BASE;

var WIDTH_AS_HEIGHT		= WIDTH_UNIT / HEIGHT_UNIT;

var CurrentURL			= location.href;

// Key codes

var BACKSPACE			=   8;
var DIGIT_0				=  48;
var DIGIT_9				=  57;
var DOLLAR				=  52;
var DOWN_ARROW			=  40;
var ESCAPE				=  27;
var F4					= 115;
var F9					= 120;
var F10					= 121;
var F11					= 122;
var F12					= 123;
var HASH				= 222;
var HYPHEN				= 189;
var LEFT_ARROW			=  37;
var LETTER_A			=  65;
var LETTER_Z			=  90;
var MINUS				= 189;
var MINUS_NUM			= 109;
var PAGE_DOWN			=  34;
var PAGE_UP				=  33;
var PLUS				= 187;
var PLUS_NUM			= 107;
var RETURN				=  13;
var RIGHT_ARROW			=  39;
var SPACE				=  32;
var SHIFT_KEY			=  16;
var UP_ARROW			=  38;

var MINUTE				= 60 * 1000;
var HOUR				= MINUTE * 60;
var DAY					= HOUR * 24;
var WEEK				= DAY * 7;

var LIGHT				= 0;
var DARK				= 1;
var STRIP				= 2;
var STRONG				= 3;

// Level 0

var BodyLoaded			= false;
var Browser				= new BrowserDetector (navigator.userAgent);
var BrowserType			= Sniffer ();
var ButtonAlignment		= "center";
var ButtonHeight		= 20; //<<<40;  //50;	//40;
//var ButtonText;												Seems not to be set or used
var ButtonTop			= 100;
var ButtonWidth			= 110;  //130;
var ColorsInUse			= [[], [], [], []];
var ColorsToUse			= [ ["whitesmoke", "mistyrose", "lavenderblush"],	//<<<, "aliceblue", "blanchedalmond", "cornsilk", "seashell", "lightyellow"],
							["black", "seagreen", "sienna"],
							["orange", "lightblue",	"yellowgreen", "plum"],
							["red", "blue", "green", "magenta", "orange"]];
var	FontSize1			= Math.max (25, 50);
var	FontSize1_5			= 40;
var	FontSize2			= 30;
var	FontSize2_5			= 25;
var	FontSize2_7			= 22;
var	FontSize3			= 19;
var	FontSize3_5			= 17;
var	FontSize4			= 15;
var	FontSize4_5			= 12;
var	FontSize5			= 10;
var FontSize6			= 8;
var iH					= new Array ();							// Stores values of innerHTML against raw ids
var iEonmouseover		= new Array ();							// Stores values of onclick events against raw ids
//var JobsLeft			= 20;
var LeftHeight			= UNIT_BASE;
var LeftWidth			= 140;  //180;
var MaxC				= 4;
var MinFontSize			= 9;
var PadLeft				= 50;
var PadRight			= 50;
var RightHeight			= UNIT_BASE;
var RPInc				= 50;
var RPPR				= 40;

// Level 0 - colors
	
var BodyBackground		= "white";//<<<ColorText (LIGHT);
//var	ButtonBackground	= "white";//<<<ColorText (LIGHT);
var ButtonColor			= "white"; //<<<"green";//<<<GlobalTextColor;
var ButtonDisabled		= "lightblue";
var ButtonOverBGC		= "lightblue";//<<<"silver";
var ButtonOverColor		= "black";
var ButtonStayColor		= "white";			//"yellow";
var GlobalBackground	= "white";//<<<ColorText (LIGHT);
var GlobalTextColor		= "dimgray";	//"black";	//ColorText (DARK);		//16 Jan 07
var LeftPanelBackground	= "gray";//<<<StripBackground;
var StripBackground		= "white";//<<<ColorText (STRIP);
var StripTextColor		= "green";//<<<GlobalTextColor;

// Level 1

var	ButtonBackground	= LeftPanelBackground;
var ButtonInc			= 40;//<<<ButtonHeight + Math.round (ButtonHeight / 2);			//75;
var ButtonLeft			= (LeftWidth - ButtonWidth) / 2;
var ButtonStayBGC		= ButtonOverBGC;	//StripBackground;	//"gray";
var ButtonTextSize		= ButtonHeight;
var RightPanelBackground= GlobalBackground;
var RightWidth			= UNIT_BASE - LeftWidth;
var	RPLeft				= PadLeft;
var	RPTop				= ButtonTop;


// Level 2

var RightLeft			= LeftWidth + RPLeft;
var RightWidth1			= RightWidth2	= RightWidth / 2;




//var ThisButton			= ButtonColor; // 5 Dec 06	Reinstate if used anywhere

var DblClickEvent		= new Array();
var OutEvent			= new Array();
var OverEvent			= new Array();
var ActualColor			= new Array();
var ActualBGC			= new Array();
var OverColour			= new Array();
var OverBGC				= new Array();
var StayColor			= new Array();
var StayBGC				= new Array();
var LastButton			= new Array();


//var LeftPanelStyleN			= [BACKGROUND, LeftPanelBackground, HEIGHT, UNIT_BASE, LEFT, 0, TOP, 0, WIDTH LeftWidth ];
var LeftPanelStyle			= ["LeftPanel", "BACKGROUND", LeftPanelBackground, "HEIGHT", UNIT_BASE, "LEFT", 0,
								"TOP", 0, "WIDTH", LeftWidth ];
//var RightPanelStyleN		= [BACKGROUND, RightPanelBackground, HEIGHT, RightHeight, LEFT, LeftWidth, TOP, 0, WIDTH, RightWidth];
var RightPanelStyle			= ["RightPanel", "BACKGROUND", RightPanelBackground, "HEIGHT", RightHeight, "LEFT", LeftWidth,
								"TOP", 0, "WIDTH", RightWidth];

//Debug ("GS0");
for (var c = 0; c < ColorsToUse[0].length; c++) ColorsInUse[0][c]	= false;
for (var c = 0; c < ColorsToUse[1].length; c++) ColorsInUse[1][c]	= false;
for (var c = 0; c < ColorsToUse[2].length; c++) ColorsInUse[2][c]	= false;

for (var b = 0; b <= 1; b++)
	{
	LastButton[b]		= _;
	}

var dragObj		= new Object();
dragObj.zIndex	= 0;


//-------------------------------------------------------------------------------
function BaseError (message)
//-------------------------------------------------------------------------------
	{
	Debug ("Error in base routines: ", message);
	}

//-------------------------------------------------------------------------------
function Bottom (obj) 
//-------------------------------------------------------------------------------
{

//Debug (3, xPH (obj.offsetTop), xPH (obj.offsetHeight));
return (xPH (obj.offsetTop) + xPH (obj.offsetHeight));
}


//-------------------------------------------------------------------------------
function BrowserDetector(ua) {
//-------------------------------------------------------------------------------

/*
Parses User-Agent string into useful info.
Source: Webmonkey Code Library
(http://www.hotwired.com/webmonkey/javascript/code_library/)
Author: Richard Blaylock
Author Email: blaylock@wired.com

Usage: var bd = new BrowserDetector(navigator.userAgent);
*/
//Debug ("SS", ua);
// Defaults
this.browser		= "Unknown";
this.platform		= "Unknown";
this.version		= "";
this.majorver		= "";
this.minorver		= "";

if (document.URL.match(/index.html/) == _) return;
//Debug("SS", "YES");
// Split into stuff before parens and stuff in parens

var preparens		= "";
var parenthesized	= "";

var i				= ua.indexOf("(");
if (i >= 0)
	{
	preparens		= Trim(ua.substring(0,i));
	parenthesized	= ua.substring(i+1, ua.length);
	j				= parenthesized.indexOf(")");
	if (j >= 0)
		{
		parenthesized	= parenthesized.substring(0, j);
		}
	}
else
	{
	preparens = ua;
	}

// First assume browser and version are in preparens. Override later if we find them in the parenthesized stuff

var browver	= preparens;
var tokens	= parenthesized.split(";");
var token	= "";

// Now go through parenthesized tokens

for (var i = 0; i < tokens.length; i++)
	{
	token = Trim (tokens[i]); 								// compatible - might want to reset from Netscape
	if (token == "compatible")
		{
		//## One might want to reset browver to a null string
		//## here, but instead, we'll assume that if we don't
		//## find out otherwise, then it really is Mozilla
		//## (or whatever showed up before the parens).
		//## browser - try for Opera or IE
		}
	else if (token.indexOf("MSIE") >= 0)
		{
		browver = token;
		}
	else if (token.indexOf("Opera") >= 0)
		{
		browver = token;
		}
		//'## platform - try for X11, SunOS, Win, Mac, PPC
	else if ((token.indexOf("X11") >= 0) || (token.indexOf("SunOS") >= 0) || (token.indexOf("Linux") >= 0))
		{
		this.platform = "Unix";
		}
	else if (token.indexOf("Win") >= 0)
		{
		this.platform = token;
		}
	else if ((token.indexOf("Mac") >= 0) || (token.indexOf("PPC") >= 0))
		{
		this.platform = token;
		}
	}

var msieIndex	= browver.indexOf("MSIE");
if (msieIndex >= 0)
	{
	browver	= browver.substring(msieIndex, browver.length);
	}

var leftover	= "";
if (browver.substring(0, "Mozilla".length) == "Mozilla")
	{
	this.browser	= "Netscape";
	leftover		= browver.substring("Mozilla".length+1, browver.length);
	}
else if (browver.substring(0, "Lynx".length) == "Lynx")
	{
	this.browser	= "Lynx";
	leftover		= browver.substring("Lynx".length + 1, browver.length);
	}
else if (browver.substring(0, "MSIE".length) == "MSIE")
	{
	this.browser	= "IE";
	leftover		= browver.substring("MSIE".length+1, browver.length);
	}
else if (browver.substring(0, "Microsoft Internet Explorer".length) == "Microsoft Internet Explorer")
	{
    this.browser	= "IE"
	leftover		= browver.substring("Microsoft Internet Explorer".length+1, browver.length);
	}
else if (browver.substring(0, "Opera".length) == "Opera")
	{
	this.browser	= "Opera"
	leftover		= browver.substring("Opera".length + 1, browver.length);
	}

leftover = Trim (leftover);

// # Try to get version info out of leftover stuff
i	= leftover.indexOf(" ");
if (i >= 0)
	{
	this.version	= leftover.substring(0, i);
	}
else
	{
	this.version	= leftover;
	}
j = this.version.indexOf(".");
if (j >= 0)
	{
	this.majorver	= this.version.substring(0,j);
	this.minorver	= this.version.substring(j+1, this.version.length);
	}
else
	{
	this.majorver = this.version;
	}

//Debug ("WW", this.platform);
//if (!((this.browser == "IE"			&& this.version == "6.0" 
//	|| this.browser == "Navigator"	&& this.version == "7.0") && (this.platform == "Windows 98" || this.platform == "Windows NT 5.0")))
//	if (document.URL.search (/.*index.html/) != -1)
//		alert ("Warning: you may be using a browser (or version or platform) on which this site has not been tested.");

}																		// BrowserDetector

//-------------------------------------------------------------------------------
function ButtonClick (level, idin)
//-------------------------------------------------------------------------------
{
var objevent	= GetObjectEvent(idin);

//Debug ("BC", idin, objevent.onclick);
GetObject(idin).style.color				= ButtonStayColor;
GetObject(idin).style.backgroundColor	= ButtonStayBGC;

if (idin != "B1")
	{
	objevent.onclick						= "";
	objevent.onmouseover					= "";
	objevent.onmouseout						= "";
	}

if (LastButton[level] != _)
	{
	var objs				= GetObject (LastButton[level]).style;
	var objevent			= GetObjectEvent(LastButton[level]);

	objs.color				= ActualColor[LastButton[level]];
	objs.backgroundColor	= ActualBGC[LastButton[level]];
	objevent.onclick		= new Function(ClickEvent[LastButton[level]]);
	objevent.ondblclick		= new Function(DblClickEvent[LastButton[level]]);
	objevent.onmouseover	= new Function (OverEvent[LastButton[level]]);
	objevent.onmouseout		= new Function (OutEvent[LastButton[level]]);
	}
LastButton[level]						= idin;
}					

//-------------------------------------------------------------------------------
function ButtonClick2 (idin)					
//-------------------------------------------------------------------------------
{
// 16 Jan 07

//Debug ("BC2", idin);
Node (idin, BACKGROUND, ButtonStayBGC, TEXT_COLOR, ButtonStayColor)

if (ButtonClick2.current)
	{
	Node (ButtonClick2.current, BACKGROUND, ButtonBackground, TEXT_COLOR, ButtonColor)
	}

ButtonClick2.current	= idin;
}																	// ButtonClick2

//-------------------------------------------------------------------------------
function ButtonOver (idin)					
//-------------------------------------------------------------------------------
{
// 17 Jan 07

if (idin != ButtonClick2.curent)
	Node (idin, BACKGROUND, ButtonOverBGC, TEXT_COLOR, ButtonOverColor);

}

//-------------------------------------------------------------------------------
function ButtonOut (idin)					
//-------------------------------------------------------------------------------
{
// 17 Jan 07

if (idin != ButtonClick2.curent)
	Node (idin, BACKGROUND, ButtonBackground, TEXT_COLOR, ButtonColor);

}

//-------------------------------------------------------------------------------
function ColorFree (shade, c)
//-------------------------------------------------------------------------------
{
ColorsInUse[shade, c]	= false;
return;
}																	// ColorFree

//-------------------------------------------------------------------------------
function ColorNo (shade)
//-------------------------------------------------------------------------------
{
var c;
var n	= ColorsToUse[shade].length - 1;

while (ColorsInUse[shade][c = RF (n)]);

ColorsInUse[shade][c]	= true;

return c;
}																	// ColorNo

//-------------------------------------------------------------------------------
function ColorText (shade)
//-------------------------------------------------------------------------------
{
var c;
var n	= ColorsToUse[shade].length - 1;
var x	= 0;

while (ColorsInUse[shade][c = RF (n)] && x++ < 5);

if (x == 4) for (var j = 0; j < ColorsToUse[shade].length; j++) ColorsInUse[shade][j]	= false;

ColorsInUse[shade][c]	= true;

return ColorsToUse[shade][c];
}																	// ColorText

//-------------------------------------------------------------------------------
function Deb (id)
//-------------------------------------------------------------------------------
{
var texttoshow	= id + ": ";
var q;

if (id == 0)
{
if (typeof Debug.DebugIds == __)
	Debug.DebugIds		= new Array ();

if (typeof Debug.DebugIds[id] != __)
	q		= Debug.DebugIds[id];
else
	Debug.DebugIds[id]		= q		= true;

if (q)
	{
	for (var a = 1; a < arguments.length; a++)
		{
		var val	= arguments[a];
		if (a > 1) texttoshow	+= ", ";
		texttoshow	+= arguments[a] + " = ";
		texttoshow	+= eval (val);
		}
	Debug.DebugIds[id]	= confirm (texttoshow);
	}
}
else																// Deb
{
var texttoshow	= id + ": ";
var q;

//alert("GGGG");
if (typeof Debug.DebugIds == __)
	Debug.DebugIds		= new Array ();

if (typeof Debug.DebugIds[id] != __)
	q		= Debug.DebugIds[id];
else
	Debug.DebugIds[id]		= q		= true;

if (q)
	{
	for (var a = 1; a < arguments.length; a++)
		{
		if (a > 1) texttoshow	+= ", ";
		texttoshow	+= arguments[a];
		}
	if (id == "status") window.status = texttoshow;
	else Debug.DebugIds[id]	= confirm (texttoshow);
	}
}
}//-------------------------------------------------------------------------------
function Debug (id)
//-------------------------------------------------------------------------------
{
var texttoshow	= id + ": ";
var q;

//alert("GGGG");
if (typeof Debug.DebugIds == __)
	Debug.DebugIds		= new Array ();

if (typeof Debug.DebugIds[id] != __)
	q		= Debug.DebugIds[id];
else
	Debug.DebugIds[id]		= q		= true;

if (q)
	{
	for (var a = 1; a < arguments.length; a++)
		{
		if (a > 1) texttoshow	+= ", ";
		texttoshow	+= arguments[a];
		}
	if (id == "status") window.status = texttoshow;
	else Debug.DebugIds[id]	= confirm (texttoshow);
	}
}																	// Debug

//-------------------------------------------------------------------------------
function DebugOff (id)
//-------------------------------------------------------------------------------
{
// Use $ to turn all current debugs on again

if (typeof Debug.DebugIds == __)
	Debug.DebugIds		= new Array ();

Debug.DebugIds[id]	= false;
}																	// DebugOff


//-------------------------------------------------------------------------------
function DebugOn (id)
//-------------------------------------------------------------------------------
{
if (typeof Debug.DebugIds == __)
	Debug.DebugIds		= new Array ();

Debug.DebugIds[id]	= true;
}																	// DebugOn

//-------------------------------------------------------------------------------
function Element (nodeid)
//-------------------------------------------------------------------------------
{
return document.getElementById (nodeid);
}

//-------------------------------------------------------------------------------
function Even (n)
//-------------------------------------------------------------------------------
{
return n % 2 == 0;
}

//-------------------------------------------------------------------------------
function GetArgs ()
//-------------------------------------------------------------------------------
{
// Returns an array with the arguments of the url. ? is the leading character.
var args	= new Array();
var query	= location.search.substr(1);			// Get query string
var pairs	= query.split (",");					// Break at comma

for (var i = 0; i < pairs.length; i++)
	{
	var argname;
	var pos		= pairs[i].indexOf('=');			// Look for "name=value"
	var value;
	if	(pos == -1)
		{
		if (pairs[i].length > 0)
			{
			argname	= i;
			value	= pairs[i];
			}
		else
			continue;
		}
	else
		{
		argname		= pairs[i].substring(0, pos);		// Extract the name
		value		= pairs[i].substring(pos + 1);
		}
	args[argname]	= unescape(value);
	}

return args;
}																		// GetArgs

//-------------------------------------------------------------------------------
function GetKeyCode ()
//-------------------------------------------------------------------------------
{
//Debug ("GKC", typeof window.event);
//if (!window.event) return;

//Debug ("GKC", document.event.keycode);
var k	= window.event.keyCode;

// Keep these lines in (commented out) to find out the code values for different keys:
//	if (k == 16) return;
//	Debug ("K", k);
//	return;

if (k == DOLLAR && typeof Debug.DebugIds != __)
	for (var d in Debug.DebugIds)
		Debug.Ids[d]	= true;

if (k == HASH)
	{
	DivStyle ("LeftPanel", "BACKGROUND", ColorText (STRIP));
	DivStyle ("RightPanel", "BACKGROUND", ColorText (LIGHT));
	}

return k;
}																		// GetKeyCode

//-------------------------------------------------------------------------------
function HTMLString (s)
//-------------------------------------------------------------------------------
{
var al				= arguments.length;
var fixedargs		= 1;
var clickstring		= _;
var	idstring		= _;
var mouseout		= _;
var mouseover		= _;
var parentstring	= _;
var setposition		= false;
var skipafter		= 0;
var skipbefore		= 0;
var statustext		= _;
var stylestring		= "";
var tag				= "span";
var textout;
var texttouse		= s;

if (al > fixedargs)
	{
	var	argnum		= fixedargs;

	while (argnum < al)
		{
		var inc	= 2;
		var val	= arguments[argnum + 1];

		switch (arguments[argnum])
			{
			case "ALIGN":
				stylestring	+= "align: " + val + ";";
				break;

			case "BACKGROUND":
				if (typeof val == "string")
					stylestring	+= "background-color: " + val + ";";
				else
					stylestring	+= "background-color: " + ColorsToUse[LIGHT][val < 0 ? ColorNo (LIGHT) : val] + "; ";
				break;

			case "BOLD":
				stylestring	+= "font-weight: bold;";
				inc						= 1;
				break;

			case "BORDER":
				stylestring	+= "border-style: solid;";
				stylestring	+= "border-width: " + val + "; ";
				break;

			case "BORDER_COLOR":
				stylestring	+= "border-color: " + val + "; ";
				break;
																		// HTMLString
			case "BOTTOM":
				stylestring	+= "bottom: " + PxH (val) + "; ";
				setposition				= true;
				break;

			case "CENTER":
				texttouse				= "<center>" + texttouse + "</center>";
				inc						= 1;
				break;

			case "CLICK":
				clickstring				= val;
				break;

//			case "DBLCLICK":
//				objevent.ondblclick		= new Function (val);
//				break;
//					
			case "FAMILY":
				stylestring	+= "font-family: " + val +"; ";
				break;

			case "HEIGHT":
				stylestring				+= "height: " + PxH (val) + "; ";
				setposition				= true;
				break;

			case "ID":
				idstring				= val;
				break;

			case "ITALIC":
				texttouse				= "<i>" + texttouse + "</i>";
				inc						= 1;
				break;
																		// HTMLString
			case "LEFT":
				stylestring				+= "left: " + PxW (val) + "; ";
				setposition				= true;
				break;

			case "OUT":
				mouseout				= val;
				break;

			case "OVER":
				mouseover				= val;
				break;

			case "PAD":
				stylestring				+= "padding: " + PxW (val) + "; ";
				break;

			case "SIZE":
				stylestring				+= "font-size: " + PxH (val) + "; ";
				break;
																		// HTMLString
			case "SKIP_AFTER":
				skipafter				= val;
				break;

			case "SKIP_BEFORE":
				skipbefore				= val;
				break;

			case "STATUS":
				// Status line text must not be more than 128 chars
				statustext	= StatusLine (val);
				break;

			case "STYLE":
				stylestring				+= "font-style: " + val + "; ";
				break;

			case "TAG":
				tag						= val;
				break;

			case "TEXT_COLOR":
				stylestring	+= "color: " + val + ";";
				break;

			case "TOP":
				stylestring				+= "top: " + PxH (val) + ";";
				setposition				= true;
				break;

			case "UL":
				stylestring	+= "text-decoration: underline; ";
				inc						= 1;
				break;

			case "VERTICAL":
				stylestring	+= "vertical-align: " + val + "; ";
//				objstyle.verticalAlign	= val;
				break;

			case "WEIGHT":
				stylestring	+= "font-weight: " + val + "; ";
				break;

			case "WIDTH":
				stylestring	+= "width: " + PxW (val) + "; ";
				break;

			default:
				Debug ("Error", "Unrecognised key word in HTMLString - " + arguments[argnum]);
				return;
			}
		argnum		+= inc;
		}
	}

	textout	= "<" + tag;

	if (setposition) stylestring	+= "position: absolute;";
																			// HTMLString
	if (idstring != _)
		textout	+= " id = '"		+ idstring		+ "'"; 
	if (stylestring != "")	textout	+= " style = '"		+ stylestring	+ "'";
	if (clickstring != _)	textout	+= " onclick ='"	+ clickstring	+ "'"; 

//Debug ("HTMLS9", mouseover);
	if (statustext != _)
		{
		if (mouseout != _)
			mouseout	+= ";window.status=''";
		else
			mouseout	= "window.status=''";

		if (mouseover != _)
			mouseover	=+ ";window.status='" + statustext + "'";
		else
			mouseover	= "window.status='" + statustext + "'";
		}

	if (mouseout != _) textout	+= " onmouseout =\""	+ mouseout		+ "\"";
	if (mouseover != _) textout+= " onmouseover =\""	+ mouseover		+ "\"";

	textout		+= ">" + texttouse + "</" + tag + ">";
	for (var s = 1; s <= skipbefore; s++) textout	= "<br>" + textout;
	for (var s = 1; s <= skipafter; s++) textout	+= "<br>";
	return	textout;
}																	// HTMLString



//-------------------------------------------------------------------------------
function NewColors ()
//-------------------------------------------------------------------------------
{
BodyBackground	= ColorText (LIGHT);
GlobalBackground= ColorText (LIGHT);
StripBackground	= ColorText (STRIP);
}


// Node constants		next 100

var A				= 82;
var ACTION			= 78;
var ALIGN			= 24;
var ALIGN_NODE		= 96;
var ARGUMENTS		= 73;
var BACKGROUND		=  4;
var BOLD			= 10;				// no value follows
var BORDER			= 18;
var BORDER_COLOR	= 43;
var BORDER_LEFT		= 44;
var BORDER_LINE		= 45;
var BORDER_RIGHT	= 46;
var BORDER_STYLE	= 77;
var BORDER_TOP		= 47;
var BORDER_WIDTH	= 48;
var BOTTOM			= 67;
var BOXES			= 71;
var BUTTON			= 75;
var CELL_BORDER		= 69;
var CELL_BORDER_TOP	= 94;
var CELL_PADDING	= 57;
var CELL_PAD_RIGHT	= 58;
var CELL_PAD_TOP	= 89;
var CELL_PC			= 70;
var CELL_SPACING	= 97;				// 23 Jan 07
var CELL_WEIGHTS	= 93;
var CELL_WIDTH		= 62;
var CELL_WIDTHS		= 88;
var CENTER			=  9;				// no value follows
var CHANGE			= 92;
var CHECKED			= 65;
var CLASS			= 12;
var CLICK			= 37;
var COLUMNS			= 49;
var CURSOR			= 13;
var DATA			= 50;
var DBLCLICK		= 38;
var DEBUG			= 68;
var DECOR			= 84;
var DOWN			= 39;
var FAMILY			= 55;
var FORM			= 81;
var HEADING			= 51;
var HEIGHT			= 22;
var HIDDEN			= 56;				// no value follows
var HR				= 99;
var HREF			= 83;
var HTML			= 16;
var IMG				= 60;
var INDENT			=  3;
var INDEX_ARRAY		= 52;
var INPUT			= 64;
var ITALIC			= 42;				// no value follows
var JUSTIFY			= 98;
var LEFT			=  7;
var MAIN_BOLD		= 59;
//var MAIN_CLICK		= ;
var MAXLENGTH		= 80;				// no value follows
var METHOD			= 79;
var NAME			= 29;
var OPTIONS			= 91;
var OUT				= 40;
var OVER			= 41;
var OVER_COLOR		= 85;
var PAD				= 20;
var PAD_LEFT		= 21;
var PAD_RIGHT		=  2;
var PAD_TOP			= 61;
var PARALLEL		= 53;
var PARENT			= 11;
var POSITION		= 23;
//var PROPERTIES		= 72;
var RIGHT			=  8;
var ROWS			= 54;
var SELECT			= 90;
var SIZE			= 25;
var SKIP			= 26;
var SKIP_AFTER		= 27;
var SPAN			= 87;
var SRC				= 28;
var STATUS			= 19;
var STYLE			= 30;
var TABLE			=  1;
var TEXTAREA		= 74;
var TEXT_COLOR		= 31;
var TEXT			=  5;
var TOP				=  6;
//var TYPE			= 63;				// type must be defined with the tag
var UL				= 32;				// no value follows
var UNCHECKED		= 66;
var UP				= 95;
var VALUE			= 76;
var VERTICAL		= 86;
var VISIBLE			= 33;				// no value follows
var VISIBILITY		= 34;
var WEIGHT			= 35;
var WIDTH			= 17;
var Z				= 36;

var NoValue			= "BOLDCENTERHIDDENITALICULVISIBLE";
var LeftPanelStyleN			= [BACKGROUND, LeftPanelBackground, HEIGHT, UNIT_BASE, LEFT, 0, TOP, 0, WIDTH, LeftWidth];


//-------------------------------------------------------------------------------
function Node (idin)
//-------------------------------------------------------------------------------

// A *****
{
// idin should be a main id, not a .style. It must be a string name.


function NodeError (message)
	{
	Debug ("Error in base routines (node " + obj.id + ")", message);
	}

//Debug ("N0", arguments);
if (idin == "WriteText" || idin == "DivStyle")
	{
	arguments	= arguments[1];
	idin		= arguments[0];
	}

var ainlength;
var al				= arguments.length;
var	arg1			= 1;
var argnum			= 1;
var argstu			= [];
var arrayin;
var bgctu;
var boxes			= false;
var boxesheight;
var boxesshape;
var boxespadtop		= _;
var boxeswidth;
var boxesx;
var boxesy;
var cellborder;
var cellbordertop;
var cellpadding;
var cellpadright;
var cellpadtop;
var cellpercent;
var cellspacing;					// 23 Jan 07
var cellwidth		= _;
var cellwidths;
var cellweights; //***
var checked			= _;
var click;
var clicktu;
var debugused		= false; //***
var endtag			= true;
var first;
var heighttu
var htmlfound;
var htmltag			= "div";
var idintu;
var inc;
var indexarray;
var key;
var mainbold;
var mainclick		= _;
var mousedown		= _;
var mouseout		= _;
var mouseover		= _;
//var name			= idin + "_N";
var ncols			= _;
var nrows			= _;
var obj;
var objevent;
var objname;
var objstyle;
//var objtext;						// See below where used
var overcolor		= _; //***
var padtoptu		= _;
//function DrawButton (idinx, leftin, topin, textin, heightin, widthin, bgcin, overbgcin, colorin, urlinx)
var properties;
var sizetu;
var statustext		= _;
var table			= false;		// The conditions under which this is set true need watching carefully
var tabletop		= false;		// This allows a plain table declaration and is set true if "Node (xxx, TABLE);" 
var textnode;
var type			= _;			// Use ONLY with INPUT fields
var val;
var valign			= _;
var widthtu;

// ARGUMENTS can include "must use first" parameters so must be handled separately first.

if (arguments[1] == ARGUMENTS)
	{
	arguments	= [idin].concat (arguments[2]);
	al			= arguments.length;
	}
	
//Debug ("N10", arguments);

// A5 *****

if (al >= 1)																	// Moved here 18 Jan 07					23 Jan 07
	if (arguments[argnum] == DEBUG)
		{
		debugused						= true;
		Node.debugcount					= 1;
		arg1++;
		argnum++;
//		inc								= 1;
//		break;
		}

if (al > arg1)
	{
	switch (arguments[argnum])
		{
		case A:
			htmltag		= "a";
			argnum++;
			break;
 
//		case ARGUMENTS:
//			arguments	= [idin].concat (arguments[2]);
//			al			= arguments.length;
//			break;
 
		case BOXES:
// Follow with array of properties. Use COLUMNS and ROWS for shape. Default for either is 1, set later.
			boxes		= true;
			properties	= arguments[2];
//			htmltag		= "span";
//			ncols		= 1;
//			nrows		= 1;
			argnum		+= 2;
			break;

		case FORM:
			htmltag		= "form";
			argnum++;
			break;

		case BUTTON:
//function DrawButton (idinx, leftin, topin, textin, heightin, widthin, bgcin, overbgcin, colorin, urlinx)
			val			= arguments[2];

			bgctu		= val[5] ? val[5] : ButtonBackground;
			heighttu	= val[3] ? val[3] : ButtonHeight; 

			sizetu		= ButtonTextSize;	//(heighttu / 5) * 2;							// 7 Jan 07

			padtoptu	= (heighttu - sizetu) / 2;

			argstu		= [LEFT, val[0], TOP, val[1], TEXT, val[2],
							HEIGHT,		heighttu,
							WIDTH,		val[4] ? val[4] : ButtonWidth,
							BACKGROUND,	bgctu,
							CURSOR,		"pointer",
							TEXT_COLOR,	val[7] ? val[7] : ButtonColor,
							OVER,		(val[8] ? "window.status='" + val[8] + "';" : "")
											+ ("Node ('" + idin + "', BACKGROUND, '" + (val[6] ? val[6] : ButtonOverBGC) + "')"),
							OUT,		"window.status='';Node ('" + idin + "', BACKGROUND, '" + bgctu + "')",
							SIZE,		sizetu,
							PAD_TOP,	padtoptu,
//<<<							CENTER,
							ITALIC,						//<<<
							BOLD,																									// 7 Jan 07
							FAMILY,		"Arial"];

			if (val[8]) argstu	= argstu.concat (CLICK, "window.location = '" + val[8] + "'");

			if (arguments.length > 3)
				for (var ai = 3; ai < arguments.length; ai++) argstu	= argstu.concat (arguments[ai]);

			return Node (idin, ARGUMENTS, argstu);

		case HR:
			htmltag		= "hr";
			argnum++;
			break;

		case IMG:
			htmltag		= "img";
			argnum++;
			break;

		case INPUT:
														// In Opera, a node using an input tag has a shaped border at the bottom and the right.
														// A "submit" input field definitely does not work unless the form field is made an explicit
														//parent. This may be true of other input fields too
			htmltag		= "input";
			type		= arguments[2];
			argnum		+= 2;
			break;

		case SELECT:
			htmltag		= _;
			argnum++;
			break;

		case SPAN:
			htmltag		= "span";
			argnum++;
			break;

		case TABLE:								// This is mandatory for tables. In an earlier draft I allowed tables to be true from properties
														//being set
			htmltag		= "table";
			argnum++;
			table		= true;
//Debug ("N20", argnum, al);
			tabletop	= argnum == al;
			break;

		case TEXTAREA:
			htmltag		= "textarea";
			argnum++
			break;
		}
	}

// B *****

//if (debugused) Debug ("N30", idin, typeof idin);

if (typeof idin == "string")
	{	
	idintu					= idin;
	if (first = ! (obj = document.getElementById (idin)))
		{
		obj		= document.createElement (htmltag);
		obj.id				= idin;
		if (type) iH[idin]	= "<input type='" + type + "' name='" + idin + "-input'>"
		document.body.appendChild (obj);
		htmltag	= obj.tagName;
		if (htmltag != "TD")										//  5 Jan 07
			obj.style.position	= "absolute";
		innerobj			= document.createElement;
		}
	else
		{
		if (argnum > arg1)
			{
			NodeError ("Attempt to redefine tagName in Node");
			return;
			}
		htmltag	= obj.tagName;
		idintu	= obj.id;											// 30 Jun 06

// It was the following statement that made Museums not work. Something like it may be needed for ather programs. The if is an attempt to isolate it from tables		2 Jan 07
		if (htmltag != "TD")										//  5 Jan 07
			obj.style.position		= "absolute";					// 30 Jun 06
		}
	}
else
	{
	obj		= idin;
	idintu	= obj.id;
	htmltag	= obj.tagName;
	if (htmltag != "TD")											//  5 Jan 07
		obj.style.position		= "absolute";						// 30 Jun 06
	}

//objtext				= obj.childNodes[0];						//  3 Aug 07 This statement causes an error in Mac OS9 and, anyway, doesn't seem to do anything									
// table				= table || obj.tagName.toLowerCase () == "table";    // This is too powerful and catches cases like justing hiding the whole table

objstyle			= obj.style

// C *****
																	// Node

if (al > argnum)
	{

	while (argnum < al)
		{
		inc		= 2;
		key		= arguments[argnum];
		if (argnum < al -1 ) val		= arguments[argnum + 1];

//if (idintu == "Extras") Debug ("N20", argnum, key, val, obj.innerHTML);
		switch (key)
			{

// -------------------- Overall values ------------------


			case HEIGHT:
				if (boxes)
					boxesheight			= val;
				else
					objstyle.height		= PxH (val);
				break;

			case LEFT:
				if (boxes)
					boxesx				= val;
				else
					objstyle.left		= PxW (val);
				break;

			case PARENT:
				if (typeof val == "string")
					document.getElementById (val).appendChild (obj);
				else
					val.appendChild (obj);
				break;

			case TEXT:													// If you use TEXT twice in the same call, the strings are concatenated.
				htmlfound				= (val.match (/</) || val.match (/\&.*;/)) && ! BodyLoaded;			// 29 Oct 07 - Is this the right thing to do???????

				if (first && ! BodyLoaded)	//(first)		5 Apr 07
					{
					if (htmlfound)
						{
						iH[idintu]		= val;
						}
					else
						{
						obj.appendChild (document.createTextNode (val));
						}
					}
				else
					{
					obj.innerHTML		= val;
					}


// The following elaborate code was written in ignorance of the fact that HTMl tags in a text create nodes willy nilly. The crude approach used in the line
// above may cause trouble. It may be necessary to store information about nodes for future use.
//					switch (obj.childNodes.length)
//						{
//						case 0:
//							obj.innerHTML	= val;
//							break;
//
//						case 1:			
//							if (typeof obj.childNodes[0].id == "undefined")
//								{
//								if (htmlfound) 
//									obj.innerHTML	= val;
//								else
//									obj.childNodes[0].nodeValue		= val;
//								break;
//								}
//							else
//								{
//								NodeError ("Resetting node could destroy child nodes (A)");
//								return;
//								}
//
//						default:				// length must be 2 or more
//							if (htmlfound || typeof obj.childNodes[0].id != "undefined")
//								{
//								NodeError ("Resetting node could destroy child nodes (B)");
//								return;
//								}
//							else
//								obj.childNodes[0].nodeValue		= val;
//						}
//					CLOSING BRACKET REMOVED
				break;

			case TOP:
//Debug ("N40", obj.id, val);
//				if (boxes)
//					boxesy						= val;//PxH (val);		// val		27 Jul 07
//				else
					objstyle.top				= PxH (val);
				break;

			case WIDTH:
				if (table || boxes)
					boxeswidth					= val;
				else
					objstyle.width				= PxW (val);
				break;

// -------------------- Non-border, non-event, non-table values ------------------

			case ALIGN:
				objstyle.textAlign				= val;
				break;

			case ALIGN_NODE:
				obj.align						= val;
				break;

			case BACKGROUND:
				if (typeof val == "string")
					{
//					objstyle.backgroundColor	= val;
					objstyle.background	= val;
					}
				else
					objstyle.backgroundColor	= ColorsToUse[LIGHT][val < 0 ? ColorNo (LIGHT) : val];
				break;

			case BOLD:
				objstyle.fontWeight				= "bold";
				inc								= 1;
				break;

			case BOTTOM:
				objstyle.bottom					= PxH (val);
				break;

			case CENTER:
				objstyle.textAlign				= "center";
				inc								= 1;
				break;

			case CLASS:
				obj.className					= val;
				break;

			case CURSOR:
				objstyle.cursor					= val;
				break;
																		// Node

			case DECOR:
				objstyle.textDecoration			= val;
				break;

			case FAMILY:
				objstyle.fontFamily				= val;
				break;


			case HIDDEN:
				objstyle.visibility				= "hidden";
				inc								= 1;
				break;

			case HREF:
				obj.href						= val;
				break;

			case HTML:
				if (first)
					{
					htm							= document.createElement ("span");
					obj.appendChild (htm);
					htm.appendChild (document.createTextNode (val));
					}
				else
					{
					obj.innerHTML				= val;
					}
				break;

			case INDENT:
				objstyle.textIndent				= PxW (val);
				break;

			case ITALIC:
				objstyle.fontStyle				= "italic";
				inc								= 1;
				break;

			case JUSTIFY:
				obj.align						= "justify";
				objstyle.textJustify			= "newspaper";
				inc								= 1;
				break;

			case NAME:
				if (first)
					objname						= obj.name				= val;
//					obj.name					= val;
				else
					NodeError ("'NAME' can be assigned only on initial call");
				break;

//			case "NOW":
//				shownow					= true;
//				inc						= 1;
//				break;
//

			case OPTIONS:
				var opts				= val;
				
//obj.name.options[0]="FFFF";
				for (var io = 0; io < opts.length; io++)
					{
					objname.options[io].text	= opts[io];
					}
				break;

			case PAD:
				objstyle.padding		= PxW (val);
				break;
																		// Node
			case PAD_LEFT:
				objstyle.paddingLeft	= PxW (val);
				break;

			case PAD_RIGHT:
				objstyle.paddingRight	= PxW (val);
				break;

			case PAD_TOP:
				if (boxes)
					boxespadtop			= val;							// In pixels
				else
					objstyle.paddingTop	= PxH (val);
				break;

			case POSITION:
				objstyle.position		= val;
				break;

//			case "RELATIVE":
//				objstyle.position		= "relative";
//				inc						= 1;
//				break;
//
			case RIGHT:
				objstyle.marginRight	= PxW (val);
				break;

			case SIZE:
				objstyle.fontSize		= obj.size		= PxH (val);
				break;

			case SKIP:												// Deprecated
			case SKIP_AFTER:
				for (var b = 1; b <= val; b++)
					{
					obj.appendChild (document.createElement ("br"));
					}
				break;
						
//			case "SKIP_BEFORE":										// It seems too hard to implement this. Always use SKIP_AFTER and attach the next node
//				obj.style.position		= "relative";
//				nod						= document.createElement ("br");
//				obj.childNode[0].insertElement (nod);
//				break;

			case SRC:
				obj.src								= val;
				break;

			case STATUS:
				// Status line text must not be more than 128 chars
				statustext							= StatusLine (val);
				break;

			case STYLE:
				objstyle.fontStyle					= val;
				break;

			case TEXT_COLOR:
				objstyle.color						= val;
				break;

			case UL:
				objstyle.textDecorationUnderline	= "true";
				inc									= 1;
				break;
                                       
			case VISIBLE:
//Debug ("N50", val);
				objstyle.visibility					= "visible";
				inc									= 1;
				break;
                                       
			case VALUE:
				obj.value							= val;
				break;
                                       
			case VERTICAL:											// Works only with tds. Does not seem to work with spans.
				objstyle.verticalAlign				= val;
				break;
                                       
			case VISIBILITY:
				objstyle.visibility					= val;
				break;
                                       
			case WEIGHT:
				objstyle.fontWeight					= val;
				break;

			case Z:
				objstyle.zIndex						= val;
				break;

// -------------------- Event values ------------------

		
			case CHANGE:
				obj.onchange				= new Function (val);
				break;
					
			case CLICK:														// Some of the replacement patterns must be evaluated here and some later
//				if (debugused) Debug ("Node - CLICK", val);
				if (table || boxes)
					{
					click					= val;
					}
				else
					{
					clicktu	= val.replace (/#/, idintu);
					clicktu	= clicktu.replace (/%/, obj.innerHTML);
//if (idintu.substr (0, 6) == "Letter") Debug ("N73", idin, obj.innerHTML, clicktu);
					obj.onclick				= new Function (clicktu);
					}
				break;

			case DBLCLICK:
				obj.ondblclick				= new Function (val);
				break;
					
			case DOWN:
				obj.onmousedown		= new Function (val);
				break;


			case OUT:
				if (table || boxes)
					mouseout				= val;
				else
					{
//					obj.onmouseout			= val;
					obj.onmouseout			= new Function (val);
//if (idintu.substr (0, 6) == "Letter") Debug ("N73", obj.id, obj.onmouseout);
	//				obj.onmouseout			= new Function (val.replace (/#/, idintu));
					}
				break;

			case OVER:
				if (table || boxes)
					mouseover				= val;
				else
					obj.onmouseover			= new Function (val);
				break;

			case OVER_COLOR:
				overcolor					= val;
				break;
					
			case UP:
				obj.onmouseup				= new Function (val);
				break;
// -------------------- Border values ------------------

			case BORDER:
				// Use BORDER_WIDTH in preference
				objstyle.borderStyle		= "solid";
				objstyle.borderWidth		= PxW (val);
				break;

			case BORDER_COLOR:
				objstyle.borderColor		= val;
				break;

			case BORDER_LEFT:
				objstyle.borderLeftStyle	= val;
				break;

			case BORDER_LINE:
				objstyle.border				= val;
				break;

			case BORDER_RIGHT:
				objstyle.borderRightStyle	= val;
				break;

			case BORDER_STYLE:
				objstyle.borderStyle		= val;
				break;

			case BORDER_TOP:
				objstyle.borderTopStyle		= val;
				break;

			case BORDER_WIDTH:
//Seems to be reset by other border features, so use last if there is trouble
				if (typeof val == "number")
					objstyle.borderWidth	= PxW (val);
				else
					objstyle.borderWidth	= val;
				break;

// -------------------- Table, forms and boxes values, also COLUMNS and ROWS for TEXTAREAS -------------------------------

			case ACTION:
				obj.action					= val;
				break;

			case CELL_BORDER:
				cellborder					= val;
				table						= true;
				break;

			case CELL_BORDER_TOP:
				cellbordertop				= val;
				table						= true;
				break;

			case CELL_PADDING:
				cellpadding					= PxW (val);
				table						= true;
				break;

			case CELL_PAD_RIGHT:
				cellpadright				= PxW (val);
				table						= true;
				break;

			case CELL_PAD_TOP:
				cellpadtop					= PxW (val);
				table						= true;
				break;

			case CELL_PC:
				cellpercent					= val + "%";
				table						= true;
				break;

			case CELL_SPACING:
				cellspacing					= val;
				table						= true;
				break;

			case CELL_WEIGHTS:
				cellweights					= val;
				table						= true;
				break;

			case CELL_WIDTH:											// This doesn't appear to have been used
				if (cellwidths) NodeError ("Use of both CELL_WIDTH and CELL_WIDTHS");
				cellwidth					= PxW (val);
				table						= true;
				break;

			case CELL_WIDTHS:
				if (cellwidth) NodeError ("Use of both CELL_WIDTH and CELL_WIDTHS");
				cellwidths					= val;
				table						= true;
				break;
//Debug ("N70", cellwidths[0], cellwidths[1], cellwidths[2]);

			case COLUMNS:
				if (htmltag == "textarea")
					{
					obj.cols				= val;
					}
				else
					{
					ncols					= val;
					table					= ! boxes;
					}
				break;

			case DATA:										// Later calls may have a shorter data array but longer ones will lose elements
//				if (first && htmltag != "table")
//					{
//					NodeError ("Data defined without table");
//					return;
//					}
				arrayin						= [val];		// ie it is not necessary to present the data array with [] as they are supplied here
				table						= ! boxes;
				break;
				
			case HEADING:
				heading						= val;
				break;

			case INDEX_ARRAY:
				indexarray					= val;
				table						= true;
				break;

			case MAIN_BOLD:									// Deprecated: use CELL_WEIGHTS but always supply a full number of values
				mainbold					= true;
				inc							= 1;
				table						= true;
				break;

//			case MAIN_CLICK:
//				mainclick					= val;
//				inc							= 1;
//				table						= true;
//				break;

			case MAXLENGTH:
				obj.maxlength				= val;
				break;

			case METHOD:
				obj.method					= val;
				break;

			case PARALLEL:
				arrayin						= val;				// eg PARALLEL, [A, B],...
				table						= true;
				break;

//			case PROPERTIES:
//				properties					= val;				// eg PROPERTIES, [HEIGHT, 30, WIDTH, 20],...
//				break;

			case ROWS:
				if (htmltag == "textarea")
					{
					obj.rows				= val;
					break;
					}
				nrows						= val;
				table						= ! boxes;
				break;


// -------------------- Input values ------------------

			case CHECKED:
				obj.checked					= true;
				inc							= 1;
				break;

//			case TYPE:											// type must be defined with the HTML tag
//				obj.type					= val;
//				break;

			case UNCHECKED:
				obj.checked					= false;
				inc							= 1;
				break;

			default:
				NodeError ("Unrecognised key word in Node - " + arguments[argnum]);
				return;
			}                                        
		argnum		+= inc;
		}
	}
//Debug ("N75");
//	Closing bracket removed                                        

// D *****

//Debug ("N80");
if (statustext != _)
	{
	if (mouseover != _)
		mouseover	=+ ";window.status=\"" + statustext + "\"";
	else
		mouseover	= "window.status=\"" + statustext + "\"";
	if (mouseout != _)
		mouseout	+= ";window.status=\"\"";
	else
		mouseout	= "window.status=\"\"";
	}


if (table)
	{
//Debug (idin);
	var aiindex;
//	var ainlength	= arrayin[0].length;			//****
	var an;
//	var arrays		= arrayin.length;
	var c;
	var cc;
	var celltext;
	var collen;
	var echo		= [];
	var heading		= _;
	var htd;
	var htm;
	var htr;
	var i	= 0;
	var indexno;
	var ncells;
	var ncolstu;
	var nod;
	var o;
//	var odd;
	var r;
	var start		= [0];
	var tby;
	var xx;		


//if (! tabletop)
//	{
	var ainlength	= arrayin[0].length;			//****
	var arrays		= arrayin.length;

	var lengthtu	= indexarray ? indexarray.length : ainlength;		// * arrayin.length;

	if (! ncols)
		ncols		= first ? 1 : obj.rows[0].cells.length;		// This calculates ncols if not specified BUT THIS WORKS ONLY FOR SQUARE TABLES

	ncolstu			= ncols / arrays;

	if (! nrows)
		nrows		= first ? Math.ceil (lengthtu / ncolstu) : Element (obj.id + "-TB").rows.length;

	collen		= Math.floor (lengthtu / ncolstu);
	ncells		= nrows * ncolstu;

//	odd			= (lengthtu - ncols) == 1 ? 1 : lengthtu % collen;
//	odd			= (lengthtu - collen) == 1 ? 1 : lengthtu % collen;

//	start[1]	= start[0] + Math.ceil (lengthtu / ncols);
//	for (c = 2; c < ncols; c++) start[c]	= Math.round (start[c - 1] + lengthtu / ncols);

	var leftc	= ncolstu;
	var rightc	= 0;
	var ceil	= Math.ceil (lengthtu / ncolstu);
	var floor	= Math.floor (lengthtu / ncolstu);

	while (leftc * ceil + rightc * floor > lengthtu)
		{
		leftc--;
		rightc++;
		}

	for (c = 1; c <= leftc; c++) start[c]	= start[c - 1] + ceil;
	for (;c < ncolstu; c++) start[c]	= start[c - 1] + floor;	 

	for (c = 0; c < ncells; c++)
		echo[c]		= c < ncolstu ? start[c] : echo[c - ncolstu] + 1;


	an			= 0;
//	}

//Create table
	if (first)
		{
		tby			= document.createElement ("tbody");
		tby.id		= idintu + "-TB";
		obj.appendChild (tby);

//Debug ("N60", idin, nrows, ncols);
		if (tabletop) return tby;									// 23 Jan 07

		if (boxeswidth)
			tby.width	= PxW (boxeswidth);
	
		if (heading)
			{
			htr					= document.createElement ("tr");
			htr.id				= idintu + "-HTR";
			tby.appendChild (htr);
			htd					= document.createElement ("td");
			htd.id				= idintu + "-HTD";
			htr.appendChild (htd);
			htd.colSpan			= ncols;
			htd.appendChild (document.createTextNode (heading));
			htd.style.textAlign	= "center";
			}

// Create row
		for (r = 0; r < nrows; r++)
			{
			o					= document.createElement ("tr");
			tby.appendChild (o);
			o.id				= idintu + "-R" + 0;//r;//0;

// Create cell
			for (c = 0; c < ncols; c++)
				{
				if (cellwidth)			widthtu	= cellwidth;
				else if (cellwidths)	widthtu	= cellwidths[c];
				else if (cellpercent)	widthtu	= cellpercent;
				else if (boxeswidth)	widthtu	= boxeswidth / ncols;

				indexno							= i;
				o	= document.createElement ("td");
				tby.rows[r].appendChild (o);
				o.id							= idintu + "-R" + r + "-C" + c;
				aiindex							= indexarray ? indexarray[i] : echo[i];
				celltext						= i < lengthtu ? arrayin[an][aiindex] : "" 
				o.appendChild (document.createTextNode (celltext));

//				o.style.position				= "relative";

//Debug ("N85", o.id, widthtu);
				o.style.width					= widthtu;

				if (cellborder)				o.style.border			= cellborder;
				if (cellbordertop)			o.style.borderTopStyle	= cellbordertop;
				if (cellpadding)			o.style.padding			= cellpadding;
				if (cellpadright)			o.style.paddingRight	= cellpadright;
				if (cellpadtop)				o.style.paddingTop		= cellpadtop;
//				if (cellpercent)			o.style.width			= cellpercent;
				if (cellweights) if (cellweights[c]) o.style.fontWeight		= cellweights[c];
//				if (cellwidths)				o.style.width			= PxW (cellwidths[c]);
				if (mainbold && an == 0)	o.style.fontWeight		= "bold";
//			if (mainclick && an == 0)	o.onclick				= mainclick;

				o.style.verticalAlign		= "top";											// This may need to be parameterized **********

				an++;
				if (an == arrayin.length)
					{
					an		= 0;
					i++;
					}

// #	id
// %	text
// !	array number

				if (celltext)
					{
					if (click)
						{
						clicktu	= click.replace (/#/g, o.id);
						clicktu	= clicktu.replace (/%/g, celltext.replace (/'/g, ""));
						clicktu	= clicktu.replace (/!/g, aiindex);
						o.onclick	= new Function (clicktu);
						}

					if (mouseout)
						o.onmouseout	= new Function (mouseout.replace (/#/g, o.id));	
					if (mouseover)
						o.onmouseover	= new Function (mouseover.replace (/#/g, o.id));
//Debug ("N87", o.onmouseover, o.onmouseout);
					}
				}
			}
		}
	else if (lengthtu)
		{
		tby	= document.getElementById (idintu + "-TB");
		i	= 0
//**		an	= 0;
		for (r = 0; r < nrows; r++)
			for (c = 0; c < ncols; c++)
				{
				if (i < lengthtu)
					{
					aiindex		= indexarray ? indexarray[echo[i]] : echo[i];
					o			= obj.rows[r].cells[c];
					xx			= arrayin[an][aiindex];

					if (click)
						{
						clicktu	= click.replace (/#/g, tby.rows[r].cells[c].id);
						clicktu	= clicktu.replace (/%/g, xx.replace (/'/g, ""));
						clicktu	= clicktu.replace (/!/g, aiindex);
						o.onclick	= new Function (clicktu);
						}

					if (mouseout)
						o.onmouseout	= new Function (mouseout.replace (/#/g, o.id));	
					if (mouseover)
						o.onmouseover	= new Function (mouseover.replace (/#/g, o.id));
					}
				else
					xx		= "";//**SP;

				tby.rows[r].cells[c].innerHTML	= xx;

//**				an++;
//**				if (an == arrayin.length)
//**					{
//**					an		= 0;
					i++;
//**					}
//				i++;

				}
		}

// E *****


	}
else if (boxes)
	{
	var b	= 0;
	var c;
	var i;
	var idout;
	var mo;
	var p	= properties;	//[];
	var r;
	var texttu;
	var toppad	= HTMLString ("<br>", "SIZE", boxespadtop);
	var x;
//	var y	= boxesy;
	var y	= 0;								// 27 Jul 07

	ainlength	= arrayin[0].length;			//****
	if (! boxesheight) boxesheight	= boxeswidth;
	if (! boxeswidth)  boxeswidth	= boxesheight;				// Don't forget to assign a value to at least one of these!

	if (!nrows && !ncols)
		{
		BaseError ("At least one of rows or columns nust be defined");
		return;
		}
		
	if (! ncols)
		{
		ncols	= ainlength / nrows;
//		if (! nrows) nrows	= arrayin[0].length;
		}

	if (! nrows)
		{
		nrows	= ainlength / ncols;
//		if (! ncols) ncols	= arrayin[0].length;
		}		

//if (debugused) Debug ("N90", ncols, nrows);
	for (r = 0; r < nrows; r++)
		{
		x		= boxesx;
		for (c	= 0; c < ncols; c++)
			{
			idout	=	idintu + b;
			texttu	=	boxespadtop ? toppad : "";
//Debug ("N93", texttu, boxespadtop);
			texttu	+=	arrayin[0][b];
//			texttu	=	toppad + arrayin[0][b];
//			texttu	=	arrayin[0][b];

//			if (typeof i != "string") i	= i.toString ();

			p	= [SPAN, PARENT, obj, BORDER, 1, HEIGHT, boxesheight, LEFT, x, TOP, y, WIDTH, boxeswidth, TEXT, texttu];
//Debug ("N94", obj.style.top);

// %	text				defer to activation, so include in PROPERTIES
// #	id					do here
// !	array number		do here
// ~	box no				do here

			if (click)
				{
				clicktu		= click.replace (/~/g, b);						// box no
				clicktu		= clicktu.replace (/#/, idout);					// id
				clicktu		= clicktu.replace (/!/, b);						// array index
				p			= p.concat (CLICK, clicktu);
				}

			if (mouseout)
				{
				mo	= mouseout.replace (/#/g, idout);
				p			= p.concat (OUT, mo);
				}

			if (mouseover)
				{
				mo			= mouseover.replace (/#/, idout);
				p			= p.concat (OVER, mo, CURSOR, "hand");
				}
				

			if (valign)
				p			= p.concat (VERTICAL, "'\"" + valign + "\"'");

			if (properties)
				p			= p.concat (properties);

			o	= Node (idout, ARGUMENTS, p);

//Debug ("N95", o.style.height, o.style.top);

			if (c) Node (o, BORDER_LEFT, "none");
			if (r) Node (o, BORDER_TOP, "none");
			x	+= boxeswidth;
//Node (o, TEXT_COLOR, "black");

			b++;
			}
		y		+= boxesheight;
		}
												// Assume box row to be horizontal
	}
else
	{
	if (overcolor)
		obj.mouseover	= "Node (" + obj + "BACKGROUND,'" + overcolor + "', CURSOR, 'hand')";
	}

//if (debugused )  Debug ("NEXIT", Element("Venues-TB").innerHTML);
//Debug ("NEND", obj.outerHTML);

	return obj;
}																		// Node

//-------------------------------------------------------------------------------
function Pop (A, i)
//-------------------------------------------------------------------------------
{
//A[A.length]	= i;    

BaseError ("Pop should not be used. It should be Push.")

}																		// Pop

//-------------------------------------------------------------------------------
function Push (A, i)
//-------------------------------------------------------------------------------
{
A[A.length]	= i;    

}																		// Push

//-------------------------------------------------------------------------------
function PxH (xin)
//-------------------------------------------------------------------------------
// Use a negative argument to get a scaled value without 'px'
{
var x	= xin * HEIGHT_UNIT;
return x > 0 ? Math.round (x) + "px" : Math.round (-x);
}																		// PxH

//-------------------------------------------------------------------------------
function PxW (xin)
//-------------------------------------------------------------------------------
// Use a negative argument to get a scaled value without 'px'
{
var x	= xin * WIDTH_UNIT;
return x > 0 ? Math.round (x) + "px" : Math.round (-x);
}																		// PxW

//-------------------------------------------------------------------------------
function xPH (x)
//-------------------------------------------------------------------------------
{
return parseInt (x) / HEIGHT_UNIT;
}																		// xPH



//-------------------------------------------------------------------------------
function xPW (x)
//-------------------------------------------------------------------------------
{
return parseInt (x) / WIDTH_UNIT;
}																		// xPW



//-------------------------------------------------------------------------------
function xPx (x)
//-------------------------------------------------------------------------------
{
return parseInt (x);
}																		// xPx

//-------------------------------------------------------------------------------
function R (n)
//-------------------------------------------------------------------------------
{
if (typeof n == "undefined")
	return Math.random ();
else
	return Math.random () * n;
}																		// R
	
//-------------------------------------------------------------------------------
function RF (n)
//-------------------------------------------------------------------------------
{
return Math.floor (Math.random () * n);
}																		// RF
		
//-------------------------------------------------------------------------------
function RR (n)
//-------------------------------------------------------------------------------
{
return Math.round (Math.random () * n);
}																		// RR

//-------------------------------------------------------------------------------
function Setup ()
//-------------------------------------------------------------------------------
// This function must be used **only** as the handler for window.onload event in the body tag
{

var h;
var id;
var s	= Element ("oBody").style;


s.fontFamily	= "Verdana, Times New Roman, Arial, sans-serif";
s.color			= GlobalTextColor;										// 16 Jan 07

for (h in iH)
	{
	if (iH[h] != _) Element (h).innerHTML		= iH[h];
	}

for (var e in iEonmouseover)
	{
	if (iEonmouseover[e] != _) GetObjectEvent (e).onmouseover		= iEonmouseover[e];
	}			

BodyLoaded	= true;

}																	// Setup
	
//-------------------------------------------------------------------------------
function Sniffer ()
//-------------------------------------------------------------------------------
{
var browser	= new Object();
var s		= "" + document.location;

window.status		= navigator.appName;

//Debug ("Sniffer", navigator.appName);

if (navigator.appName.indexOf ("Microsoft") != -1)
	browser.type	= "M";
else if (navigator.appName.indexOf ("Netscape") != -1)
	browser.type	= "N";
else
	browser.type	= "O";

browser.version	= parseInt (navigator.appVersion);

if (browser.type == "O" || browser.type == "M" && (browser.version < 4 || navigator.appVersion.search (/MSIE [56]/) == -1) || browser.type == "N" && browser.version < 5)
	{
	browser.type	= "O";
//	if (s.match (/.*index.htm|.*QueneauHome.htm/) != _)
//		alert ("You are not using a browser than can handle this website. It is designed for PCs with IE5 or IE6 and mostly works with NS6.1");
	}
return browser.type;
}																	// Sniffer

//-------------------------------------------------------------------------------
function StatusLine (t, use)
//-------------------------------------------------------------------------------
// Creates a right justified status message with stars on each side.

{

var nstars		= 5;
var stars		= "";
var template	= "                                                                                                                                "			// 128 spaces
if (t != _)
	{
	while (t.length + 2 * nstars + 2 > template.len && nstars > 1) nstars--;
	for (var n = 1; n <= nstars; n++) stars	+= "*";
	template	= template.substr (1, template.length - t.length - 2 * stars.length - 2) + stars + " " + t + " " + stars;
	}
else
	template	= "";

if (typeof use != "undefined") if (use) window.status	= template;

return template;

}																		// StatusLine

//-------------------------------------------------------------------------------
function TestColors ()
//-------------------------------------------------------------------------------
{
var x1		= 30;
var y1		= 30;

var h		= 80;
var n		= 0;
var w0		= 80;
var w2		= 30;
var x		= x1;
var xinc	= 150;
var y		= y1;
var yinc	= 100;

for (var c0 in ColorsToUse[0])
	{
	for (var c2 in ColorsToUse[2])
		{
//Debug ("C", c1, c2);
		WriteText ("CT" + n, x, y, "", "BACKGROUND", ColorsToUse[2][c2], "HEIGHT", h, "WIDTH", w2);
		WriteText ("CU" + n + 1, x + w2, y, "", "BACKGROUND", ColorsToUse[0][c0], "HEIGHT", h, "WIDTH", w0);
		WriteText ("CV" + n + 2, x + w2 / 2, y + yinc / 2, "X", "TEXT_COLOR", ButtonStayColor);
		n	+= 3;
		x	+= xinc;
		}
	x		= x1;
	y		+= yinc;
	}
}																		// TestColors

//-------------------------------------------------------------------------------
function Timer (val)
//-------------------------------------------------------------------------------

{
var now	= new Date ().getTime ();

if (arguments.length == 1)
	{
	switch (val)
		{
		case "Start":
			Timer.times	= new Array ();
			Timer.starttime	= now;
			break;

		case "Show":
			Timer.times.push (now - Timer.starttime);
			Debug ("Show times", Timer.times);
//			for (var t in Timer.times) Debug ("Show times", Timer.times[t]);
			return;
		}
	}
//Debug (0, starttime, now);
Timer.times.push (now - Timer.starttime);

}

//-------------------------------------------------------------------------------
function Trim (inString)
//-------------------------------------------------------------------------------
// Trims spaces from both ends of a string

{
var end		= inString.length;
var start	= 0;

while ((start < end) && (inString.charAt(start) == ' ')) ++start;
while ((end > 0) && (inString.charAt(end - 1) == ' ')) --end;

return	inString.substring(start, end);
}																	// Trim

//-------------------------------------------------------------------------------
function WritePoem (objh, objv1, objv2, verse)
//-------------------------------------------------------------------------------
{
var ce	= ""; 
var m	= typeof verse[2] == "undefined" ? verse[1].length : Math.max (verse[1].length, verse[2].length);
	
var t	= typeof arguments[4] == "undefined" ? (250 - m) / 2 : arguments[4];

Node (objh, TOP, t);
Node (objv1, LEFT, LeftWidth + RPLeft, TOP, t += 50);
Node (objv2, TOP, t);
Node (objh, TEXT, "<b>" + verse[0][0] + "</b><br>"); 

//objh.style.top	= PxH (t);
//objv1.style.top	= objv2.style.top	= PxH (t + 50);
//objh.innerHTML	= "<b>" + verse[0][0] + "</b><br>"; 

for (var v = 0; v < verse[1].length; v++)
	ce	+= "<br>" + verse[1][v];

Node (objv1, TEXT, ce);
//objv1.innerHTML	= ce;

if (verse.length == 3)
	{
	ce	= "";
	for (var v = 0; v < verse[2].length; v++)
		ce	+= "<br>" + verse[2][v];
	Node (objv2, TEXT, ce);
//	objv2.innerHTML	= ce;
	}
else
	{
	Node (objv2, TEXT, "");
	Node (objv1, LEFT, 400);
	}
//	objv2.innerHTML	= "";
}																		// WritePoem

//-------------------------------------------------------------------------------
//						SOUNDEX ROUTINES
//-------------------------------------------------------------------------------

////-------------------------------------------------------------------------------
//function Soundex (namein)
////-------------------------------------------------------------------------------
//// Compute the SOUNDEX code for the surname
//// BR version 1.2	18 Jul 03
//	{

	// create object listing the SOUNDEX values for each letter
	// -1 indicates that the letter is not coded, but is used for coding
	//  0 indicates that the letter is omitted for modern census archives
	//                              but acts like -1 for older census archives
	//  1 is for BFPV
	//  2 is for CGJKQSXZ
	//  3 is for DT
	//  4 is for L
	//  5 is for MN my home state
	//  6 is for R

	// Get results with the function Soundex (name)

	//-------------------------------------------------------------------------------
	function makesoundex()
	//-------------------------------------------------------------------------------
		{
		this.a = -1;
		this.b =  1;
		this.c =  2;
		this.d =  3;
		this.e = -1;
		this.f =  1;
		this.g =  2;
		this.h =  0;
		this.i = -1;
		this.j =  2;
		this.k =  2;
		this.l =  4;
		this.m =  5;
		this.n =  5;
		this.o = -1;
		this.p =  1;
		this.q =  2;
		this.r =  6;
		this.s =  2;
		this.t =  3;
		this.u = -1;
		this.v =  1;
		this.w =  0;
		this.x =  2;
		this.y = -1;
		this.z =  2;
		}																//Soundex - makesoundex

	var sndx	= new makesoundex();


	//-------------------------------------------------------------------------------
	function isSurname(name)
	//-------------------------------------------------------------------------------
	// check to see that the input is valid
		{
		if (name == "" || name == null)
			{
			Debug ("Soundex coding", "Please enter surname for which to generate SOUNDEX code.", name);
			return false;
			}
		else
			{
			for (var i = 0; i < name.length; i++)
				{
				var letter= name.charAt(i);
				if (!(letter >= 'a' && letter <= 'z' || letter >= 'A' && letter <='Z'))
					{
					Debug("Soundex coding", "Please enter only letters in the surname.", name);
					return false;
					}
				}
			}
		return true
		}																	//Soundex - isSurname

	//-------------------------------------------------------------------------------
	function collapse (surname)
	//-------------------------------------------------------------------------------
	// Collapse out directly adjacent sounds
	// 1. Assume that surname.length>=1
	// 2. Assume that surname contains only lowercase letters
		{
		if (surname.length == 1)
			return surname;

		var right	= collapse (surname.substring (1, surname.length));

		if (sndx[surname.charAt(0)] == sndx[right.charAt(0)])
			return surname.charAt(0) + right.substring (1, right.length);

		return surname.charAt(0) + right;
		}																// Soundex - surname

	//-------------------------------------------------------------------------------
	function omit (surname)
	//-------------------------------------------------------------------------------
	// Collapse out directly adjacent sounds using the new National Archives method
	// 1. Assume that surname.length>=1
	// 2. Assume that surname contains only lowercase letters
	// 3. H and W are completely ignored
		{
		if (surname.length == 1)
			return surname;

		var right	= omit (surname.substring (1, surname.length));

		if (!sndx[right.charAt(0)])
			return surname.charAt(0) + right.substring (1, right.length);

		return surname.charAt(0) + right;
		}																// Soundex - omit

	//-------------------------------------------------------------------------------
	function output_sequence (seq)
	//-------------------------------------------------------------------------------
	// Output the coded sequence
		{
		var output	= seq.charAt(0).toUpperCase();		// Retain first letter
		var stage2	= seq.substring(1, seq.length);
		var count	= 0;

// The following line is not needed for the new version of name processing
		output		+= "-";								// Separate letter with a dash

		for (var i = 0; i < stage2.length && count < 3; i++)
			{
			if (sndx[stage2.charAt(i)] > 0)
				{
				output	+= sndx[stage2.charAt(i)];
				count++;
				}
			}

		for (; count < 3; count++)
			output	+= "0";

		return output;
		}																
////-------------------------------------------------------------------------------
function Soundex (namein)
////-------------------------------------------------------------------------------
//// Compute the SOUNDEX code for the surname
//// BR version 1.2	18 Jul 03
	{
	//	if (!isSurname(namein))
	//		{
	//		return;
	//		}

		var stage1			= collapse (namein.toLowerCase())

	//  form.result.value	= output_sequence(stage1);
	//  var stage1			= omit(form.surname.value.toLowerCase())

		var stage2			= collapse (stage1);						// stage2 always seems the same as stage1 so I have skipped this.

	//  form.result_na.value= output_sequence (stage2);

	//	return output_sequence (stage2);
		return output_sequence (stage1);

	//function Soundex2 (namein)
	//	{
	//	return output_sequence (collapse (namein.toLowerCase ()));
	//	}

	}																	// Soundex - output_sequence
