var c_strHighlightClass="focuspcbkgnd";

var c_strActiveClass="activepcbkgnd";

var c_strBackgroundClass="pcbkgnd";

var c_strWrongClass="wrongpcbkgnd";

var c_strCellHighlightClass="focuspc";

var c_strCellActiveClass="activepc";

var c_strCellBackgroundClass="pc";

var c_strCellWrongClass="wrongpc";

var c_strClueTextHighlightClass="activeclue";

var c_strClueTextClass="clue";

var c_strCellPrefix="Cell";

var c_strTextPrefix="Text";

var c_strCluePrefix="Clue";



var c_nKeyDown=40;

var c_nKeyRight=39;

var c_nKeyUp=38;

var c_nKeyLeft=37;

var c_nKeyBack=8;

var c_nKeyDelete=46;

var c_nKeySpace=32;

var c_nKeyReturn=13;

var c_nKeyTab=9;

var c_nAcross=1;

var c_nDown=2;



var m_showErrors = false;

var m_nCurrentClueId=-1;

var m_nCurrentCellId=-1;



function HideErrors()

{

	for ( var nCellId=0;nCellId<(nRows*nColumns);nCellId++)

	{

		if ( document.getElementById(c_strTextPrefix+nCellId) )

		{

			document.getElementById(c_strCellPrefix+nCellId).className=c_strBackgroundClass;

			document.getElementById(c_strTextPrefix+nCellId).className=c_strCellBackgroundClass;

		}

	}

	m_showErrors = false;	

}



function ChangeCellClass(nCellId,strCellClass,strCellBgrndClass)

{

	var nCellId=Number(nCellId);



	if(nCellId<0||nCellId>(nRows*nColumns))

		return;



	document.getElementById(c_strTextPrefix+nCellId).className=strCellClass;	

	document.getElementById(c_strCellPrefix+nCellId).className=strCellBgrndClass;

}



function ChangeClueClass(nClueId,strCellClass,strCellBgrndClass)

{	

	for(var nLoop=0;nLoop<CA[nClueId].length;nLoop+=3)

		ChangeCellClass(CA[nClueId].substring(nLoop,nLoop+3),strCellClass,strCellBgrndClass);

}



function GetColumnId(nCellId)

{

	return (nCellId%nColumns)+1;

}



function GetRowId(nCellId)

{

	return Math.round((nCellId/nColumns)-0.5)+1;

}



function GetOrientation(nClueId)

{

	if(nClueId<0||nClueId>nClueCount-1)

		return;



	if((Number(CA[nClueId].substring(3,6))-Number(CA[nClueId].substring(0,3)))==1)

		return c_nAcross;

	else

		return c_nDown;

}



function FindClueIdGivenCellId(nCellId, bKP)

{

	var oldclues = new Array();

	var clues = new Array();

	var position = new Array();

	

	if ( bKP && m_nCurrentCellId != -1 && m_nCurrentCellId != nCellId )

	{

		for(var nClueId=0;nClueId<nClueCount;nClueId+=1)

			for(var nCheckCellId=0;nCheckCellId<CA[nClueId].length; nCheckCellId+=3)

				if(Number(CA[nClueId].substring(nCheckCellId,nCheckCellId+3))==m_nCurrentCellId)

					oldclues[oldclues.length] = nClueId;

	}

	

	for(var nClueId=0;nClueId<nClueCount;nClueId+=1)

	{

		for(var nCheckCellId=0;nCheckCellId<CA[nClueId].length; nCheckCellId+=3)

		{

			if(Number(CA[nClueId].substring(nCheckCellId,nCheckCellId+3))==nCellId)

			{

				clues[clues.length] = nClueId;

				position[position.length] = nCheckCellId;

			}

		}

	}

	

	if ( bKP && oldclues.length > 0 )

	{

		for ( old = 0; old < oldclues.length; ++old )

			for ( clue = 0; clue < clues.length; ++clue )

				if ( oldclues[old] == clues[clue] && oldclues[old] != m_nCurrentClueId )

					return oldclues[old];

	}

	

	for ( i = 0; i < position.length; ++i )

		if ( position[i] == 0 && clues[i] == m_nCurrentClueId && nCellId != m_nCurrentCellId  )

			return clues[i];

		

	for ( i = 0; i < position.length; ++i )

		if ( position[i] == 0 && nCellId != m_nCurrentCellId)

			return clues[i];

			

	for ( i = 0; i < clues.length; ++i )

		if ( nCellId != m_nCurrentCellId && clues[i] == m_nCurrentClueId )

			return clues[i];

			

	for ( i = 0; i < clues.length; ++i )

		if ( clues[i] != m_nCurrentClueId )

			return clues[i];

			

	return -1;

}



