/****************************/
/*      MISC ROUTINES       */
/* (c)1995 Pangea Software  */
/* By Brian Greenstone      */
/****************************/


/***************/
/* EXTERNALS   */
/***************/


extern	EventRecord	gTheEvent;
extern	Boolean		gQD3DInitialized;

/****************************/
/*    CONSTANTS             */
/****************************/

#define		ERROR_ALERT_ID		401

/**********************/
/*     VARIABLES      */
/**********************/

KeyMap gKeyMap,gOldKeyMap;

unsigned long	gTick = 0;


unsigned long seed0 = 0, seed1 = 0, seed2 = 0;

/****************** DO SYSTEM ERROR ***************/

void ShowSystemErr(long err)
{
Str255		numStr;

	NumToString(err, numStr);
	DoAlert (numStr);
	
	DebugStr("\perr");
	CleanQuit();
}

/*********************** DO ALERT *******************/

void DoAlert(Str255 s)
{
	ParamText(s,NIL_STRING,NIL_STRING,NIL_STRING);
	NoteAlert(ERROR_ALERT_ID,NIL_POINTER);
	DebugStr("\perr");
}
		
/*********************** DO FATAL ALERT *******************/

void DoFatalAlert(Str255 s)
{
	ParamText(s,NIL_STRING,NIL_STRING,NIL_STRING);
	NoteAlert(ERROR_ALERT_ID,NIL_POINTER);
	CleanQuit();
	DebugStr("\perr");
}

/************ CLEAN QUIT ***************/

void CleanQuit(void)
{
	ExitToShell();
}



/***************** NUM TO HEX *****************/
//
// NumToHex - fixed length, returns a C string
//

unsigned char *NumToHex(unsigned short n)
{
static unsigned char format[] = "0xXXXX";				// Declare format static so we can return a pointer to it.
char *conv = "0123456789ABCDEF";
short i;

	for (i = 0; i < 4; n >>= 4, ++i)
			format[5 - i] = conv[n & 0xf];
	return format;
}




/*************** NUM TO DECIMAL *****************/
//
// NumToDecimal --  returns a ++PASCAL++ string.
//

unsigned char *NumToDec(unsigned long n)
{
static unsigned char format[] = "\pXXXXXXXX";				// Declare format static so we can return a pointer to it
char *conv = "0123456789";
short		 i,digits;
unsigned long temp;

	if (n < 10)										// fix digits
		digits = 1;
	else if (n < 100)
		digits = 2;
	else if (n < 1000)
		digits = 3;
	else if (n < 10000)
		digits = 4;
	else if (n < 100000)
		digits = 5;
	else
		digits = 6;

	format[0] = digits;								// adjust length byte of output string

	for (i = 0; i < digits; ++i)
	{
		temp = n/10;
		format[digits-i] = conv[n-(temp*10)];
		n = n/10;
	}
	return format;
}


/**************** READ KEYBOARD *************/

void ReadKeyboard(void)
{
	GetKeys(gKeyMap);								// READ THE REAL KEYBOARD
}


/****************** GET KEY STATE ***********/
//
// NOTE: Assumes that ReadKeyboard has already been called!!
//

Boolean GetKeyState(unsigned short key)
{
unsigned char *keyMap;

	keyMap = (unsigned char *)&gKeyMap;
	return ( ( keyMap[key>>3] >> (key & 7) ) & 1);
}




/*************** ABSOLUTE ********************/

float Absolute(float f)
{
	if (f < 0)
		return(-f);
	else
		return(f);
}


/******************** MY RANDOM LONG **********************/
//
// My own random number generator that returns a LONG
//
// NOTE: call this instead of MyRandomShort if the value is going to be
//		masked or if it just doesnt matter since this version is quicker
//		without the 0xffff at the end.
//

unsigned long MyRandomLong(void)
{
  return seed2 ^= (((seed1 ^= (seed2>>5)*1568397607UL)>>7)+
                   (seed0 = (seed0+1)*3141592621UL))*2435386481UL;
}
 

/**************** SET MY RANDOM SEED *******************/

void SetMyRandomSeed(unsigned long seed)
{
	seed0 = seed;
	seed1 = 0;
	seed2 = 0;	
}

/************************* RANDOM RANGE *************************/

unsigned short	RandomRange(unsigned short min, unsigned short max)
{
register	unsigned short		qdRdm;							// treat return value as 0-65536
register	unsigned long		range, t;

	qdRdm = MyRandomLong()&0xffff;
	range = max+1 - min;
	t = (qdRdm * range)>>16;	 							// now 0 <= t <= range
	
	return( t+min );
}




/******************* FLOAT TO STRING *******************/

void FloatToString(float num, Str255 string)
{
Str255	sf;
long	n,i,f;

	n = (long)(num*1000);			// shift decimal place down 4 places, then truncate the rest
	i = n/1000;						// get integer part
	f = n%1000;						// get remainder/fractional part
	if (f < 0)
		f = -f;

	if ((i==0) && (num < 0))		// special case if (-), but integer is 0
	{
		string[0] = 2;
		string[1] = '-';
		string[2] = '0';
	}
	else
		NumToString(i,string);		// make integer into string
		
	NumToString(f,sf);				// make fraction into string
	
	string[++string[0]] = '.';		// add "." into string
	for (i = 0; i < sf[0]; i++)
	{
		string[++string[0]] = sf[i+1];	// copy fraction into string
	}
}

/****************** ALLOC HANDLE ********************/

Handle AllocHandle(long size)
{
Handle	hand;
OSErr	err;

	hand = NewHandleClear(size);					// alloc in APPL
	if (hand == nil)
	{
		hand = TempNewHandle(size,&err);			// try TEMP mem
		return(hand);
	}
	else
		return(hand);								// use APPL
}


/****************** ALLOC PTR ********************/

void *AllocPtr(long size)
{
Ptr	pr;

	pr = NewPtrClear(size);						// alloc in APPL
	return(pr);
}

/************* COPY PSTR **********************/

void CopyPStr(ConstStr255Param	inSourceStr, StringPtr	outDestStr)
{
short	dataLen = inSourceStr[0] + 1;
	
	BlockMoveData(inSourceStr, outDestStr, dataLen);
	outDestStr[0] = dataLen - 1;
}












