
var ScrSizeAsc	= 4;
var ScrSizeHex	= 8;
var ScrSizeDec	=11;
var ScrSizeOct	=12;
var ScrSizeBin	=ScrSizeHex<<2;

var iStackSize	=25;
var iHexaNum	= 8;
var iBitsNum	=iHexaNum<<2;

var NumStack	,
	OpStack		;
var iNumStackLen=-1;
var iOpStackLen	=-1;
var bRes		=true	,
	bErr		=false	,
	bChange		=true	;
var refBase		=16;
var iMem		= 0;




function SubString(text,debut,fin)
	{
	debut=Math.max(0,debut);
	fin  =Math.min(text.length,fin);

	if (fin>debut)
		return text.substring(debut,fin);
	  else
		return '';
	}



function InitTab(iNum)
	{
	this.length=iNum;
	}



function Clear(bClrScr)
	{
	iNumStackLen=iOpStackLen=0;
	bRes=bChange=true;
	bErr=false;

	if (bClrScr)
		{
		document.Calc.ScreenHex.value=
		document.Calc.ScreenDec.value=
		document.Calc.ScreenOct.value=
		document.Calc.ScreenBin.value=
		document.Calc.ScreenAsc.value='0';
		}
	}


function GetScreen(base)
	{
	if (base== 0)	return document.Calc.ScreenAsc.value;
	if (base== 2)	return document.Calc.ScreenBin.value;
	if (base== 8)	return document.Calc.ScreenOct.value;
	if (base==10)	return document.Calc.ScreenDec.value;
					return document.Calc.ScreenHex.value;
	}



function SetScreen(sText,base)
	{
	switch (base)
		{
		case  0:
					document.Calc.ScreenAsc.value=sText; break;
		case  2:
					document.Calc.ScreenBin.value=sText; break;
		case  8:
					document.Calc.ScreenOct.value=sText; break;
		case 10:
					document.Calc.ScreenDec.value=((''+sText=='NaN')?'0':sText); break;
		default:
					document.Calc.ScreenHex.value=sText;
		}
	}



function GetScreenValue(base)
	{
	var s	=GetScreen(base);
	var res	=0;

	if (base==10) return parseInt(s);

	if (base==0)
		{
		for (i=0;i<s.length;i++)
			{
			if (s.charAt(i)<' ')	continue;

			res=(res<<8) + s.charCodeAt(i);
			}
		return res;
		}

	if (base==2)
		{
		for (i=0;i<s.length;i++)
			{
			if ((s.charAt(i)!='0')
			  &&(s.charAt(i)!='1'))	continue;

			res=(res<<1)+parseInt(s.charAt(i),2);
			}
		return res;
		}

	if (base==8)
		{
		for (i=0;i<s.length;i++)
			{
			if ((s.charAt(i)<'0')||(s.charAt(i)>'7'))	continue;

			res=(res<<3) + parseInt(s.charAt(i),8);
			}
		return res;
		}

	if (base==16)
		{
		for (i=0;i<s.length;i++)
			{
			if (((s.charAt(i)<'0')||(s.charAt(i)>'9'))
			  &&((s.charAt(i)<'A')||(s.charAt(i)>'F'))
			  &&((s.charAt(i)<'a')||(s.charAt(i)>'f')))	continue;

			res=(res<<4) + parseInt(s.charAt(i),16);
			}
		return res;
		}

	return res;
	}



function SetRefBase(base)
	{
	refBase=base;

	document.getElementById("ButtonHex").className="kWhite";
	document.getElementById("ButtonDec").className="kWhite";
	document.getElementById("ButtonOct").className="kWhite";
	document.getElementById("ButtonBin").className="kWhite";
	document.getElementById("ButtonAsc").className="kWhite";

	switch (base)
		{
		case  0:
					document.getElementById("ButtonAsc").className="kWhite_o"; break;
		case  2:
					document.getElementById("ButtonBin").className="kWhite_o"; break;
		case  8:
					document.getElementById("ButtonOct").className="kWhite_o"; break;
		case 10:
					document.getElementById("ButtonDec").className="kWhite_o"; break;
		default:
					document.getElementById("ButtonHex").className="kWhite_o";
		}

	for (i=0; i<base;i++)	eval("document.getElementById('b"+i+"').style.color='#333333'");
	for (i=base;i<16;i++)	eval("document.getElementById('b"+i+"').style.color='#CCCCCC'");
	}



