// 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
// 			21 Aug 07	v4			This version should be fully compatible with v3 except for programs that are based on tables. These will have to be carefully revised.
//									Also, all commented out lines have been deleted. Refer to v3 if any reinstating, or for more history in general
//			24 Oct 07				This version is working with the Konstam pages. It has a special coding for SIZE i Node as this was causing an odd error in IE.

// Include this line before any other code:
//<script src = "../GenSubs_v4_core.js">	</script> (but make sure the level is right)

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;
var POUND				= "&pound;"
var QUOTERS				= "&rsquo;"

var NL_small				= "<div style='font-size: 0;height: 7px'><br></div>";

// 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 POUND				= "&pound;"

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;
var ButtonTop			= 100;
var ButtonWidth			= 110;
var ColorsInUse			= [[], [], [], []];
var ColorsToUse			= [ ["whitesmoke", "mistyrose", "lavenderblush"],
							["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 iC					= new Array ();										// Stores commands to be executed						19 Nov 08
var iH					= new Array ();										// Stores values of innerHTML against raw ids
var iEonmouseover		= new Array ();										// Stores values of onclick events against raw ids
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";
var ButtonColor			= "white";
var ButtonDisabled		= "lightblue";
var ButtonOverBGC		= "lightblue";
var ButtonOverColor		= "black";
var ButtonStayColor		= "white";
var GlobalBackground	= "white";
var GlobalTextColor		= "dimgray";
var LeftPanelBackground	= "gray";
var StripBackground		= "white";
var StripTextColor		= "green";
																			// Level 1
var	ButtonBackground	= LeftPanelBackground;
var ButtonInc			= 40;
var ButtonLeft			= (LeftWidth - ButtonWidth) / 2;
var ButtonStayBGC		= ButtonOverBGC;
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 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 LeftPanelStyle			= ["LeftPanel", "BACKGROUND", LeftPanelBackground, "HEIGHT", UNIT_BASE, "LEFT", 0, "TOP", 0, "WIDTH", LeftWidth ];
var RightPanelStyle			= ["RightPanel", "BACKGROUND", RightPanelBackground, "HEIGHT", RightHeight, "LEFT", LeftWidth, "TOP", 0, "WIDTH", RightWidth];

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 Anchor (text, href)
//-------------------------------------------------------------------------------
	{
	return "<a style='text-decoration: none; color: red' href = '" + href + "'>" + text + "</a>";
	}

//-------------------------------------------------------------------------------
function BaseError (message)
//-------------------------------------------------------------------------------
	{
	Debug ("Error in base routines: ", message);
	}

//-------------------------------------------------------------------------------
function Bottom (obj) 
//-------------------------------------------------------------------------------
{
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);
*/
// Defaults
this.browser		= "Unknown";
this.platform		= "Unknown";
this.version		= "";
this.majorver		= "";
this.minorver		= "";

if (document.URL.match(/index.html/) == _) return;
// 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;

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);
	}
}																			// Deb

}//-------------------------------------------------------------------------------
function Debug (id)
//-------------------------------------------------------------------------------
{
var texttoshow	= id + ": ";
var q;

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 + "; ";

			case "BORDER_BOTTOM":
				stylestring	+= "border-bottom-style: solid;";
				stylestring	+= "border-bottom-width: " + PxH (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;
Debug ("HTMLS5", mouseover);
				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	+ "'"; 

	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 + ">";
Debug ("HTMLS9", textout);
	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 111

var A				=  82;				// Deprecated
var ANCHOR			=  82;
var ACTION			=  78;
var ALIGN			=  24;
var ALIGN_NODE		=  96;
var ALL				= 108;
var ARGUMENTS		=  73;
var BACKGROUND		=   4;
var BACKGROUND_IMAGE= 109;
var BOLD			=  10;				// no value follows
var BORDER			=  18;
var BORDER_BOTTOM	= 101;
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 BY_COLUMNS		= 105;
var BY_ROWS			= 107;
//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 COLUMN_STYLE	= 103;
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 HEADINGS		= 102;												// 13 Aug 07
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 OVERFLOW		= 110;												// 7 Oct 07
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 RELATIVE		= 100;
var RIGHT			=   8;
var ROWS			=  54;
var ROW_STYLE		= 104;
var SELECT			=  90;
var SIZE			=  25;
var SKIP			=  26;
var SKIP_AFTER		=  27;
var SPAN			=  87;
var SRC				=  28;
var START			= 106;
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.
																			//Debug ("N0", idin, typeof idin);
//-------------------------
function NodeError (message)
	{
	Debug ("Error in base routines (node " + obj.id + ")", message);
	}

//-------------------------
function SetUpEvent (val, id)
	{
	if (table) return val;

	var n;
	var o		= Element (id);
	var valout	= val;

																			//Debug ("SUE1", val, id);
	valout	= valout.replace (/#/g, "'" + id + "'");
	valout	= valout.replace (/%/g, o.innerHTML);

//	if ((n = id.split ("-")).length == 3)									// **** This doesn't work at all - recode and test when needed *****************************
//		{
//		var len	= o.parentNode.cells.length / ncols;
//
//		valout	= valout.replace (/!/g, "" + (Node.arraystart + parseInt (n[1]) * len + parseInt (n[2])));
																			//Debug ("SUE5", val, id, valout);
//		}

	return valout;
	}


if (! Node.arraystart) Node.arraystart	= 0;								// This is needed so that "!" can be replaced by a correct array value
if (idin == "WriteText" || idin == "DivStyle")
	{
	arguments	= arguments[1];
	idin		= arguments[0];
	}

//-------------------------
function unpackrange (r, len)
			{
			var dash	= false;
			var first	= true;
			var range	= [];
			var ir		= 0;
			var lastv;
			var rr;
			var v		= 0;
			var vi;
			var vn		= 0;
			var x;

			if (r == "ALL")
				{
				for (vi = 0; vi < len; vi++)
					range[range.length]	= vi;
																		//Debug ("NUR2", idin, r, range);
				return range;
				}

			for (rr = 0; rr < r.length; rr++)
				{
				x	= r.substr(rr, 1);
																		//Debug ("NUR3", idin, r, rr, x);
				if (x.match (/[0-9]/))
					{
					first	= true;
					vn		= vn * 10 + parseInt (x);
					}

				if (x.match (/[,-]/) || rr == r.length - 1)
					{
					if (first)
						{
						if (dash)
							{
							for (vi = ++lastv; vi <= vn; vi++)
								range[range.length]	= vi;
							dash	= false;
							}
						else
							{
							range[range.length]	= vn;
							lastv				= vn;
							}
						first	= false;
						}
					vn					= 0;
					dash	= x.match (/-/);
					}
				}

			return range;
			}

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 bycolumns		= false;
var byrows			= false;
//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			= false;												// 22 Aug 07
var heading			= _;
var headings		= _;
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 ncols			= _;
var nrows			= _;														// Left in for boxes code. Tables now use prows, the number of rows on the page.
var obj;
var objevent;
var objname;
var objstyle;
var overcolor		= _;
var padtoptu		= _;
var properties;
var prows;
var range;
var sizetu;
var start			= 0;
var statustext		= _;
var table			= false;													// The conditions under which this is set true need watching carefully. TABLE musr be used in ll cases.
var tabletop		= false;													// This allows a plain table declaration and is set true if "Node (xxx, TABLE);" 
var tby;																		// Table body object
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.
																				// COLUMN_STYLE and ROW_STYLE must be followed by two array arameters:
																				//			range		a list of all the coluns or rows to be changed, eg [3,5,7]
																				//			parameters	the Node parameters to be applied, eg [BOLD, PAD_RIGHT, 5]

//Debug ("N0", idin);
switch (arguments[1])
	{
	case ARGUMENTS:
		arguments	= [idin].concat (arguments[2]);
		al			= arguments.length;
		break;
	}
	

if (al >= 1)
	if (arguments[argnum] == DEBUG)
		{
		debugused						= true;
		Node.debugcount					= 1;
		arg1++;
		argnum++;
		}

if (al > arg1)
	{
	switch (arguments[argnum])
		{
		case A:
			htmltag		= "a";
			argnum++;
			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];
			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;

			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,
							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		= "select";	//_;
			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 (typeof idin == "string")
	{	
	idintu	= idin;

	//if (first = ! (obj = document.getElementById (idin)))
	if (first = ! (obj = Element (idin)))
		{
																			if (idin == "H1" || idin == "H2") Debug ("N23", idin, "new");
		obj		= document.createElement (htmltag);
		obj.id	= idin;

		if (htmltag == "table")
			{
			tby			= document.createElement ("tbody");
			tby.id		= idintu + "-B";
			obj.appendChild (tby);

			if (tabletop)
				return tby;
			}

		if (type) iH[idin]	= "<input type='" + type + "' name='" + idin + "-input'>"

		document.body.appendChild (obj);
		htmltag	= obj.tagName;

		if (htmltag != "TD")
			obj.style.position	= "absolute";

		innerobj			= document.createElement;
		}
	else
		{
																			if (idin == "H1") Debug ("N25", idin, obj.innerHTML);
																			//Debug ("N30", idin, obj.style.position);
		if (argnum > arg1)
			{
			NodeError ("Attempt to redefine tagName in Node");
			return;
			}
		htmltag	= obj.tagName;
		idintu	= obj.id;
		}
	}
else
	{
	obj		= idin;
	idintu	= obj.id;
	htmltag	= obj.tagName;
	}
switch (htmltag.toLowerCase())
	{
	case ("td"):
		break;

	case "table":
		tby	= obj.tBodies[0];												// Allow TABLE to run into default

	default:
		if (! obj.style.position) obj.style.position		= "absolute";
	}

objstyle			= obj.style

																			// C *****
if (al > argnum)
	{

	while (argnum < al)
		{
		inc		= 2;
		key		= arguments[argnum];
		if (argnum < al -1 ) val		= arguments[argnum + 1];

																			//if (idin == "Content")Debug ("N36", idin, key);
																			//if (idintu == "Extras") Debug ("37", 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.
																			//Debug ("N35", idin, val);
				htmlfound				= (val.match (/</) || val.match (/\&.*;/)) && ! BodyLoaded;			// 29 Oct 07 - Is this the right thing to do???????

				if (first && ! BodyLoaded)
					{
					if (htmlfound)
						{
						iH[idintu]		= val;
						}
					else
						{
						obj.appendChild (document.createTextNode (val));
						}
					}
				else
					{
					obj.innerHTML		= val;
					}
				break;

			case TOP:
					objstyle.top				= PxH (val);
				break;

			case WIDTH:
				if (boxes)													//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 BACKGROUND_IMAGE:
//var xxx;
				objstyle.backgroundImage	= val;
																			//Debug ("N40", obj.id, objstyle.backghroundImage);
				break;

			case BOLD:
				objstyle.fontWeight				= "bold";
				inc								= 1;
				break;

			case BOTTOM:
				objstyle.bottom					= PxH (val);
				break;

			case CENTER:
				objstyle.textAlign				= "center";
//				center							= "center";			//  5 Aug 07
				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;
				
				for (var io = 0; io < opts.length; io++)
					{
					objname.options[io].text	= opts[io];
					}
				break;

			case OVERFLOW:												// 7 Oct 07
				objstyle.overflow		= val;							// 7 Oct 07
				break;													// 7 Oct 07
																	
			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.right			= PxW (val);				// 18 Dec 07
//				objstyle.marginRight	= PxW (val);
				break;

			case SIZE:
																	//if (idin == "DW") Debug ("N50", idin, PxH (val));
				if (typeof val == "number")							// 14 Nov 07
					objstyle.fontSize		= PxH (val);
				else												// 14 Nov 07
					objstyle.fontSize		= val;					// 14 Nov 07
																	//objstyle.fontSize		= obj.size		= PxH (val);
																	//Debug ("N51", idin, objstyle.fontSize);
				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;
																		//Debug ("N70", obj.src);
				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:
				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 (SetUpEvent (val, idin));
				break;
					
			case CLICK:														// Some of the replacement patterns must be evaluated here and some later
				obj.onclick					= new Function (SetUpEvent (val, idin));
				break;

			case DBLCLICK:
				obj.ondblclick				= new Function (SetUpEvent (val, idin));
				break;
					
			case DOWN:
				obj.onmousedown				= new Function (SetUpEvent (val, idin));
				break;


			case OUT:
				obj.onmouseout				= new Function (SetUpEvent (val, idin));
				break;

			case OVER:
				obj.onmouseover				= new Function (SetUpEvent (val, idin));
				break;

			case OVER_COLOR:
				overcolor					= val;
				break;
					
			case UP:
				obj.onmouseup				= new Function (SetUpEvent (val, idin));
				break;
																			// -------------------- Border values ------------------

			case BORDER:
				// Use BORDER_WIDTH in preference
				objstyle.borderStyle		= "solid";
				objstyle.borderWidth		= PxW (val);
				break;

			case BORDER_BOTTOM:
				objstyle.borderBottomStyle	= "solid";
				objstyle.borderBottomWidth	= PxH (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;

				objstyle.borderStyle		= "solid";
				break;
																			// -------------------- Table, forms and boxes values, also COLUMNS and ROWS for TEXTAREAS ------------------------------
			case ACTION:
				obj.action					= val;
				break;

			case BY_COLUMNS:
				bycolumns					= true;
				inc							= 1;
				break;

			case BY_ROWS:
				byrows						= true;
				inc							= 1;
				break;

			case COLUMNS:
				if (htmltag == "textarea")
					{
					obj.cols				= val;
					}
				else
					{
					ncols					= val;
					}
				break;

			case COLUMN_STYLE:
				range		= unpackrange (val);
				for (var ci = 0; ci < range.length; ci++)
					{
					var column	= range[ci];
					var nr		= Element (idin).rows.length;

					for (ri = 0; ri < nr; ri++)
						{
						var idtu	= idin + "-" + ri + "-" + column;

						Node (idtu, ARGUMENTS, arguments[argnum + 2]);
						}
					}
				inc							= 3;
				break;

			case DATA:														// Later calls may have a shorter data array but longer ones will lose elements
				arrays						= 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 HEADINGS:
				headings					= val;
				break;

//			case INDEX_ARRAY:												// The index arrays is now indicated by a null in the array list
//				indexarray					= val;
//				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 PC:
//				obj.width					= val + "%";
//				break;

//			case PROPERTIES:
//				properties					= val;				// eg PROPERTIES, [HEIGHT, 30, WIDTH, 20],...
//				break;

			case ROWS:
				if (htmltag == "textarea")
					{
					obj.rows				= val;
					break;
					}
				nrows						= val;

//				if (table)
//					prows					= val;
	
				break;

			case ROW_STYLE:
				range	= unpackrange (val);

				for (var ri = 0; ri < range.length; ri++)
					{
					var row		= range[ri];
					var nr		= Element (idin).rows.length;

					var rowid	= idin + "-"  + row;

					var nc		= Element (rowid).cells.length;

					for (ci = 0; ci < nc; ci++)
						{
						var idtu	= rowid + "-" + ci;

						Node (idtu, ARGUMENTS, arguments[argnum + 2]);
						}
					}
				inc							= 3;
				break;

			case START:
				start =	Node.arraystart		= val;
				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;
		}
	}
																								// D *****
																//Debug ("N75", idin);

if (statustext != _)
	{
	if (mouseover != _)
		mouseover	=+ ";window.status=\"" + statustext + "\"";
	else
		mouseover	= "window.status=\"" + statustext + "\"";
	if (mouseout != _)
		mouseout	+= ";window.status=\"\"";
	else
		mouseout	= "window.status=\"\"";
	}

if (table)																	// TABLE MUST be set expilicitly. All reference to "table = true" have been commented out.
	{
	var a;
	var al;																	// Length of arrays - set below
	var an			= arrays.length;										// Number of arrays
	var ar;
//	var arms;
	var c;
	var cellvalue;
	var indexarray	= _;
	var lasttc;
	var lasttr;
	var o;
	var pagecolumns;
	var pageitems;
	var pageitemstu;
	var pagerows;															// Effective no  of rows
	var r;
	var tc;
	var tr;
	var x;

//	var	perpage		= nrows * ncols;

	for  (a = 0; a < an; a++)
		{
		if (! arrays[a])
			{
			indexarray	= a;
			break;
			}
		else
			al	= arrays[a].length;
		}
																			// If nrows is not set, it is set to 25
																			// If ncols is not set, it is set to 1 if nrows > 1, to array length if nrows = 1
	if (! nrows) nrows	= 25;
	if (! ncols) ncols	= nrows > 1 ? 1 : al;

	pagecolumns	= ncols * an;												// The actual number of columns of data on the page.
	pageitems	= ncols * nrows;											// The mumber of items used on a apge from each array.

	if (al - start >= pageitems)												// Array longer than or same length as page
		pagerows	= nrows;
	else
		pagerows	= Math.ceil ((al - start) / ncols); 

	pageitemstu		= pagerows * ncols;
																			//Debug ("N82", nrows, ncols, pagerows, pagecolumns, pageitems, pageitemstu);
																			//Create table
	if (first)
		{
		for (r = 0; r < nrows; r++)		//prows; r++)
			{
			o		= document.createElement ("tr");
			tby.appendChild (o);
			o.id	= idintu + "-" + r;

			for (c = 0; c < pagecolumns; c++)		//ncols; c++)
				{
				for (a = 0; a < an; a++)
					{
					o		= document.createElement ("td");
					tby.rows[r].appendChild (o);
					o.id	= idintu + "-" + r + "-" + (c * an + a);
					o.appendChild (document.createTextNode (""));
					}
				}
			}
		}
																			// Add values;
//	if (bycolumns)
//		{
	for (a = 0; a < an; a++)
		{
		for (ar = 0; ar < pageitemstu; ar++)		//start; ar < pp2 + start; ar++)
			{
			var artu	= ar + start;
																			//Debug ("N81", a, an, ar, artu);

			if (artu >= al)													// there are cells to be blanked out
					cellvalue	= "";
				else
					{
					if (! arrays[a])										// this is the index array
						cellvalue	= artu;
					else
						{
						cellvalue	= arrays[a][artu];
						}
					}
			if (bycolumns)
				{
//				arms	= ar - start;
				tr		= ar % pagerows;									// ? nrows
				tc		= Math.floor(ar / pagerows) * (an) + a;
				}
			else															// byrows		Doesn't work yet for ncols > 1
				{
				tr		= Math.floor (ar / ncols) * ncols;
				tc		= ar % ncols;
				}
																			//Debug ("N82", a,ar, artu, tr, tc, cellvalue)

			tby.rows[tr].cells[tc].innerHTML	= cellvalue;

			lasttr	= tr;
			lasttc	= tc;
			}
		}
																			//Debug ("N85", lasttr, tby.rows.length);

		for (tr = lasttr + 1; tr < tby.rows.length; tr++)
			for (tc = 0; tc < tby.rows[0].cells.length; tc++)
				tby.rows[tr].cells[tc].innerHTML	= "";
//		}
//	else if (byrows)
//		{
//		for (a = 0; a < an; a++)
//			{
//			for (ar = 0; ar < pp2; ar++)
//				{


// 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("Pick").innerHTML);
//Debug ("NEXIT", idin, Element(idin).innerHTML);
//if (idin == "Pick") Debug ("NEND", idin, obj.innerHTML);

	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
{

//Debug ("SU0");
var h;
var id;
var s	= Element ("oBody").style;


s.fontFamily	= "Verdana";											//, Times New Roman, Arial, sans-serif";			KONSTAM AMENDMENT *****************************
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];
	}			

for (var c in iC)													// Konstam only		19 Nov 08
	{																// Konstam only		19 Nov 08
	eval (c);														// Konstam only		19 Nov 08
	}																// Konstam only		19 Nov 08

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