function CellInClue(nCellId,nClueId)

{

	for(var nCheckCellId=0;nCheckCellId<CA[nClueId].length; nCheckCellId+=3)

		if(Number(CA[nClueId].substring(nCheckCellId,nCheckCellId+3))==nCellId)

			return true;



	return false;

}



function FindNextTextCell(start, increment, minimum, maximum)

{

	for (var next = start+increment; minimum <= next && next <= maximum; next+=increment )

		if ( document.getElementById(c_strTextPrefix+next) )

			return next;

	

	return start;

}



function MoveCursor(keyCode, jumpToNextTextCell)

{

	var c_nMinAcross=(GetRowId(m_nCurrentCellId)-1)*nColumns;

	var c_nMaxAcross=(GetRowId(m_nCurrentCellId)*nColumns)-1;

	var c_nMinDown=GetColumnId(m_nCurrentCellId)-1;

	var c_nMaxDown=((nRows)*nColumns)+(GetColumnId(m_nCurrentCellId)-1);



	switch(keyCode)

	{

		case c_nKeyUp:

			if ( jumpToNextTextCell )

				SC(FindNextTextCell(m_nCurrentCellId,-nColumns,c_nMinDown,c_nMaxDown), true);

			else if (m_nCurrentCellId!=c_nMinDown)

				SC(m_nCurrentCellId-nColumns, true);

			break;



		case c_nKeyDown:

			if ( jumpToNextTextCell )

				SC(FindNextTextCell(m_nCurrentCellId,nColumns,c_nMinDown,c_nMaxDown), true);

			else if(m_nCurrentCellId!=c_nMaxDown)

				SC(m_nCurrentCellId+nColumns,true);

			break;

		

		case c_nKeyLeft:

			if ( jumpToNextTextCell )

				SC(FindNextTextCell(m_nCurrentCellId,-1,c_nMinAcross,c_nMaxAcross), true);

			else if(m_nCurrentCellId!=c_nMinAcross)

				SC(m_nCurrentCellId-1,true);

			break;

	

		case c_nKeyRight:

			if ( jumpToNextTextCell )

				SC(FindNextTextCell(m_nCurrentCellId,1,c_nMinAcross,c_nMaxAcross), true);

			else if (GetColumnId(m_nCurrentCellId)<nColumns)

				SC(m_nCurrentCellId+1,true);

			break;

	}

}



function OKP(evnt)

{

	if ( m_showErrors )

		HideErrors();

	

	if ( evnt.which )

	{

		evnt.preventDefault();

		evnt.stopPropagation();

		var keyCode = evnt.which;

	}

	else

	{

		evnt.returnValue = false;

		evnt.cancelBubble = true;

		var keyCode = evnt.keyCode ;

	}

		

	switch(keyCode)

	{

		case c_nKeyUp:

		case c_nKeyDown:

		case c_nKeyLeft:

		case c_nKeyRight:

			MoveCursor(keyCode, true);

			break;

	 

		case c_nKeyReturn:

			SC(m_nCurrentCellId);

			break;



		case c_nKeySpace:

			document.getElementById(c_strTextPrefix+m_nCurrentCellId).value="";

			if (GetOrientation(m_nCurrentClueId)==c_nAcross)

				MoveCursor(c_nKeyRight, false);

			else

				MoveCursor(c_nKeyDown, false);

			break;



		case c_nKeyBack:

			document.getElementById(c_strTextPrefix+m_nCurrentCellId).value="";

			if (GetOrientation(m_nCurrentClueId)==c_nAcross)

				MoveCursor(c_nKeyLeft, false);

			else

				MoveCursor(c_nKeyUp, false);

			break;



	case c_nKeyDelete:

			document.getElementById(c_strTextPrefix+m_nCurrentCellId).value="";

			break;

			

	case c_nKeyTab:

			nextClueId = m_nCurrentClueId+1;

			nextClueId = nextClueId >= nClueCount ? 1 : nextClueId;

			CCH(nextClueId);

			break;



		default:

			if(keyCode>=65&&keyCode<=90)

			{

				document.getElementById(c_strTextPrefix+m_nCurrentCellId).value=String.fromCharCode(keyCode);

				if (GetOrientation(m_nCurrentClueId)==c_nAcross)

					MoveCursor(c_nKeyRight, false);

				else

					MoveCursor(c_nKeyDown, false);

			}

			break;

	}

}