function ConvertTo(iValue,base)
	{
	if (iValue==0) return '0';

	if (base==10) return iValue;

	var s='';

	if (base==0)
		{
		for (;iValue>0;iValue>>>=8)
			{
			s=''+String.fromCharCode(iValue & 255)+s;
			}

		return s;
		}


	if (iValue>0)
		{
		switch (base)
			{
			case 2:
						for (;iValue>0;iValue>>>=1)
							s=''+(iValue & 1)+s;
						break;
			case 8:
						for (;iValue>0;iValue>>>=3)
							{
							var iDigit=iValue & 7;
							if (iDigit<10)
								s=''+iDigit+s;
							  else
								s=''+unescape('%3'+(iDigit-9))+s;
							}
						break;
			default:
						for (;iValue>0;iValue>>>=4)
							{
							var iDigit=iValue & 15;
							if (iDigit<10)
								s=''+iDigit+s;
							  else
								s=''+unescape('%4'+(iDigit-9))+s;
							}
			}
		}
	  else
		{
		switch (base)
			{
			case 2:
						for (iValue=-iValue -1, i=0; i<(iHexaNum<<2); iValue>>>=1, i++)
							s=''+((~ iValue) & 1)+s;
						break;
			case 8:
						for (iValue=-iValue -1, i=0 ; i<iHexaNum; iValue>>>=3, i++)
							{
							var iDigit=7-(iValue & 7);
							if (iDigit<10)
								s=''+iDigit+s;
							  else
								s=''+unescape('%3'+(iDigit-9))+s;
							}
						break;
			default:
						for (iValue=-iValue -1, i=0 ; i<iHexaNum; iValue>>>=4, i++)
							{
							var iDigit=15-(iValue & 15);
							if (iDigit<10)
								s=''+iDigit+s;
							  else
								s=''+unescape('%4'+(iDigit-9))+s;
							}
			}
		}

	return s;
	}



function SetToValidNumber(base)
	{
	if (bErr) return;

	switch (base)
		{
		case  0:
					SetScreen(GetScreenValue( 0),10); break;
		case  2:
					SetScreen(GetScreenValue( 2),10); break;
		case  8:
					SetScreen(GetScreenValue( 8),10); break;
		case 10:
					SetScreen(GetScreenValue(10),10); break;
		default:
					SetScreen(GetScreenValue(16),10); break;
		}

	SetScreen(ConvertTo(GetScreenValue(10), 0), 0);
	SetScreen(ConvertTo(GetScreenValue(10), 2), 2);
	SetScreen(ConvertTo(GetScreenValue(10), 8), 8);
	SetScreen(ConvertTo(GetScreenValue(10),16),16);

	bChange=true;
	}



function InitCalc()
	{
	if (iNumStackLen!=-1)  return;

	NumStack=new InitTab(iStackSize);
	OpStack =new InitTab(iStackSize);
	SetRefBase(16);
	Clear(false);
	SetToValidNumber(10);
	}



function Error(sError)
	{
	bErr=bRes=true;
	document.Calc.ScreenHex.value=sError+" !";
	return 0;
	}



function DelChar(sText,iPos)
	{
	if ((iPos>=0)
	  &&(iPos< sText.length))
		return SubString(sText,0,iPos)+SubString(sText,iPos+1,sText.length);
	  else
		return SubString(sText,0,sText.length-1);
	}



function AddDigit(sDigit)
	{
	if (bErr || (parseInt(sDigit,16) > refBase))  return;

	if (bRes)
		{
		SetScreen(sDigit,refBase);
		bRes=false;
		}
	  else
		if (((refBase==16)&&(GetScreen(16).length<ScrSizeHex))
		  ||((refBase==10)&&(GetScreen(10).length<ScrSizeDec))
		  ||((refBase== 8)&&(GetScreen( 8).length<ScrSizeOct))
		  ||((refBase== 2)&&(GetScreen( 2).length<ScrSizeBin))
		  ||((refBase== 0)&&(GetScreen( 0).length<ScrSizeAsc)))
			SetScreen(GetScreen(refBase) + sDigit,refBase);

	SetToValidNumber(refBase);
	}



function DelDigit()
	{
	if (bErr) return;
	if (!bRes) SetScreen(DelChar(GetScreen(refBase),-1),refBase);
	SetToValidNumber(refBase);
	}



function ChangeSign()
	{
	if (bErr) return;
	SetScreen(1 + ~ GetScreenValue(10),10);
	SetToValidNumber(10);
	bRes=true;
	}



function Not()
	{
	if (bErr) return;
	SetScreen(~ GetScreenValue(10),10);
	SetToValidNumber(10);
	bRes=true;
	}



function ManualEntry(base)
	{
	if (base== 0) document.Calc.ScreenDec.value=GetScreenValue( 0);
	if (base== 2) document.Calc.ScreenDec.value=GetScreenValue( 2);
	if (base== 8) document.Calc.ScreenDec.value=GetScreenValue( 8);
	if (base==16) document.Calc.ScreenDec.value=GetScreenValue(16);

	SetToValidNumber(10);
	bRes=bErr=false;
	}