function CCH(nClueId)

{			

	nCellId = Number(CA[nClueId].substring(0,3));

	

	if ( m_nCurrentCellId != -1 )

		ChangeCellClass(m_nCurrentCellId,c_strCellBackgroundClass,c_strBackgroundClass);



	if (m_nCurrentClueId != -1 && nClueId != -1 && m_nCurrentClueId != nClueId)

	{

		ChangeClueClass(m_nCurrentClueId,c_strCellBackgroundClass,c_strBackgroundClass);

		document.getElementById(c_strCluePrefix+m_nCurrentClueId).className=c_strClueTextClass;

	}

		

	if (nClueId != -1)

		m_nCurrentClueId=nClueId;



	m_nCurrentCellId=nCellId;



	ChangeClueClass(m_nCurrentClueId,c_strCellHighlightClass,c_strHighlightClass);

	ChangeCellClass(m_nCurrentCellId,c_strCellActiveClass,c_strActiveClass);

	

	document.getElementById(c_strCluePrefix+m_nCurrentClueId).className=c_strClueTextHighlightClass;

	document.getElementById(c_strTextPrefix+nCellId).focus();

	document.getElementById(c_strTextPrefix+nCellId).select();		

}



function SC(nCellId,bKP)

{

	if ( m_showErrors )

		HideErrors();

			

	if (nCellId<0 || nCellId > (nRows*nColumns) ) {

		return;

	} else if (!document.getElementById(c_strTextPrefix+nCellId)) {

		document.getElementById(c_strTextPrefix+m_nCurrentCellId).select();	

		return;

	}



	if (bKP && m_nCurrentCellId != -1)

	{

		if ( CellInClue(nCellId,m_nCurrentClueId) )

			var nCurrentClueId=-1; /* Prevents unhighlighting of clue */

		else

			var nCurrentClueId=FindClueIdGivenCellId(nCellId,bKP);

	}

	else

	{

		var nCurrentClueId = FindClueIdGivenCellId(nCellId,bKP);

	}



	if ( m_nCurrentCellId != -1 )

		ChangeCellClass(m_nCurrentCellId,c_strCellBackgroundClass,c_strBackgroundClass);



	if (m_nCurrentClueId != -1 && nCurrentClueId != -1 && m_nCurrentClueId != nCurrentClueId)

	{

		ChangeClueClass(m_nCurrentClueId,c_strCellBackgroundClass,c_strBackgroundClass);

		document.getElementById(c_strCluePrefix+m_nCurrentClueId).className=c_strClueTextClass;

	}

		

	if (nCurrentClueId != -1)

		m_nCurrentClueId=nCurrentClueId;



	m_nCurrentCellId=nCellId;



	ChangeClueClass(m_nCurrentClueId,c_strCellHighlightClass,c_strHighlightClass);

	ChangeCellClass(m_nCurrentCellId,c_strCellActiveClass,c_strActiveClass);

	

	document.getElementById(c_strCluePrefix+m_nCurrentClueId).className=c_strClueTextHighlightClass;

	

	if ( document.getElementById("crossword").className == "compact" ) {

	 	ScrollIntoView(m_nCurrentClueId);

	}

	

	document.getElementById(c_strTextPrefix+nCellId).focus();

	document.getElementById(c_strTextPrefix+nCellId).select();	

}



function RL(nCellId)

{

	if ( m_showErrors )

		HideErrors();

		

	if(nCellId == undefined)

		nCellId = m_nCurrentCellId;



	nClueId = m_nCurrentClueId;



	if(nCellId<0||nCellId>(nRows*nColumns) || nClueId<0||nClueId>nClueCount-1)

		return;

		

	for(var nLoop=0;nLoop<CA[nClueId].length;nLoop+=3)

	{

		if (Number(CA[nClueId].substring(nLoop,nLoop+3)) == nCellId )

		{

			idx = nLoop/3;

			document.getElementById(c_strTextPrefix+nCellId).value = WA[nClueId].substring(idx,idx+1);

			break;

		}

	}

}



function RC(nClueId)