function MemoryMinus()
	{
	if (bErr) return;
	iMem-=GetScreenValue(10);
	bRes=true;
	}



function MemoryPlus()
	{
	if (bErr) return;
	iMem+=GetScreenValue(10);
	bRes=true;
	}



function MemoryRestore()
	{
	if (bErr) return;
	document.Calc.ScreenDec.value=iMem;
	SetToValidNumber(10);
	bRes=true;
	}



function MemoryClear()
	{
	iMem=0;
	}



function GetOppLevel(sOpp)
	{
	if ( sOpp=="(" ) return -1;
	if ((sOpp=="lSh")||(sOpp=="rSh" )||(sOpp=="zrSh")) return 4;
	if ((sOpp=="or")||(sOpp=="and")||(sOpp=="xor")) return 3;
	if ((sOpp=="*" )||(sOpp=="/")) return 2;
	if ((sOpp=="+" )||(sOpp=="-")) return 1;
	return 0;
	}



function Calculate(f1,f2,sOp)
	{
	if (sOp=="+") return f1+f2;
	if (sOp=="-") return f1-f2;
	if (sOp=="*") return f1*f2;

	if (sOp=="/")
		if (f2==0)
			return Error("Division by zero");
		  else
			return Math.floor(f1/f2);

	if (sOp=="or"  ) return f1|f2;
	if (sOp=="and" ) return f1&f2;
	if (sOp=="xor" ) return f1^f2;
	if (sOp=="rSh" ) return f1>>f2;
	if (sOp=="zrSh") return f1>>>f2;
	if (sOp=="lSh" ) return f1<<f2;

	return Error("Invalid operator");
	}



function PileUpOpp(sOpp)
	{
	if (!bChange) return;

	if (iNumStackLen==-1)  InitCalc();

	if (  bErr
	  ||(iNumStackLen>=iStackSize)
	  ||(iOpStackLen >=iStackSize))
		Error("Stack overflow");
	  else
		{
		NumStack[iNumStackLen++]=GetScreenValue(10);
		OpStack [iOpStackLen++ ]=sOpp;

		while ((iOpStackLen>=2)
			 &&(GetOppLevel(OpStack[iOpStackLen-1])
			 <= GetOppLevel(OpStack[iOpStackLen-2])))
			{
			NumStack[iNumStackLen-2]=Calculate(NumStack[iNumStackLen-2],
											   NumStack[iNumStackLen-1],
											   OpStack[iOpStackLen  -2]);

			if (!bErr) SetScreen(NumStack[iNumStackLen-2], 10);

			OpStack[iOpStackLen-2]=OpStack[iOpStackLen-1];
			iNumStackLen--;
			iOpStackLen--;
			}
		SetToValidNumber(10);
		bRes=true;
		bChange=false;
		}
	}



function OpenBrackets()
	{
	if (iNumStackLen==-1)  InitCalc();

	if (bErr || (iOpStackLen>=iStackSize))
		Error("Stack overflow");
	  else
		{
		OpStack[iOpStackLen++]="(";
		bRes=bChange=true;
		}
	}



function CloseBrackets()
	{
	while (iOpStackLen>=1)
		{
		if (OpStack[iOpStackLen-1] == "(")
			{
			iOpStackLen--;
			break;
			}

		var iRes=Calculate (NumStack[iNumStackLen-1],
							GetScreenValue(10),
							OpStack[iOpStackLen-1] );

		if (!bErr) SetScreen(iRes,10);
		iNumStackLen--;
		iOpStackLen--;
		}

	bRes=true;
	SetToValidNumber(10);
	}



function Equal()
	{
	while (iOpStackLen>=1)
		CloseBrackets();
	}


///////////////////////////////////////////////////////////////////
function Links(n)
	{
	if (n< 0)  return '&nbsp;';

	iResult="<span class='h'>Char code #"+n+"</b></span><p><font color='#999999'>More info:</font><br />";

	if ((n>=  0)&& n<=127)	iResult+="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href='info.php?c="+n+"' onclick='return popUp("+n+");'><b>::<\/b> ASCII Table<\/a>";
	if ((n> 127)&&(n<=255))	iResult+="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>::<\/b> ANSI Table<br>"
									+"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>::<\/b> Extended Set";
	if ( n> 255)			iResult+="&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>::<\/b> Unicode Table";

	return iResult;
	}

///////////////////////////////////////////////////////////////////



function popUp(i)
	{
	var h=screen.height;
	var w=screen.width ;

	var l=parseInt((w-350)/2);
	var t=parseInt((h-450)/2);

	iWin=window.open('info.php?c='+i,'info','dependent,width=360,height=450,left='+l+',top='+t+',directories=no,location=no,menubar=no,resizable=no,scrollbars=no,status=no,toolbar=no');
	iWin.focus();
	return false;
	}