{

	if ( m_showErrors )

		HideErrors();

		

	if(nClueId == undefined)

		nClueId = m_nCurrentClueId;

		

	if(nClueId<0||nClueId>nClueCount-1)

		return;

		

	var nCurrentCell = 0;

	for(var nLoop=0;nLoop<CA[nClueId].length;nLoop+=3)

	{

		var strCurrentCell = c_strTextPrefix+Number(CA[nClueId].substring(nLoop,nLoop+3));

		document.getElementById(strCurrentCell).value = WA[nClueId].substring(nCurrentCell++,nCurrentCell);

	}

}



function RA()

{

	if ( !confirm("This will reveal all the answers to the crossword. Press OK if you want to continue.") )

		return;

		

	if ( m_showErrors )

		HideErrors();

		

	if (m_nCurrentClueId != -1 )

	{

		ChangeClueClass(m_nCurrentClueId,c_strCellBackgroundClass,c_strBackgroundClass);

		document.getElementById(c_strCluePrefix+m_nCurrentClueId).className=c_strClueTextClass;

	}

	

	m_nCurrentClueId = -1;

	for ( var nLoop=0; nLoop<nClueCount; nLoop++)

		RC(nLoop);

}



function R()

{

	if ( m_showErrors )

		HideErrors();

		

	for ( var nCellId=0;nCellId<(nRows*nColumns);nCellId++)

	{

		if ( document.getElementById(c_strTextPrefix+nCellId))

			document.getElementById(c_strTextPrefix+nCellId).value = "";

	}

}



function PG()

{

	if ( m_showErrors )

		HideErrors();

	

	m_nCurrentClueId = -1;

	for ( var nLoop=0; nLoop<nClueCount; nLoop++)

		RC(nLoop);



	for ( var nCellId=0;nCellId<(nRows*nColumns);nCellId++)

	{

		if ( document.getElementById(c_strTextPrefix+nCellId))

			document.getElementById(c_strTextPrefix+nCellId).readOnly = true;

	}	

}



function GRS()

{	

	var delimeter = "";

	var output = "";

	for ( var i = 0; i < nRows*nColumns; ++i )

	{

		if ( (element = document.getElementById("Text" + i) ) )

		{

			if ( element.value != "" )

			{

				output = output + delimeter + i + ":" + element.value;

				delimeter = "|";

			}

		}

	}

	return output;

}



function SE()

{

	if (m_nCurrentClueId != -1 )

		ChangeClueClass(m_nCurrentClueId, c_strCellBackgroundClass, c_strBackgroundClass);



	for ( var nClueId=0; nClueId < nClueCount; nClueId++)

	{

		for(var cellPos=0, letterPos=0; cellPos < CA[nClueId].length; cellPos+=3, ++letterPos)

		{

			var cellId = Number(CA[nClueId].substring(cellPos,cellPos+3));

			var letter = WA[nClueId].substring(letterPos,letterPos+1);

			var current = document.getElementById(c_strTextPrefix+cellId).value.toUpperCase();

			if ( current != "" && current != letter )

			{

					document.getElementById(c_strCellPrefix+cellId).className=c_strWrongClass;

					document.getElementById(c_strTextPrefix+cellId).className=c_strCellWrongClass;

			}

		}

	}

	

	m_showErrors = true;

}



function RS(cell, word)

{	

	m_nCurrentClueId=word;

	m_nCurrentCellId=cell;

	ChangeClueClass(m_nCurrentClueId,c_strCellHighlightClass,c_strHighlightClass);

	ChangeCellClass(m_nCurrentCellId,c_strCellActiveClass,c_strActiveClass);

	document.getElementById(c_strCluePrefix+m_nCurrentClueId).className=c_strClueTextHighlightClass;

	document.getElementById(c_strTextPrefix+m_nCurrentCellId).focus();

	document.getElementById(c_strTextPrefix+m_nCurrentCellId).select();	

}



function GCCL()

{

	return m_nCurrentClueId;

}



function GCCE()

{

	return m_nCurrentCellId;

}



function ScrollIntoView(clueId)

	{

		var clue = document.getElementById(c_strCluePrefix+clueId);

		if ( !clue )

			return;

		

		var parent = clue.parentNode;

		if ( !parent )

			return;

		

		var offset = 0, begin = parent.scrollTop, end = parent.scrollTop + parent.offsetHeight;

		for ( var i = 0; parent.childNodes.length; ++i )

		{

			if ( parent.childNodes[i].id == clue.id )

				break;

			

			offset += parent.childNodes[i].offsetHeight == undefined ? 0 : parent.childNodes[i].offsetHeight;

		}

	

		if ( offset < (end-2) && begin < offset )

			return;

		

		parent.scrollTop = offset;

	}
