#include "Script.hpp"
//===========================================================================//
// File:	 Script	.cpp													 //
// Project:  GOSScript				                                         //
// Contents: Script control													 //
//---------------------------------------------------------------------------//
// Date      Who    Modification                                             //
// 02/27/98  AG		Created													 //
//---------------------------------------------------------------------------//
// Copyright (C) 2000, Microsoft, Inc.										//
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

int __cdecl CompareObjectsDrawOrder( const void* arg1, const void *arg2 );
int __cdecl CompareObjectsExecuteOrder( const void* arg1, const void *arg2 );
int __cdecl CompareObjectsExpense( const void* arg1, const void *arg2 );

extern OBJECT* pFocusedObject;
extern SCRIPT* pFocusedScript;
extern int scriptLastKey;

extern SCRIPT*			pListofScripts;		// All scripts loaded into memory

extern int ScriptMouseButton1;	// for use as variable within scripts
extern int ScriptMouseButton2; // for use as variable within scripts
extern int ScriptMouseButton3; // for use as variable within scripts
extern int ScriptMouseButton4; // for use as variable within scripts
extern int ScriptMouseButton5; // for use as variable within scripts
extern int ScriptPointerDevice;
extern DWORD gIgnoreFlags;
extern DWORD gEnableScriptSpews;
extern OBJECT * pInRegionTopmost;
extern HGOSFONT3D gScriptFont3d;
extern HGOSHEAP gScriptHeap[] = {0,0,0,0,0,0};
OBJECT ** pStart = NULL;
extern DWORD InternalRunGameOSLogic(void (*)(void)); 

extern PaneTextureList * gMasterPaneTextureList;

int DrawDebugging(OBJECT * obj, int nStage, int& nLastPos);
extern CUBE g_textMargins;
void ShowScriptSpewOutput();
void ShowExpenseReport();
void ShowSpewDrawBackground(DWORD x1, DWORD y1, DWORD x2, DWORD y2, DWORD color);
void ShowScriptsLoaded();
void GetJoystickInput();
extern bool bIgnoreMouseMessages;
extern DWORD g_mailStack;
extern int g_scriptPostedInteger[][8];
extern OBJECT * g_scriptMailPoster[];


extern bool gScript_InDraw;

bool ScriptsRunning=0;
extern void(__stdcall *DoScriptUpdate)(int);
extern int ScriptSP;
int totalObjectNumber = 0;
void (_stdcall *DoModalScriptLogic)(void);

extern DWORD gosScript_localizationFile;
extern DWORD gCurrentHeapStackLevel;
extern HGOSHEAP ClientHeap;

#ifdef LAB_ONLY
char gScriptSpewLog[32][SPEWLINE_LENGTH];
char gScriptExpenseReport[32][SPEWLINE_LENGTH];
bool gFreezeExpenses = false;
extern bool DebuggerActive;
extern bool InDebugger;
#endif 

DWORD gScriptSpewLogItr = 0;
DWORD Button[5] = {BUTTON_FREE, BUTTON_FREE, BUTTON_FREE, BUTTON_FREE, BUTTON_FREE};
DWORD ButtonPrev[5] = {BUTTON_FREE, BUTTON_FREE, BUTTON_FREE, BUTTON_FREE, BUTTON_FREE};
DWORD ButtonDebounce[5] = {BUTTON_FREE, BUTTON_FREE, BUTTON_FREE, BUTTON_FREE, BUTTON_FREE};

double ButtonTimes[5] = {0,0,0,0,0};

DWORD	ScriptsDefaultFrameRate  = 60;
DWORD	gEnableScriptsLoaded = 0;
DWORD	gEnableScriptRegions=0;
DWORD	gEnableScriptMargins=0;
DWORD	gEnableScriptSpews=0;
DWORD	gEnableScriptPanes=0;
DWORD	gEnableExpenseReport=0;
DWORD	gDisableScriptRender=0;
DWORD	gScriptColorCycle = 0;
bool	gScriptPaneFlicker = false;
OBJECT * pBlockingObjects[16];
int lastScreenWidth = 0;

double gScriptLastTime = 0;

bool ShowFastPane=0;
bool ShowFastRect=0;
bool EnableFastPath=1;

BYTE g_bLeadByte = 0;
extern BYTE LeadByteTable[];

#define ProfileTime(x, y)  x = gos_GetHiResTime(); y; x = gos_GetHiResTime() - x;

bool __stdcall CheckScriptsLoaded()
{
	return gEnableScriptsLoaded != 0;
}
void __stdcall EnableScriptsLoaded()
{
	gEnableScriptsLoaded =! gEnableScriptsLoaded;
	if (gEnableScriptsLoaded)
	{
		gEnableScriptRegions = 0;
		gEnableScriptSpews = 0;
		gEnableScriptMargins = 0;
		gEnableScriptPanes = 0;
		gEnableExpenseReport = 0;
	}
}

bool __stdcall CheckScriptRegions()
{
	return gEnableScriptRegions != 0;
}
void __stdcall EnableScriptRegions()
{
	gEnableScriptRegions =! gEnableScriptRegions;
	if (gEnableScriptRegions)
	{
		gEnableScriptsLoaded = 0;
		gEnableScriptSpews = 0;
		gEnableScriptMargins = 0;
		gEnableScriptPanes = 0;
		gEnableExpenseReport = 0;
	}
}

bool __stdcall CheckScriptMargins()
{
	return gEnableScriptMargins != 0;
}
void __stdcall EnableScriptMargins()
{
	gEnableScriptMargins =! gEnableScriptMargins;
	if (gEnableScriptMargins)
	{
		gEnableScriptsLoaded = 0;
		gEnableScriptSpews = 0;
		gEnableScriptRegions = 0;
		gEnableScriptPanes = 0;
		gEnableExpenseReport = 0;
	}
}

bool __stdcall CheckScriptSpews()
{
	return gEnableScriptSpews!=0;
}
void __stdcall EnableScriptSpews()
{
	gEnableScriptSpews =! gEnableScriptSpews;
	if (gEnableScriptSpews) 
	{
		gEnableScriptsLoaded = 0;
		gEnableScriptRegions = 0;
		gEnableScriptMargins = 0;
		gEnableScriptPanes = 0;
		gEnableExpenseReport = 0;
	}

}

bool __stdcall CheckScriptPanes()
{
	return gEnableScriptPanes!=0;
}
void __stdcall EnableScriptPanes()
{
	gEnableScriptPanes =! gEnableScriptPanes;
	if (gEnableScriptPanes) 
	{
		gEnableScriptsLoaded = 0;
		gEnableScriptSpews = 0;
		gEnableScriptRegions = 0;
		gEnableScriptMargins = 0;
		gEnableExpenseReport = 0;
	}

}

bool __stdcall CheckExpenseReport()
{
	return gEnableExpenseReport!=0;
}
void __stdcall EnableExpenseReport()
{
	gEnableExpenseReport =! gEnableExpenseReport;
	if (gEnableExpenseReport) 
	{
		gEnableScriptsLoaded = 0;
		gEnableScriptPanes = 0;
		gEnableScriptSpews = 0;
		gEnableScriptRegions = 0;
		gEnableScriptMargins = 0;
	}

}

bool __stdcall CheckScriptDisableRender()
{
	return gDisableScriptRender != 0;
}
void __stdcall DisableScriptRender()
{
	gDisableScriptRender =! gDisableScriptRender;
}

bool __stdcall CheckFastPane()
{
	return ShowFastPane;
}
void __stdcall EnableFastPane()
{
	ShowFastPane=!ShowFastPane;
}
bool __stdcall CheckUsingBlade()
{
	return Environment.Renderer!=3;
}

bool __stdcall CheckFastRect()
{
	return ShowFastRect;
}
void __stdcall EnableFastRect()
{
	ShowFastRect=!ShowFastRect;
}

bool __stdcall CheckFastPath()
{
	return EnableFastPath;
}
void __stdcall ToggleFastPath()
{
	EnableFastPath=!EnableFastPath;
}

//
// Faster float to long  (Always rounds to nearest)  ie: -2.7 goes to 3
//
inline long float2long( float fval )
{
	fval += 3 << 22;
	return ((*(long*)&fval)&0x007fffff) - 0x00400000;
}


#if (DISTRIBUTED_GOSSCRIPT == 0)
int InsideScripts=0;
bool InScriptRender=0;
char* (__stdcall *SavedGetGameInformation)();
extern char* __stdcall ErrorInScript();
//
//
// Save and restore the 'GameOS Error Handler' - so any errors in GameOS routines append script information...
//
//
void PushInScripts( bool InRender )
{
	if( ++InsideScripts==1 )
	{
		InScriptRender=InRender;
		SavedGetGameInformation=Environment.GetGameInformation;
		Environment.GetGameInformation=ErrorInScript;
	}
}

void PopInScripts()
{
	if( --InsideScripts==0 )
	{
		Environment.GetGameInformation=SavedGetGameInformation;
	}
}
#else
void PushInScripts( bool )
{
}
void PopInScripts()
{
}
#endif //DISTRIBUTED_GOSSCRIPT




//
//
//
void __stdcall gosScript_InitializeProcessor(int defaultFrameRate, void (_stdcall *ModalScriptLogic) (void))
{
	if( !ScriptsRunning )
	{
		AddDebuggerMenuItem( "Libraries\\gosScript\\Show regions", CheckScriptRegions, EnableScriptRegions );
		AddDebuggerMenuItem( "Libraries\\gosScript\\Show margins", CheckScriptMargins, EnableScriptMargins );
		AddDebuggerMenuItem( "Libraries\\gosScript\\Show spews", CheckScriptSpews, EnableScriptSpews );
		AddDebuggerMenuItem( "Libraries\\gosScript\\Show panes", CheckScriptPanes, EnableScriptPanes );
		AddDebuggerMenuItem( "Libraries\\gosScript\\Show expense report", CheckExpenseReport, EnableExpenseReport );
		AddDebuggerMenuItem( "Libraries\\gosScript\\Show loaded scripts", CheckScriptsLoaded, EnableScriptsLoaded );
		AddDebuggerMenuItem( "Libraries\\gosScript\\Disable rendering", CheckScriptDisableRender, DisableScriptRender );
		AddDebuggerMenuItem( "Libraries\\gosScript\\Show 'fast PANE' rendering", CheckFastPane, EnableFastPane, CheckUsingBlade );
		AddDebuggerMenuItem( "Libraries\\gosScript\\Show 'fast DRAWRECT' rendering", CheckFastRect, EnableFastRect, CheckUsingBlade );
		AddDebuggerMenuItem( "Libraries\\gosScript\\Enable fast path rendering", CheckFastPath, ToggleFastPath, CheckUsingBlade );
		gosScript_localizationFile = 0;
		ScriptsRunning=1;
		InitLineBuffer();
		InitScripts();
		ModalScripts=0;
		ScriptSP=0;
		DoScriptUpdate = ScriptsUpdate;
		DoModalScriptLogic = ModalScriptLogic;
		ScriptsDefaultFrameRate = defaultFrameRate;
		InitTextCache();
		lastScreenWidth = Environment.screenWidth;
		#ifdef LAB_ONLY
			if( gos_DoesFileExist("assets\\graphics\\arial8.tga") )
				gScriptFont3d = gos_LoadFont( "assets\\graphics\\arial8.tga" );
			else
				gScriptFont3d = gos_LoadFont( "arial8.tga" );

			memset(gScriptSpewLog,0, SPEWLINE_LENGTH*32);
		#endif
	}
}
//
//
//
void __stdcall gosScript_ShutdownProcessor()
{
	if( ScriptsRunning )
	{
		//
		// we need to remove the menu items we've added!
		//
		DelDebuggerMenuItem( "Libraries\\gosScript\\Show regions" );
		DelDebuggerMenuItem( "Libraries\\gosScript\\Show margins" );
		DelDebuggerMenuItem( "Libraries\\gosScript\\Show spews" );
		DelDebuggerMenuItem( "Libraries\\gosScript\\Show panes" );
		DelDebuggerMenuItem( "Libraries\\gosScript\\Show expense report" );
		DelDebuggerMenuItem( "Libraries\\gosScript\\Show loaded scripts" );
		DelDebuggerMenuItem( "Libraries\\gosScript\\Disable rendering" );
		DelDebuggerMenuItem( "Libraries\\gosScript\\Show 'fast PANE' rendering"  );
		DelDebuggerMenuItem( "Libraries\\gosScript\\Show 'fast DRAWRECT' rendering" );
		DelDebuggerMenuItem( "Libraries\\gosScript\\Enable fast path rendering" );

		DoScriptUpdate = NULL;
		ModalScripts=0;
		ScriptsRunning=0;
	}

	DestroyTextCache();
	DestroyScripts();
	ModalScripts=0;
	ScriptSP=0;
#ifdef LAB_ONLY
	if (gScriptFont3d)
	{
		gos_DeleteFont(gScriptFont3d);
		gScriptFont3d = NULL;
	}
#endif

	// shut down the last string resource, if any
	if (gosScript_localizationFile)
	{
		gos_CloseResourceDLL(gosScript_localizationFile);
		gosScript_localizationFile = 0;
	}
	gMasterPaneTextureList = 0;
}







extern DWORD __stdcall RunGameOSLogic();
extern void __stdcall ExitGameOS();
extern volatile __int64 TimeGameLogic;

extern OBJECT** pStart;
//
//
// GameOS entry point from user applications
//
// 0x2000 For Priority means 'MODAL'
//
HGOSSCRIPT __stdcall gosScript_ExecuteScript( const char* ScriptFileName, int Priority, void * ptr )
{
//
// Prepare the script (read in, find functions and messages)
//
#if defined(_DEBUG) && 0
    int nLen = strlen(ScriptFileName);
    static const char* s_pcszNL = "netlobby.script";
    int nNLL = strlen(s_pcszNL);
    if (nLen >= nNLL) {
        if (stricmp(&ScriptFileName[nLen - nNLL], s_pcszNL) == 0) {
            PAUSE(("Script(%s) executed", s_pcszNL));
        }
    }
#endif // _DEBUG
	if (!ScriptsRunning)
		STOP(( "gosScript has not been initialized" ));
	SavePosition();
	if( Priority>=0x2000 && Priority < 0x4000)
		ModalScripts++;
	SPEW((GROUP_SCRIPTS,"Executing script \"%s\", priority=0x%x",ScriptFileName, Priority ));
	HGOSSCRIPT scr;
	scr = (HGOSSCRIPT)ProcessScript( (char*)ScriptFileName, Priority, ptr );
	SendScriptMessage( scr->pMainObject, MSG_GUI_RESOLUTION );
	RestorePosition();
//
// Call main loop directly on modal scripts
//
	bool restore = false;
	OBJECT ** pSaveObjectArray = NULL;
	int SaveIndex = 0;
	int nSaveObjectNumber = 0;
	int nSaveTotalObjectNumber = 0;
	while(ModalScripts == 1 && Priority>=0x2000 && Priority < 0x4000)
	{
		SPEW((GROUP_SCRIPTS,"Entering modal script loop" ));
		DWORD Terminate=0;

		// save the current object list as well as the current *pStart
		restore = true;
		SaveIndex = (pStart - pObjectArray);
		pSaveObjectArray = (OBJECT **) gos_Malloc(sizeof(OBJECT *) * ObjectNumber);
		memcpy(pSaveObjectArray, pObjectArray, sizeof(OBJECT *) * ObjectNumber);
		nSaveObjectNumber = ObjectNumber;
		nSaveTotalObjectNumber = totalObjectNumber;
					 
		do
		{
			#if (DISTRIBUTED_GOSSCRIPT == 0)
				Terminate=gos_RunMainLoop( DoModalScriptLogic );
			#else
				Terminate=InternalRunGameOSLogic(DoModalScriptLogic);
			#endif

		} while( ModalScripts && !Terminate );

		if( !Terminate )
			break;

		if (Environment.TerminateGameEngine)
		{
			DWORD stackLevel = gCurrentHeapStackLevel;
			gos_PushCurrentHeap(ClientHeap);
			Environment.TerminateGameEngine();
			gos_PopCurrentHeap();
			if (stackLevel > gCurrentHeapStackLevel)
				STOP(("The heap stack was popped more times than it was pushed"));
			else
			if (stackLevel < gCurrentHeapStackLevel)
				STOP(("The heap stack was pushed more times than it was pushed"));
		}
		gos_Free(pSaveObjectArray);
		ExitGameOS();										// Last minute cleanup routines
		SPEW((GROUP_SCRIPTS,"Exiting modal script loop" ));
		return NULL;
	}
	if (restore)
	{
		gos_Free(pObjectArray);
		pObjectArray = pSaveObjectArray;
		pStart = &pSaveObjectArray[SaveIndex];
		ObjectNumber = nSaveObjectNumber;
		totalObjectNumber = nSaveTotalObjectNumber;
	}

	return scr;
}

//
//Find the script handle based on the script name and instance.  This handle can be used
//in gosScript_Command calls, for instance.
//
HGOSSCRIPT _stdcall gosScript_GetScriptHandle( const char *pszScriptName, int Instance )
{
	if (!ScriptsRunning)
		STOP(( "gosScript has not been initialized" ));
	gosASSERT(pszScriptName);
	
	char szTmpName[260] = "@";
	strcat(szTmpName, pszScriptName);
	strcat(szTmpName, "@");
	
	SCRIPT *tmp = pListofScripts;
	while (tmp)
	{
		if (0 == strcmpi(tmp->pMainObject->Name, szTmpName) && Instance == tmp->Instance)
		{
			return tmp;
		}
		tmp = tmp->pNext;
	}
	return NULL;
}

bool __stdcall gosScript_EndScript( HGOSSCRIPT Handle )
{
	if (!Handle)
	{
		SPEW((GROUP_SCRIPTS,"NULL script handle, returning from gosScript_EndScript"));
		return 0;
	}
	SavePosition();
	pScript= (SCRIPT *)Handle;
	SCRIPT * tmp = pListofScripts;
	while (tmp)
	{
		if ((SCRIPT *) Handle == tmp)
		{
			SPEW((GROUP_SCRIPTS,"Ending script %s, HGOSSCRIPT = 0x%x",Handle->pMainObject->Name, (int) Handle));
			SendScriptMessage(tmp->pMainObject, MSG_GUI_DESTROY);
			EndScript();
			RestorePosition();
			return true;
		}
		tmp = tmp->pNext;
	}
	RestorePosition();
	//#removed for demo STOP(("A bad handle was passed to gosScript_EndScript"));
	return false;
}

bool __stdcall gosScript_EndAllScripts(void)
{
	SCRIPT * tmp = pListofScripts;
	while (tmp)
	{
		SPEW((GROUP_SCRIPTS,"Ending script %s, HGOSSCRIPT = 0x%x", tmp ->pMainObject->Name, (int) tmp));
		SCRIPT * next = tmp->pNext;
		pScript=tmp;
		SendScriptMessage(tmp->pMainObject, MSG_GUI_DESTROY);
		EndScript();
		tmp = next;
	}
	return true;
}

int __stdcall gosScript_GetScriptPriority( HGOSSCRIPT Handle )
{
	SCRIPT * tmp = pListofScripts;
	while (tmp)
	{
		if ((SCRIPT *) Handle == tmp)
		{
			return *tmp->pMainObject->Priority;
		}
		tmp = tmp->pNext;
	}
	STOP(("Script handle is invalid"));
	return false;
}
void __stdcall gosScript_SetScriptPriority( HGOSSCRIPT Handle, int Priority )
{
	SCRIPT * tmp = pListofScripts;
	while (tmp)
	{
		if ((SCRIPT *) Handle == tmp)
		{
			*tmp->pMainObject->Priority =  Priority;
			return;
		}
		tmp = tmp->pNext;
	}
	STOP(("Script handle is invalid"));
}

//
// Pause a currently loaded script. Region-checking and GUI_EXECUTE will not be enabled.
// If drawMeThough is set to true, the GUI_DRAW will be called whether or not the script
// is paused.
//
bool _stdcall gosScript_PauseScript(HGOSSCRIPT Handle, bool drawMeThough)
{
	if (!ScriptsRunning)
		STOP(( "gosScript has not been initialized" ));
	SCRIPT * tmp = pListofScripts;
	while (tmp)
	{
		if ((SCRIPT *) Handle == tmp)
		{
			SendScriptMessage( tmp->pMainObject, MSG_GUI_PAUSE );
			tmp->dwPaused = (drawMeThough ? 1 : 2);
			return true;
		}
		tmp = tmp->pNext;
	}
	return false;
}

//
// Resume processing and drawing a paused script.
//
bool _stdcall gosScript_ContinueScript(HGOSSCRIPT Handle)
{
	if (!ScriptsRunning)
		STOP(( "gosScript has not been initialized" ));
	SCRIPT * tmp = pListofScripts;
	while (tmp)
	{
		if ((SCRIPT *) Handle == tmp)
		{

			tmp->dwPaused = 0;
			SendScriptMessage( tmp->pMainObject, MSG_GUI_CONTINUE );
			return true;
		}
		tmp = tmp->pNext;
	}
	return false;
}


//-----------------------------------------------
// Increase array, if needed, by 32 more objects
//-----------------------------------------------
void GrowObjectArray(int Number, OBJECT ***Index = NULL)
{
	if (Number > ObjectNumber)
	{
		OBJECT **tmp = pObjectArray;
		pObjectArray = (OBJECT **)gos_Malloc( (Number+32)*sizeof(OBJECT *), gScriptHeap[0] );
		if (Index)
		{
			*Index = pObjectArray + (*Index - tmp);	//same place in new array
		}
		if (tmp)
		{
			memcpy(pObjectArray, tmp, ObjectNumber*sizeof(OBJECT *));
			gos_Free(tmp);
		}
		ObjectNumber = Number+32;
	}
}

//-----------------------------------------------------------
// Called every game loop to execute all the running scripts
//-----------------------------------------------------------
void ScriptsExecute()
{
//
// Trap errors that occur in gosScript callbacks
//
	PushInScripts(0);

	//--------------------------------
	// Setup variables once per frame
	//--------------------------------
	float the_time = (float) gos_GetElapsedTime(1);

	// this value hold the first item which had the pointer over it...
	pInRegionTopmost = NULL;
	// this helps with the pass_on of region entered/exited messages
	gIgnoreFlags = 0;

	float MouseX, MouseY;
	int	MouseWheelDelta;
	DWORD Buttons;

	gos_GetMouseInfo( &MouseX, &MouseY, 0, 0, &MouseWheelDelta, &Buttons );

	if (ScriptPointerDevice == -1)
	{
		ScriptMousePosition->x	= float2long(MouseX*Environment.screenWidth-0.5f);
		ScriptMousePosition->y	= float2long(MouseY*Environment.screenHeight-0.5f);
		ScriptMousePosition->z  = MouseWheelDelta;

		Button[0] = (BUTTON_STATES) gos_GetKeyStatus(KEY_LMOUSE);
		Button[1] = (BUTTON_STATES) gos_GetKeyStatus(KEY_RMOUSE);
		Button[2] = (BUTTON_STATES) gos_GetKeyStatus(KEY_MMOUSE);
		Button[3] = (BUTTON_STATES) gos_GetKeyStatus(KEY_MOUSEX1);
		Button[4] = (BUTTON_STATES) gos_GetKeyStatus(KEY_MOUSEX2);
	}
	else
	{
		GetJoystickInput();
	}

	//---------------------------------------------
	// This flag is used to trap calls to blits
	// and renders outside GUI_DRAW
	gScript_InDraw = false;


	//---------------------------------------------
	// Order all Objects in reverse-draw-order 
	//	  for event processing and script execution
	//---------------------------------------------
	pScript = pListofScripts;
	pStart = pObjectArray;
	OBJECT *pObj = NULL;
	totalObjectNumber = 0;

	int Number = 0;

	while (pScript)
	{
		// if the resolution changes, tell all scripts, regardless of their states
		if (Environment.screenWidth != lastScreenWidth)
			SendScriptMessage(pScript->pMainObject, MSG_GUI_RESOLUTION);

		pObj = pScript->pListofObjects;
		while (pObj)
		{
			if(  pObj->bActive && pObj->pFunction && pScript->dwPaused != 2 )
			{
				if (ModalScripts && (*pObj->Priority)<0x2000 )
				{
					pObj->LastRan = the_time;
				}
				else
				{
					++Number;
				
					GrowObjectArray(Number, &pStart);
			
					*pStart++ = pObj;
				}
			}
			else
				pObj->LastRan = the_time;
			pObj = pObj->pNext;
		}
		pScript = pScript->pNext;
	}

	lastScreenWidth = Environment.screenWidth;

	//
	// Sort the array by priority in execution order (highest first)
	//
	totalObjectNumber = Number;
	qsort( pObjectArray, Number, sizeof(OBJECT *), CompareObjectsExecuteOrder );

	bool In_Region_Blocked = false;

	//-----------------------------------------------
	// Now execute all the objects in priority order
	//-----------------------------------------------
	pStart=pObjectArray;
	for( int t0=0; t0<Number; t0++ )
	{
		ScriptMouseButton1 = Button[0];
		ScriptMouseButton2 = Button[1];
		ScriptMouseButton3 = Button[2];
		ScriptMouseButton4 = Button[3];
		ScriptMouseButton5 = Button[4];

		pScript=(*pStart)->pScript;

		if (pScript->dwPaused) 
		{
			(*pStart)->LastRan = (float) gos_GetElapsedTime(1);
			++pStart;
			continue;
		}
		// Now, if an object is in focus via the FOCUS keyword, send chars to it
		if (*pStart == pFocusedObject)
		{
			if (!(gos_GetMachineInformation( gos_Info_GetApplicationStatus ) & 2)) 
			{
				// application doesn't have application status
				SendScriptMessage( pFocusedObject, MSG_GUI_UNFOCUS );
				pFocusedObject = NULL;
			}
			else
			{
				while ((scriptLastKey = gos_GetKey()) != 0)
				{
					SendScriptMessage( pFocusedObject, MSG_GUI_CHAR );
					if (g_bLeadByte)	// if the last char is trail byte, clear lead byte data.
						g_bLeadByte = 0;
					else if (LeadByteTable[(unsigned char)scriptLastKey])	// if the last char is lead byte, save it.
						g_bLeadByte = (unsigned char )scriptLastKey;
				}
			}
		}

		//
		// The objRegion code below has been added to accomodate the relative 
		// positioning flag in gui_objects.
		//
		CUBE objRegion = 
		{
			(*pStart)->Cube->p1.x,
			(*pStart)->Cube->p1.y,
			0,
			(*pStart)->Cube->p2.x,
			(*pStart)->Cube->p2.y,
			0
		};

		OBJECT * ptr = *pStart;
		while (ptr)
		{
			objRegion.p1.x += ptr->Coordinates->x;
			objRegion.p1.y += ptr->Coordinates->y;
			objRegion.p2.x += ptr->Coordinates->x;
			objRegion.p2.y += ptr->Coordinates->y;
			if (*ptr->bPosRelative)
				ptr = ptr->pParentObject;
			else
				break;
		};
		//
		// is the mouse in this object's region?
		//
		if ( (*(*pStart)->AlwaysInRegion ||
				(ScriptMousePosition->x >= objRegion.p1.x &&
				ScriptMousePosition->x < objRegion.p2.x &&
				ScriptMousePosition->y >= objRegion.p1.y &&
				ScriptMousePosition->y < objRegion.p2.y)) 
			)
		{
			// it is! was it inside the region last time as well?
			
			if (!In_Region_Blocked)
			{
				if (!(*pStart)->bMouseInRegion )
				{
					// ptr in script region for first time!
				  	(*pStart)->bMouseInRegion = true;
					SendScriptMessage( *pStart, MSG_REGION_ENTERED );
				  	if ( gIgnoreFlags&(1<<MSG_REGION_ENTERED))
					{
						In_Region_Blocked = true;
						OBJECT ** itr = pStart+1;
						while (itr <= pObjectArray)
						{
							if (((OBJECT*)*itr)->bMouseInRegion )
							{
								// yes it was! let the object know the cursor has left!
								(*itr)->bMouseInRegion = false;
								(*itr)->bInFocus = false;
								SendScriptMessage( *itr, MSG_REGION_EXITED );
							}
							itr++;
						}
					}

				}
				else
				{
					pInRegionTopmost = *pStart;
					if ((*pStart)->dwBlockingFlags & (1<<MSG_REGION_ENTERED))
						In_Region_Blocked = true;
				}
			}
			
			// let the obj know that the delta changed (if it did, that is!)
			if ( MouseWheelDelta  && !(gIgnoreFlags & (1<<MSG_WHEEL_MOVED))  || *(*pStart)->AlwaysInRegion )
			{
				SendScriptMessage( *pStart, MSG_WHEEL_MOVED );
			}
	
			// send any pertinent lbutton messages
			if (!(gIgnoreFlags& (1<<MSG_LBUTTON_UPDATE)) || *(*pStart)->AlwaysInRegion)
			{
				if (ButtonDebounce[0] == BUTTON_DCLICKED ||
					ButtonDebounce[0] == BUTTON_CLICKED)
				{
					ScriptMouseButton1 = BUTTON_RELEASED;					
					SendScriptMessage( *pStart, MSG_LBUTTON_UPDATE );
				}

				switch (Button[0])
				{
				case BUTTON_FREE:
					break;
				case BUTTON_PRESSED:
					SendScriptMessage( *pStart, MSG_LBUTTON_UPDATE );
					(*pStart)->bInFocus = true;
					break;
				case BUTTON_HELD:
					SendScriptMessage( *pStart, MSG_LBUTTON_UPDATE );
					break;
				case BUTTON_RELEASED:
					if (ButtonDebounce[0] == BUTTON_FREE)
					{
						ScriptMouseButton1 = BUTTON_PRESSED;					
						SendScriptMessage( *pStart, MSG_LBUTTON_UPDATE );
						if ((*pStart)->dwDblClicks)
							ScriptMouseButton1 = BUTTON_DCLICKED;					
						else
							ScriptMouseButton1 = BUTTON_CLICKED;					
						SendScriptMessage( *pStart, MSG_LBUTTON_UPDATE );
						ScriptMouseButton1 = BUTTON_RELEASED;
						Button[0] = BUTTON_DCLICKED;
					}
					else
					{
						if ((*pStart)->bInFocus)
						{
							ScriptMouseButton1 = BUTTON_CLICKED;
							Button[0] = BUTTON_CLICKED;
							SendScriptMessage( *pStart, MSG_LBUTTON_UPDATE );
						}
						else
							SendScriptMessage( *pStart, MSG_LBUTTON_UPDATE );
						(*pStart)->bInFocus = false;
					}
					break;
				}
			}
			
			// send any pertinent rbutton messages
			if (!(gIgnoreFlags& (1<<MSG_RBUTTON_UPDATE)) || *(*pStart)->AlwaysInRegion)
			{
				if (ButtonDebounce[1] == BUTTON_DCLICKED ||
					ButtonDebounce[1] == BUTTON_CLICKED)
				{
					ScriptMouseButton2 = BUTTON_RELEASED;					
					SendScriptMessage( *pStart, MSG_RBUTTON_UPDATE );
				}

				switch (Button[1])
				{
				case BUTTON_FREE:
					break;
				case BUTTON_PRESSED:
					SendScriptMessage( *pStart, MSG_RBUTTON_UPDATE );
					(*pStart)->bInFocus = true;
					break;
				case BUTTON_HELD:
					SendScriptMessage( *pStart, MSG_RBUTTON_UPDATE );
					break;
				case BUTTON_RELEASED:
					if (ButtonDebounce[1] == BUTTON_FREE)
					{
						ScriptMouseButton2 = BUTTON_PRESSED;					
						SendScriptMessage( *pStart, MSG_RBUTTON_UPDATE );
						ScriptMouseButton2 = BUTTON_RELEASED;					
						SendScriptMessage( *pStart, MSG_RBUTTON_UPDATE );
						if ((*pStart)->dwDblClicks)
							ScriptMouseButton2 = BUTTON_DCLICKED;					
						else
							ScriptMouseButton2 = BUTTON_CLICKED;					
						SendScriptMessage( *pStart, MSG_RBUTTON_UPDATE );
						ScriptMouseButton2 = BUTTON_RELEASED;
						Button[1] = BUTTON_DCLICKED;
					}
					else
					{
						if ((*pStart)->bInFocus)
						{
							ScriptMouseButton2 = BUTTON_CLICKED;
							Button[1] = BUTTON_CLICKED;
							SendScriptMessage( *pStart, MSG_RBUTTON_UPDATE );
						}
						else
							SendScriptMessage( *pStart, MSG_RBUTTON_UPDATE );
						(*pStart)->bInFocus = false;
					}
					break;
				}
			}
			
			// send any pertinent mbutton messages
			if (!(gIgnoreFlags& (1<<MSG_MBUTTON_UPDATE))  || *(*pStart)->AlwaysInRegion)
			{
				if (ButtonDebounce[2] == BUTTON_DCLICKED ||
					ButtonDebounce[2] == BUTTON_CLICKED)
				{
					ScriptMouseButton3 = BUTTON_RELEASED;					
					SendScriptMessage( *pStart, MSG_MBUTTON_UPDATE );
				}

				switch (Button[2])
				{
				case BUTTON_FREE:
					break;
				case BUTTON_PRESSED:
					SendScriptMessage( *pStart, MSG_MBUTTON_UPDATE );
					(*pStart)->bInFocus = true;
					break;
				case BUTTON_HELD:
					SendScriptMessage( *pStart, MSG_MBUTTON_UPDATE );
					break;
				case BUTTON_RELEASED:
					if (ButtonDebounce[2] == BUTTON_FREE)
					{
						ScriptMouseButton3 = BUTTON_PRESSED;					
						SendScriptMessage( *pStart, MSG_MBUTTON_UPDATE );
						if ((*pStart)->dwDblClicks)
							ScriptMouseButton3 = BUTTON_DCLICKED;					
						else
							ScriptMouseButton3 = BUTTON_CLICKED;					
						SendScriptMessage( *pStart, MSG_MBUTTON_UPDATE );
						ScriptMouseButton3 = BUTTON_RELEASED;
						Button[2] = BUTTON_DCLICKED;
					}
					else
					{
						if ((*pStart)->bInFocus)
						{
							ScriptMouseButton3 = BUTTON_CLICKED;
							Button[2] = BUTTON_CLICKED;
							SendScriptMessage( *pStart, MSG_MBUTTON_UPDATE );
						}
						else
							SendScriptMessage( *pStart, MSG_MBUTTON_UPDATE );
						(*pStart)->bInFocus = false;
					}
					break;
				}
			}

			// send any pertinent lbutton messages
			if (!(gIgnoreFlags& (1<<MSG_AUX1BUTTON_UPDATE)) || *(*pStart)->AlwaysInRegion)
			{
				if (ButtonDebounce[3] == BUTTON_DCLICKED ||
					ButtonDebounce[3] == BUTTON_CLICKED)
				{
					ScriptMouseButton4 = BUTTON_RELEASED;					
					SendScriptMessage( *pStart, MSG_LBUTTON_UPDATE );
				}

				switch (Button[3])
				{
				case BUTTON_FREE:
					break;
				case BUTTON_PRESSED:
					SendScriptMessage( *pStart, MSG_AUX1BUTTON_UPDATE );
					(*pStart)->bInFocus = true;
					break;
				case BUTTON_HELD:
					SendScriptMessage( *pStart, MSG_AUX1BUTTON_UPDATE );
					break;
				case BUTTON_RELEASED:
					if (ButtonDebounce[3] == BUTTON_FREE)
					{
						ScriptMouseButton4 = BUTTON_PRESSED;					
						SendScriptMessage( *pStart, MSG_AUX1BUTTON_UPDATE );
						if ((*pStart)->dwDblClicks)
							ScriptMouseButton4 = BUTTON_DCLICKED;					
						else
							ScriptMouseButton4 = BUTTON_CLICKED;					
						SendScriptMessage( *pStart, MSG_AUX1BUTTON_UPDATE );
						ScriptMouseButton4 = BUTTON_RELEASED;
						Button[3] = BUTTON_DCLICKED;
					}
					else
					{
						if ((*pStart)->bInFocus)
						{
							ScriptMouseButton4 = BUTTON_CLICKED;
							Button[3] = BUTTON_CLICKED;
							SendScriptMessage( *pStart, MSG_AUX1BUTTON_UPDATE );
						}
						else
							SendScriptMessage( *pStart, MSG_AUX1BUTTON_UPDATE );
						(*pStart)->bInFocus = false;
					}
					break;
				}
			}

			// send any pertinent lbutton messages
			if (!(gIgnoreFlags& (1<<MSG_AUX2BUTTON_UPDATE)) || *(*pStart)->AlwaysInRegion)
			{
				if (ButtonDebounce[4] == BUTTON_DCLICKED ||
					ButtonDebounce[4] == BUTTON_CLICKED)
				{
					ScriptMouseButton5 = BUTTON_RELEASED;					
					SendScriptMessage( *pStart, MSG_AUX2BUTTON_UPDATE );
				}

				switch (Button[4])
				{
				case BUTTON_FREE:
					break;
				case BUTTON_PRESSED:
					SendScriptMessage( *pStart, MSG_AUX2BUTTON_UPDATE );
					(*pStart)->bInFocus = true;
					break;
				case BUTTON_HELD:
					SendScriptMessage( *pStart, MSG_AUX2BUTTON_UPDATE );
					break;
				case BUTTON_RELEASED:
					if (ButtonDebounce[4] == BUTTON_FREE)
					{
						ScriptMouseButton5 = BUTTON_PRESSED;					
						SendScriptMessage( *pStart, MSG_AUX2BUTTON_UPDATE );
						if ((*pStart)->dwDblClicks)
							ScriptMouseButton5 = BUTTON_DCLICKED;					
						else
							ScriptMouseButton5 = BUTTON_CLICKED;					
						SendScriptMessage( *pStart, MSG_AUX2BUTTON_UPDATE );
						ScriptMouseButton5 = BUTTON_RELEASED;
						Button[4] = BUTTON_DCLICKED;
					}
					else
					{
						if ((*pStart)->bInFocus)
						{
							ScriptMouseButton5 = BUTTON_CLICKED;
							Button[4] = BUTTON_CLICKED;
							SendScriptMessage( *pStart, MSG_AUX2BUTTON_UPDATE );
						}
						else
							SendScriptMessage( *pStart, MSG_AUX2BUTTON_UPDATE );
						(*pStart)->bInFocus = false;
					}
					break;
				}
			}

			if (!pInRegionTopmost)	
			{
				pInRegionTopmost = *pStart;
				// something was already "entered"
				// send a exited to anything else until no pass_on is encountered
				OBJECT ** itr = pStart+1;
				while (itr <= pObjectArray)
				{
					if (((OBJECT*)*itr)->bMouseInRegion )
					{
						// yes it was! let the object know the cursor has left!
						(*itr)->bMouseInRegion = false;
						(*itr)->bInFocus = false;
						if (!(gIgnoreFlags & (1<<MSG_REGION_EXITED)) )
							SendScriptMessage( *itr, MSG_REGION_EXITED );
						if ((gIgnoreFlags & (1<<MSG_REGION_EXITED)) )
						{
							In_Region_Blocked = true;	
							break;
						}
					}
					itr++;
				}
			}
			
		}
		else
		{
			// mouse isn't in region. was it in the region last time?
			if ((*pStart)->bMouseInRegion )
			{
				// yes it was! let the object know the cursor has left!
				(*pStart)->bMouseInRegion = false;
				(*pStart)->bInFocus = false;
				if ( !(gIgnoreFlags & (1<<MSG_REGION_EXITED)) )
					SendScriptMessage( *pStart, MSG_REGION_EXITED );
			}
		}


		// in execute loops, you'll never encounter a BUTTON_CLICKED!
		ScriptMouseButton1 = Button[0];
		ScriptMouseButton2 = Button[1];
		ScriptMouseButton3 = Button[2];
		ScriptMouseButton4 = Button[3];
		ScriptMouseButton5 = Button[4];

#ifdef LAB_ONLY
		double itrTime = 0;
#endif
		if (*((*pStart)->FrameRate) > 0)
		{
			float time_slice = 1.0f/(*((*pStart)->FrameRate));
			long timesToRun = (long) ((the_time - (*pStart)->LastRan) / time_slice);
			float leftOver = (the_time - (*pStart)->LastRan) - (time_slice*timesToRun);
			int itrCount = 0;
#ifdef LAB_ONLY
			if( gEnableExpenseReport )
				(*pStart)->timeInExecute = 0.0;
#endif
			while (
				pScript->bAddToDeathRow != 1 &&
				(*pStart)->bAddToDeathRow != 1 &&
				itrCount < timesToRun
			)
			{
				itrCount++;
#ifdef LAB_ONLY
				if( gEnableExpenseReport )
				{
					ProfileTime(itrTime, SendScriptMessage( *pStart, MSG_GUI_EXECUTE))
				}
				else
#endif
				SendScriptMessage( *pStart, MSG_GUI_EXECUTE);
				if (*(*pStart)->Catchup)
				{
#ifdef LAB_ONLY
					if( gEnableExpenseReport)
						(*pStart)->timeInExecute += itrTime;
#endif
				}
				else
				{
#ifdef LAB_ONLY
					if( gEnableExpenseReport)
						(*pStart)->timeInExecute += itrTime;
#endif
					break;
				}
			}
			(*pStart)->LastRan = the_time - leftOver;
		}
		else
		if (*((*pStart)->FrameRate) == -1)	// run once!
		{
			if ( pScript->bAddToDeathRow != 1 && (*pStart)->bAddToDeathRow != 1)
			{
				*((*pStart)->FrameRate) = 0;	//allow framerate to be changed in GUI_EXECUTE
				(*pStart)->LastRan = the_time;
#ifdef LAB_ONLY
				if( gEnableExpenseReport)
				{
					ProfileTime(itrTime, SendScriptMessage( *pStart, MSG_GUI_EXECUTE));
					(*pStart)->timeInExecute = itrTime;
				}
#endif
			}
		}
#ifdef LAB_ONLY
		else
			(*pStart)->timeInExecute = 0.0f;
#endif

		
		++pStart;
	}

	//----------------------------------------
	// remove any unwanted scripts or objects
	//   and setup drawlist
	//----------------------------------------
	pScript = pListofScripts;
	pStart = pObjectArray;
	Number = 0;
	SCRIPT *pScriptNext;
	while (pScript)
	{
		pScriptNext = pScript->pNext;
		if (pScript->bAddToDeathRow == 1)
		{
			gosScript_EndScript(pScript);

			// i need to rebuild the object array!
		}
		else
		{
			pObj = pScript->pListofObjects;
			OBJECT *pObjNext;

			while (pObj)
			{
				pObjNext = pObj->pNext;
				if (pObj->bAddToDeathRow == true)
				{
					// problem in here!
					if (pObject == pInRegionTopmost)
						pInRegionTopmost = NULL;
					DeleteScriptObject(pObj);
				}
				pObj = pObjNext;
			}
			
			pObj = pScript->pListofObjects;
			while (pObj)
			{
				if(  pObj->bAddToDeathRow == false && pObj->bActive && pObj->pFunction && pScript->dwPaused != 2 )
				{
					++Number;
					GrowObjectArray(Number, &pStart);
					*pStart++ = pObj;
				}
				pObj = pObj->pNext;
			}
		}
		pScript = pScriptNext;
	}

	//
	// make sure there is enough room in ObjectArray for NULL terminator
	//
	GrowObjectArray(Number+1);

	//
	// Sort the array by priority in draw order (lowest first)
	//
	qsort( pObjectArray, Number, sizeof(OBJECT *), CompareObjectsDrawOrder );

	//
	// add NULL terminator to ObjectArray (drawlist)
	//
	*(pObjectArray + Number) = NULL;

	ButtonDebounce[0] = Button[0];
	ButtonDebounce[1] = Button[1];
	ButtonDebounce[2] = Button[2];


	gScriptLastTime = the_time;
//
// Trap errors that occur in gosScript callbacks
//
	PopInScripts();

	return;
}

//----------------------------------------------------------------------------
// Called every game loop to update (execute or draw) all the running scripts
//
// Priority
//
// 0xFFFF	Script execute (all scripts and objects from 0x3FFF to 0x0000)
// 0x0000	Script draw before Game draw (drawing a background to a game)
// 0x1000	Script draw after Game display updated (before movies) 
// 0x2000	Modal Scripts
// 0x4000   Mouse & topmost
//----------------------------------------------------------------------------
void __stdcall ScriptsUpdate( int Priority )	//Draw
{
//
// Priority 0xffff - run all scripts
//
	if (Priority == 0xFFFF)
	{
		ScriptsExecute();	// >>> RunGameOSLogic() should call this directly when supported by gosEnvironment <<<
		gScriptPaneFlicker = !gScriptPaneFlicker;
		return;
	}

	if( gDisableScriptRender )
		return;

//
// Trap errors that occur in gosScript callbacks
//
	PushInScripts(1);


	gScript_InDraw = true;

	static OBJECT **pStart;

	if (Priority == 0x0000)
	{
		pStart = pObjectArray;
	}

	bool DoneViewPort=0;
	
	while (*pStart && (*(*pStart)->Priority & 0xF000) == Priority)
	{
		pScript=(*pStart)->pScript;
		if (pScript->dwPaused == 2 || !(*pStart)->bActive || !(*pStart)->pFunction) 
		{
			++pStart;
			continue;
		}

		if( !DoneViewPort )
		{
			DoneViewPort=1;
			if( 0==Environment.disableZBuffer && 0==Priority )
			{
				gos_SetupViewport( 1,1.0,0,0,0.0,0.0,1.0,1.0 );			// If rendering before the game renders, clear the z buffer
			}
			else
			{
				gos_SetupViewport( 0,1.0,0,0,0.0,0.0,1.0,1.0 );
			}
		}

		// clear the print3d margins between each draw
		gos_TextSetRegion(0, 0, Environment.screenWidth, Environment.screenHeight);
#ifdef LAB_ONLY
		double itrTimeIN = gos_GetHiResTime();
#endif
		SendScriptMessage( *pStart, MSG_GUI_DRAW );
#ifdef LAB_ONLY
		double itrTimeOUT = gos_GetHiResTime();
		(*pStart)->timeInDraw = itrTimeOUT-itrTimeIN;
#endif

#ifdef LAB_ONLY
		if (gEnableScriptMargins)
		{
			ScriptDrawLine(g_textMargins.p1.x, g_textMargins.p1.y, g_textMargins.p2.x, g_textMargins.p1.y, 0xff000000+gScriptColorCycle);
			ScriptDrawLine(g_textMargins.p2.x, g_textMargins.p1.y, g_textMargins.p2.x, g_textMargins.p2.y, 0xff000000+gScriptColorCycle);
			ScriptDrawLine(g_textMargins.p1.x, g_textMargins.p2.y, g_textMargins.p2.x, g_textMargins.p2.y, 0xff000000+gScriptColorCycle);
			ScriptDrawLine(g_textMargins.p1.x, g_textMargins.p1.y, g_textMargins.p1.x, g_textMargins.p2.y, 0xff000000+gScriptColorCycle);
		}


		if( gEnableScriptRegions )
		{
			if ((*pStart)->Cube->p1.x < (*pStart)->Cube->p2.x)
			{
				CUBE objRegion = 
				{
					(*pStart)->Cube->p1.x,
					(*pStart)->Cube->p1.y,
					0,
					(*pStart)->Cube->p2.x,
					(*pStart)->Cube->p2.y,
					0
				};

				OBJECT * ptr = *pStart;
				while (ptr)
				{
					objRegion.p1.x += ptr->Coordinates->x;
					objRegion.p1.y += ptr->Coordinates->y;
					objRegion.p2.x += ptr->Coordinates->x;
					objRegion.p2.y += ptr->Coordinates->y;
					if (*ptr->bPosRelative)
						ptr = ptr->pParentObject;
					else
						break;
				};

				int color = 0xff000000+(gScriptColorCycle & 0xffff00);
				signed long x1 = objRegion.p1.x;
				signed long y1 = objRegion.p1.y;
				signed long x2 = objRegion.p2.x;
				signed long y2 = objRegion.p2.y;

				// red for in-region
				if (((*pStart)->bMouseInRegion || *(*pStart)->AlwaysInRegion))
					color = 0xff000000 + (gScriptColorCycle & 0xff0000);
				ScriptDrawLine(x1,y1,x2,y1,color);
				ScriptDrawLine(x2,y1,x2,y2,color);
				ScriptDrawLine(x2,y2,x1,y2,color);
				ScriptDrawLine(x1,y2,x1,y1,color);
			}
		}
#endif
		++pStart;
	}

#ifdef LAB_ONLY
//
// Any lines left to draw?
//
	FlushLineBuffer();
//
// Color cycle debug regions
//
	gScriptColorCycle += 0x111111;
	if (gScriptColorCycle>0xffffff) gScriptColorCycle = 0xaaaaaa;

	// if debugging, draw mouse
	if( gEnableScriptRegions && DoneViewPort )
	{
		if( pInRegionTopmost ) {
			int nStage = 0;
			int nLastPos = 0;
			while(!DrawDebugging(pInRegionTopmost, nStage, nLastPos))
				nStage++;
		}

		DWORD width, height;
		gos_TextSetAttributes( gScriptFont3d, 0xff00ff00, 1, false, true, true, false );
		gos_TextSetPosition( ScriptMousePosition->x, ScriptMousePosition->y );
		gos_TextStringLength( &width, &height, "(%d, %d)", ScriptMousePosition->x, ScriptMousePosition->y );

		ShowSpewDrawBackground( ScriptMousePosition->x, ScriptMousePosition->y, ScriptMousePosition->x+width, ScriptMousePosition->y+ height, 0x7f000000 );
		gos_TextDraw( "(%d, %d)", ScriptMousePosition->x, ScriptMousePosition->y );
	}

	if ( gEnableScriptSpews && DoneViewPort)
		ShowScriptSpewOutput();

	if ( gEnableExpenseReport && DoneViewPort)
		ShowExpenseReport();
	if ( gEnableScriptsLoaded && DoneViewPort)
		ShowScriptsLoaded();
#endif

//
// Any lines left to draw?
//
	FlushLineBuffer();
//
// Set flag to signify we are done with all drawing
//
	gScript_InDraw = false;
//
// Trap errors that occur in gosScript callbacks
//
	PopInScripts();

//
// Do modal scripts after all other scripts
//
	if(Priority==0x1000)
	{
		if( ModalScripts )
			ScriptsUpdate(0x2000);
	}

//
// Update text cache
//
	EndofFrameTextCache();
	return;
}

//-----------------------------------------
// Compare two objects for ascending order
//-----------------------------------------
int __cdecl CompareObjectsDrawOrder( const void* arg1, const void *arg2 )
{
	OBJECT * obj1 = *(OBJECT**)arg1;
	OBJECT * obj2 = *(OBJECT**)arg2;

	if (*(obj1)->Priority == *(obj2)->Priority)
	{
		long value1B = 0;
		long value2B = 0;

		//
		// check relative positioning flag on offset z val
		//

		if (!((*obj1->bPosRelative) || (*obj1->bPosRelative)))
		{
			value1B = obj1->Coordinates->z;
			value2B = obj2->Coordinates->z;
		}
		else
		{
			OBJECT * ptr = obj1;
			while(ptr)
			{
				value1B += ptr->Coordinates->z;
				if (*ptr->bPosRelative)
					ptr = ptr->pParentObject;
				else
					break;
			}

			ptr = obj2;
			while(ptr)
			{
				value2B += ptr->Coordinates->z;
				if (*ptr->bPosRelative)
					ptr = ptr->pParentObject;
				else
					break;
			}
		}

		if (value1B == value2B)
		{
			int y1 = obj1->Coordinates->y ;
			int y2 = obj2->Coordinates->y ;
			if (y1 < y2)
				return -1;
			else
			if (y1 > y2)
				return 1;
			else
			{
				if (obj1->Coordinates->x == obj2->Coordinates->x)
					return 0;
				if (obj1->Coordinates->x < obj2->Coordinates->x)
					return -1;
				else
					return 1;
			}
		}
		return (value1B < value2B ? -1 : value1B > value2B ? 1 : 0);
	}
	else
	if (*(obj1)->Priority < *(obj2)->Priority)
		return -1;
	else
		return 1;
}

//------------------------------------------
// Compare two objects for descending order
//------------------------------------------
int __cdecl CompareObjectsExecuteOrder( const void* arg1, const void *arg2 )
{
	if (*((OBJECT*)(*(OBJECT**)arg1))->AlwaysInRegion)
		return -1;
	else
	if (*((OBJECT*)(*(OBJECT**)arg2))->AlwaysInRegion)
		return 1;
	return -CompareObjectsDrawOrder(arg1, arg2);
}


//
// Setup the preprocessor (To be called only at startup)
//
void InitScripts()
{
//
// Debugging information
//
//	SPEW(( GROUP_GAMEOS, "InitScripts()" ));
//
//
//
	gScriptHeap[5] = gos_CreateMemoryHeap("gosScript", 0, NULL);
	gScriptHeap[0] = gos_CreateMemoryHeap("Parser", 0, gScriptHeap[5]);
	gScriptHeap[1] = gos_CreateMemoryHeap("Panes", 0, gScriptHeap[5]);
	gScriptHeap[2] = gos_CreateMemoryHeap("Surfaces", 0, gScriptHeap[5]);
	gScriptHeap[3] = gos_CreateMemoryHeap("Variables", 0, gScriptHeap[5]);
	gScriptHeap[4] = gos_CreateMemoryHeap("GAFs", 0, gScriptHeap[5]);
	gos_PushCurrentHeap(gScriptHeap[0]);
	InitScriptGlobals();
	InitFastString();
	gos_PopCurrentHeap();
}


//
// Destroy the preprocessor (To be called only on exit)
//
void DestroyScripts()
{
//
// Debugging information
//
//	SPEW(( GROUP_GAMEOS, "DestroyScripts()" ));
//
//
//
	CleanUpScripts();
	DeleteFastStrings();

	gos_DestroyMemoryHeap(gScriptHeap[4]);
	gos_DestroyMemoryHeap(gScriptHeap[3]);
	gos_DestroyMemoryHeap(gScriptHeap[2]);
	gos_DestroyMemoryHeap(gScriptHeap[1]);
	gos_DestroyMemoryHeap(gScriptHeap[0]);
	gos_DestroyMemoryHeap(gScriptHeap[5]);

	gScriptHeap[0] = gScriptHeap[1] = gScriptHeap[2] = gScriptHeap[3] = gScriptHeap[4] = gScriptHeap[5] = 0;


}


int DrawDebugging(OBJECT * obj, int nStage, int& nLastPos)
{
	int bRet = TRUE;

	int line;
	DWORD height, width;

  if (nStage == 0) {
	line = 16;
	gos_TextSetRegion(0, 0, Environment.screenWidth, Environment.screenHeight);
	gos_TextSetAttributes( gScriptFont3d, 0xff00ff00, 1, false, true, true, false );
	gos_TextSetPosition( 16, line);
	if (obj->pParentVariable && obj->pParentVariable->ArraySize)
	{
		int num; 
		for(num = 0; num < obj->pParentVariable->ArraySize; num++) 
		{
			if (obj == (OBJECT *) obj->pParentVariable->pCubes[num])
				break;
		}

		gos_TextStringLength( &width, &height, "OBJECT %s[%d] running %s (%s), child of %s", obj->Name, num, obj->pFunction->Name, obj == pFocusedObject ? "HAS FOCUS" : "NOT FOCUSED", obj->pParentObject ? obj->pParentObject->Name : "None"  );
		ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
		gos_TextDraw( "OBJECT %s[%d] running %s (%s), child of %s", obj->Name, num, obj->pFunction->Name, obj == pFocusedObject ? "HAS FOCUS" : "NOT FOCUSED", obj->pParentObject ? obj->pParentObject->Name : "None");
	}
	else
	{
		gos_TextStringLength( &width, &height, "OBJECT %s running %s (%s), child of %s", 
			obj->Name, obj->pFunction->Name, 
			obj == pFocusedObject ? "HAS FOCUS" : "NOT FOCUSED", 
			obj->pParentObject ? obj->pParentObject->Name : "None");
		ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
		gos_TextDraw( "OBJECT %s running %s (%s), child of %s", obj->Name, obj->pFunction->Name, obj == pFocusedObject ? "HAS FOCUS" : "NOT FOCUSED",obj->pParentObject ? obj->pParentObject->Name : "None");
	}

	line += height;
#ifdef LAB_ONLY
	gos_TextSetAttributes( gScriptFont3d, 0xffff0000, 1, false, true, true, false );
	gos_TextStringLength( &width, &height, "Execute Time: %.2f ms", obj->timeInExecute*1000.0 );
	ShowSpewDrawBackground( 16, Environment.screenHeight-32, width+16, Environment.screenHeight-32+height, 0x7f000000 );
	gos_TextSetPosition( 16, Environment.screenHeight-32);
	gos_TextDraw("Execute Time: %.2f ms", obj->timeInExecute*1000.0 );
	gos_TextStringLength( &width, &height, "Draw Time: %.2f ms", obj->timeInDraw*1000.0 );
	ShowSpewDrawBackground( Environment.screenWidth-144, Environment.screenHeight-32, Environment.screenWidth-144+width, Environment.screenHeight-32+height, 0x7f000000 );
	gos_TextSetPosition( Environment.screenWidth-144, Environment.screenHeight-32);
	gos_TextDraw("Draw Time: %.2f ms", obj->timeInDraw *1000.0);
#endif
  } else {
	line = nLastPos;
  }
	// give some basic member variable readouts
	gos_TextSetAttributes( gScriptFont3d, 0xff00ff00, 1, false, false/*true*/, false, false );
	VARIABLE* tmp;
	
	static VARIABLE* s_pa[1024]; // ^^
	int nVarCount = 0;

struct SLocal
{
	static int __cdecl var_compare(const void *elem1, const void *elem2)
	{
		VARIABLE* v1 = *(VARIABLE**)elem1;
		VARIABLE* v2 = *(VARIABLE**)elem2;
		return strcmpi(v1->Name, v2->Name);
	}
};
	tmp = obj->pVariables;
	while(tmp)
	{
		s_pa[nVarCount++] = tmp;
		tmp = tmp->pNext;
	}
	qsort(&s_pa[0], nVarCount, sizeof(s_pa[0]), SLocal::var_compare);

	for(int iii = 0; iii < nVarCount; iii++)
	{
		tmp = s_pa[iii];
		gos_TextSetPosition( 16, line);

		int nTargetStage = +1;
		switch(tmp->Type)
		{
		case VAR_INT:
			nTargetStage = 0;
			break;
		case VAR_FLOAT:
			nTargetStage = 2;
			break;
		case VAR_STRING: 
			nTargetStage = 1;
			break;
		case VAR_POSITION: 
		case VAR_BITMAP:
		case VAR_OBJECT: 
		case VAR_FONT:
		case VAR_SOUND: 
		case VAR_CUBE:
		case VAR_MOVIE: 
		case VAR_GAF:
		case VAR_PANE: 
		case VAR_FONT3D:
		default:
			nTargetStage = -1;
			break;
		}
		if (nTargetStage < 0) {
			// no display
			continue;
		}
		if (nStage != nTargetStage) {
			if (nStage < nTargetStage) {
				// display in next stage....
				bRet = FALSE;
			} else {
				// should be already displayed...
			}
			continue;
		}
		switch(tmp->Type)
		{
		case VAR_INT:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						gos_TextSetPosition( 16, line);
						gos_TextStringLength( &width, &height, "INT %s[%d] = %d", tmp->Name, i, tmp->pValues[i] );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "INT %s[%d] = %d", tmp->Name, i, tmp->pValues[i] );
						line += height;
					}
				}
				else
				{
					gos_TextStringLength( &width, &height, "INT %s = %d", tmp->Name, tmp->Value  );
					ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
					gos_TextDraw( "INT %16s = %08x(=%d)", tmp->Name, tmp->Value, tmp->Value );
					line += height;
				}
			}
			break;
		case VAR_FLOAT:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						gos_TextSetPosition( 16, line);
						gos_TextStringLength( &width, &height, "FLOAT %s[%d] = %.2f", tmp->Name, i, tmp->pfValues[i] );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "FLOAT %s[%d] = %.2f", tmp->Name, i, tmp->pfValues[i] );
						line += height;
					}
				}
				else
				{
					gos_TextStringLength( &width, &height, "FLOAT %s = %.2f", tmp->Name, tmp->fValue  );
					ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
					gos_TextDraw( "FLOAT %s = %.2f", tmp->Name, tmp->fValue );
					line += height;
				}
			}
			break;
		case VAR_STRING: 
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						gos_TextSetPosition( 16, line);
						if (tmp->pValues[i])
						{
							gos_TextStringLength( &width, &height, "STRING %s[%d] = \"%s\"", tmp->Name, i, tmp->pValues[i] );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "STRING %s[%d] = \"%s\"", tmp->Name, i, tmp->pValues[i] );
						}
						else
						{
							gos_TextStringLength( &width, &height, "STRING %s[%d] = undefined", tmp->Name, i );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "STRING %s[%d] = undefined", tmp->Name, i ); 
						}
						line += height;
					}
				}
				else
				{
					if (tmp->pString)
					{
						gos_TextStringLength( &width, &height, "STRING %s = \"%s\"", tmp->Name, tmp->pString );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "STRING %s = \"%s\"", tmp->Name, tmp->pString );
					}
					else
					{
						gos_TextStringLength( &width, &height, "STRING %s = undefined", tmp->Name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "STRING %s = undefined", tmp->Name ); 
					}
					line += height;
				}
			}
			break;
		case VAR_POSITION: 
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						gos_TextSetPosition( 16, line);
						if (tmp->pPositions[i])
						{
							gos_TextStringLength( &width, &height, "POSITION %s[%d] = ( %d, %d, %d )", tmp->Name, i, tmp->pPositions[i]->x, tmp->pPositions[i]->y, tmp->pPositions[i]->z );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "POSITION %s[%d] = ( %d, %d, %d )", tmp->Name, i, tmp->pPositions[i]->x, tmp->pPositions[i]->y, tmp->pPositions[i]->z );
						}
						else
						{
							gos_TextStringLength( &width, &height, "POSITION %s[%d] = undefined", tmp->Name, i );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "POSITION %s[%d] = undefined", tmp->Name, i ); 
						}
						line += height;
					}
				}
				else
				{
					if (tmp->pPosition)
					{
						gos_TextStringLength( &width, &height, "POSITION %s = ( %d, %d, %d )", tmp->Name, tmp->pPosition->x, tmp->pPosition->y, tmp->pPosition->z );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "POSITION %s = ( %d, %d, %d )", tmp->Name, tmp->pPosition->x, tmp->pPosition->y, tmp->pPosition->z );
					}
					else
					{
						gos_TextStringLength( &width, &height, "POSITION %s = undefined", tmp->Name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "POSITION %s = undefined", tmp->Name ); 
					}
					line += height;
				}
			}
			break;
		case VAR_BITMAP:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						gos_TextSetPosition( 16, line);
						if (tmp->pSurfaces[i])
						{
							char * name = NULL;
							name = tmp->pSurfaces[i]->m_lpPath;
							gos_TextStringLength( &width, &height, "BITMAP %s[%d] = \"%s\", size(%d x %d)", 
								tmp->Name, i, name, tmp->pSurfaces[i]->m_nativeFormat.m_width, tmp->pSurfaces[i]->m_nativeFormat.m_height );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "BITMAP %s[%d] = \"%s\", size(%d x %d)", 
								tmp->Name, i, name, tmp->pSurfaces[i]->m_nativeFormat.m_width, tmp->pSurfaces[i]->m_nativeFormat.m_height );
							line += height;
						}
						else
						{
							gos_TextStringLength( &width, &height, "BITMAP %s[%d] = undefined", tmp->Name, i );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "BITMAP %s[%d] = undefined", tmp->Name, i ); 
							line += height;
						}
					}
				}
				else
				{
					if (tmp->Surface)
					{
   						gos_TextSetPosition( 16, line);
						char * name = NULL;
						name = tmp->Surface->m_lpPath;
						gos_TextStringLength( &width, &height, "BITMAP %s = \"%s\", size(%d x %d)", 
							tmp->Name, name, tmp->Surface->m_nativeFormat.m_width, tmp->Surface->m_nativeFormat.m_height );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "BITMAP %s = \"%s\", size(%d x %d)", 
							tmp->Name, name, tmp->Surface->m_nativeFormat.m_width, tmp->Surface->m_nativeFormat.m_height );
					}
					else
					{
						gos_TextStringLength( &width, &height, "BITMAP %s = undefined", tmp->Name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "BITMAP %s = undefined", tmp->Name ); 
					}
					line += height;
				}
			}
			break;
		case VAR_OBJECT: 
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
   						gos_TextSetPosition( 16, line);
						if (tmp->pValues[i])
						{
							OBJECT * o = (OBJECT *) tmp->pValues[i];
							gos_TextStringLength( &width, &height, "OBJECT %s[%d] = running %s, framerate %d, region (%d, %d to %d, %d), position (%d, %d, %d)", 
								o->Name, i, o->pFunction ? o->pFunction->Name: "(none)", *o->FrameRate, 
								o->Cube->p1.x, o->Cube->p1.y, o->Cube->p2.x, o->Cube->p2.y, 
								o->Coordinates->x, o->Coordinates->y, o->Coordinates->z );
	
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "OBJECT %s[%d] = running %s, framerate %d, region (%d, %d to %d, %d), position (%d, %d, %d)", 
								o->Name, i, o->pFunction ? o->pFunction->Name: "(none)", *o->FrameRate,
								o->Cube->p1.x, o->Cube->p1.y, o->Cube->p2.x, o->Cube->p2.y, 
								o->Coordinates->x, o->Coordinates->y, o->Coordinates->z );
						}
						else
						{
							gos_TextStringLength( &width, &height, "OBJECT %s[%d] = undefined", tmp->Name, i );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "OBJECT %s[%d] = undefined", tmp->Name, i ); 
						}
						line += height;
					}
				}
				else
				{
					if (tmp->Value)
					{
						OBJECT * o = (OBJECT *) tmp->Value;
   						gos_TextSetPosition( 16, line);
						gos_TextStringLength( &width, &height, "OBJECT %s = running %s, framerate %d, region (%d, %d to %d, %d), position (%d, %d, %d)", 
							o->Name, o->pFunction ? o->pFunction->Name: "(none)", *o->FrameRate, 
							o->Cube->p1.x, o->Cube->p1.y, o->Cube->p2.x, o->Cube->p2.y, 
							o->Coordinates->x, o->Coordinates->y, o->Coordinates->z );

						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "OBJECT %s = running %s, framerate %d, region (%d, %d to %d, %d), position (%d, %d, %d)", 
							o->Name, o->pFunction ? o->pFunction->Name: "(none)", *o->FrameRate, 	
							o->Cube->p1.x, o->Cube->p1.y, o->Cube->p2.x, o->Cube->p2.y, 
							o->Coordinates->x, o->Coordinates->y, o->Coordinates->z );
					}
					else
					{
						gos_TextStringLength( &width, &height, "OBJECT %s = undefined", tmp->Name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "OBJECT %s = undefined", tmp->Name ); 
					}
					line += height;
				}
			}
			break;
		case VAR_FONT:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						gos_TextSetPosition( 16, line);
						if (tmp->pValues[i])
						{
							char * name = NULL;
							name = ((Surface *) tmp->pValues[i])->m_lpPath;
							gos_TextStringLength( &width, &height, "FONT %s[%d] = \"%s\"", 
								tmp->Name, i, name );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "FONT %s[%d] = \"%s\"", tmp->Name, i, name );

						}
						else
						{
							gos_TextStringLength( &width, &height, "FONT %s[%d] = undefined", tmp->Name, i );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "FONT %s[%d] = undefined", tmp->Name, i ); 
						}
						line += height;
					}
				}
				else
				{
					if (tmp->Value)
					{
						gos_TextSetPosition( 16, line);
						char * name = NULL;
						name = ((Surface *) tmp->Value)->m_lpPath;
						gos_TextStringLength( &width, &height, "FONT %s = \"%s\"", 
							tmp->Name, name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "FONT %s = \"%s\"", tmp->Name, name );
					}
					else
					{
						gos_TextStringLength( &width, &height, "FONT %s = undefined", tmp->Name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "FONT %s = undefined", tmp->Name ); 
					}
					line += height;
				}
			}
			break;
		case VAR_SOUND: 
 			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						gos_TextSetPosition( 16, line);
						if (tmp->pSounds[i])
						{
							gosAudio_ResourceInfo ga_ri;
							gosAudio_GetResourceInfo(tmp->pSounds[i], &ga_ri);
							gos_TextStringLength( &width, &height, "SOUND %s[%d] = \"%s\"", tmp->Name, i, ga_ri.lpstrPath );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "SOUND %s[%d] = \"%s\"", tmp->Name, i, ga_ri.lpstrPath );
							line += height;
						}
						else
						{
							gos_TextStringLength( &width, &height, "SOUND %s[%d] = undefined", tmp->Name, i );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "SOUND %s[%d] = undefined", tmp->Name, i );
							line += height;
						}
					}
				}
				else
				{
					if (tmp->Sound)
					{
						gosAudio_ResourceInfo ga_ri;
						gosAudio_GetResourceInfo(tmp->Sound, &ga_ri);
						gos_TextStringLength( &width, &height, "SOUND %s = \"%s\"", tmp->Name, ga_ri.lpstrPath );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "SOUND %s = \"%s\"", tmp->Name,  ga_ri.lpstrPath );
					}
					else
					{
						gos_TextStringLength( &width, &height, "SOUND %s = undefined", tmp->Name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "SOUND %s = undefined", tmp->Name );
					}
					line += height;
				}
			}
			break;
		case VAR_CUBE:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						gos_TextSetPosition( 16, line);
						if (tmp->pCubes[i])
						{
							gos_TextStringLength( &width, &height, "CUBE %s[%d] = ( %d, %d to %d, %d )", tmp->Name, i, tmp->pCubes[i]->p1.x, tmp->pCubes[i]->p1.y, tmp->pCubes[i]->p2.x, tmp->pCubes[i]->p2.y );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "CUBE %s[%d] = ( %d, %d to %d, %d )", tmp->Name, i, tmp->pCubes[i]->p1.x, tmp->pCubes[i]->p1.y, tmp->pCubes[i]->p2.x, tmp->pCubes[i]->p2.y );
						}
						else
						{
							gos_TextStringLength( &width, &height, "SOUND %s[%d] = undefined", tmp->Name, i );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "SOUND %s[%d] = undefined", tmp->Name, i );
						}
						line += height;
					}
				}
				else
				{
					if (tmp->pCube)
					{
						gos_TextStringLength( &width, &height, "CUBE %s = ( %d, %d to %d, %d )", tmp->Name, tmp->pCube->p1.x, tmp->pCube->p1.y, tmp->pCube->p2.x, tmp->pCube->p2.y );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "CUBE %s = ( %d, %d to %d, %d )", tmp->Name, tmp->pCube->p1.x, tmp->pCube->p1.y, tmp->pCube->p2.x, tmp->pCube->p2.y );
					}
					else
					{
						gos_TextStringLength( &width, &height, "CUBE %s = undefined", tmp->Name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "CUBE %s = undefined", tmp->Name );
					}
					line += height;
				}
			}
			break;
		case VAR_MOVIE: 
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						gos_TextSetPosition( 16, line);
						if (tmp->pVideos[i])
						{
							gosVideo_ResourceInfo gv_ri;
							gosVideo_GetResourceInfo(tmp->pVideos[i], &gv_ri);
							gos_TextStringLength( &width, &height, "MOVIE %s[%d] = \"%s\"", tmp->Name, i, gv_ri.lpstrPath  );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "MOVIE %s[%d] = \"%s\"", 
								tmp->Name, i, gv_ri.lpstrPath  );
						}
						else
						{
							gos_TextStringLength( &width, &height, "MOVIE %s[%d] = undefined", tmp->Name, i );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "MOVIE %s[%d] = undefined", tmp->Name, i ); 
						}
						line += height;
					}
				}
				else
				{
					if (tmp->Video)
					{
   						gos_TextSetPosition( 16, line);
						gosVideo_ResourceInfo gv_ri;
						gosVideo_GetResourceInfo(tmp->Video, &gv_ri);
						gos_TextStringLength( &width, &height, "MOVIE %s = \"%s\"", 
							tmp->Name, gv_ri.lpstrPath );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "MOVIE %s = \"%s\"", 
							tmp->Name, tmp->Name, gv_ri.lpstrPath   );
					}
					else
					{
						gos_TextStringLength( &width, &height, "MOVIE %s = undefined", tmp->Name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "MOVIE %s = undefined", tmp->Name ); 
					}
					line += height;
				}
			}
			break;
		case VAR_GAF:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						gos_TextSetPosition( 16, line);
						if (tmp->pGAFs[i])
						{
							gos_TextStringLength( &width, &height, "GAF %s[%d] = \"%s\", size(%d, %d), frame %d of %d", 
								tmp->Name, i, tmp->pGAFs[i]->m_primarySurface->m_lpPath, 
								tmp->pGAFs[i]->m_gafHeader->m_width, tmp->pGAFs[i]->m_gafHeader->m_height, tmp->pGAFs[i]->m_lastFrame, tmp->pGAFs[i]->m_gafHeader->m_totalImages );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "GAF %s[%d] = \"%s\", size(%d, %d), frame %d of %d", 
								tmp->Name, i, tmp->pGAFs[i]->m_primarySurface->m_lpPath, 
								tmp->pGAFs[i]->m_gafHeader->m_width, tmp->pGAFs[i]->m_gafHeader->m_height, tmp->pGAFs[i]->m_lastFrame, tmp->pGAFs[i]->m_gafHeader->m_totalImages );
						}
						else
						{
							gos_TextStringLength( &width, &height, "GAF %s[%d] = undefined", tmp->Name, i );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "GAF %s[%d] = undefined", tmp->Name, i ); 
						}
						line += height;
					}
				}
				else
				{
					if (tmp->Gaf)
					{
   						gos_TextSetPosition( 16, line);
						gos_TextStringLength( &width, &height, "GAF %s = \"%s\", size(%d, %d), frame %d of %d", 
								tmp->Name, tmp->Gaf->m_primarySurface->m_lpPath, 
								tmp->Gaf->m_gafHeader->m_width, tmp->Gaf->m_gafHeader->m_height, tmp->Gaf->m_lastFrame, tmp->Gaf->m_gafHeader->m_totalImages );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "GAF %s = \"%s\", size(%d, %d), frame %d of %d", 
								tmp->Name, tmp->Gaf->m_primarySurface->m_lpPath, 
								tmp->Gaf->m_gafHeader->m_width, tmp->Gaf->m_gafHeader->m_height, tmp->Gaf->m_lastFrame, tmp->Gaf->m_gafHeader->m_totalImages );
					}
					else
					{
						gos_TextStringLength( &width, &height, "GAF %s = undefined", tmp->Name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "GAF %s = undefined", tmp->Name ); 
					}
					line += height;
				}
			}
			break;
		case VAR_PANE: 
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						gos_TextSetPosition( 16, line);
						if (tmp->pPanes[i])
						{
							char * name = NULL;
							name = tmp->pPanes[i]->GetSurfacePath();
							gos_TextStringLength( &width, &height, "PANE %s[%d] = \"%s\", size(%d x %d), origin(%d, %d), rot( %d, %d, %d), scale(%d, %d)", 
								tmp->Name, i, name,
								tmp->pPanes[i]->m_pTextureList->m_width, tmp->pPanes[i]->m_pTextureList->m_height, 
								(int) (tmp->pPanes[i]->currentOffset.x), (int) (tmp->pPanes[i]->currentOffset.y), 
								(tmp->pPanes[i]->currentRotation.x*360.0f) / 6.28f, (tmp->pPanes[i]->currentRotation.y*360.0f) / 6.28f, (tmp->pPanes[i]->currentRotation.z*360.0f) / 6.28f,
								(int)tmp->pPanes[i]->currentScaleX, (int)tmp->pPanes[i]->currentScaleY);
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "PANE %s[%d] = \"%s\", size(%d x %d), origin(%d, %d), rot( %d, %d, %d), scale(%d, %d)", 
								tmp->Name, i, name,
								tmp->pPanes[i]->m_pTextureList->m_width, tmp->pPanes[i]->m_pTextureList->m_height, 
								(int) tmp->pPanes[i]->currentOffset.x, (int) tmp->pPanes[i]->currentOffset.y, 
								(tmp->pPanes[i]->currentRotation.x*360.0f) / 6.28f, (tmp->pPanes[i]->currentRotation.y*360.0f) / 6.28f, (tmp->pPanes[i]->currentRotation.z*360.0f) / 6.28f,
								(int)tmp->pPanes[i]->currentScaleX, (int)tmp->pPanes[i]->currentScaleY);
						}
						else
						{
							gos_TextStringLength( &width, &height, "PANE %s[%d] = undefined", tmp->Name, i );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "PANE %s[%d] = undefined", tmp->Name, i ); 
						}
						line += height;
					}
				}
				else
				{
					if (tmp->Pane)
					{
						gos_TextSetPosition( 16, line);
						char * name = NULL;
						name = tmp->Pane->GetSurfacePath();
						gos_TextStringLength( &width, &height, "PANE %s = \"%s\", size(%d x %d), origin(%d, %d), rot( %d, %d, %d), scale(%d, %d)", 
							tmp->Name, name,
							tmp->Pane->m_pTextureList->m_width, tmp->Pane->m_pTextureList->m_height, 
							(int) tmp->Pane->currentOffset.x, (int) tmp->Pane->currentOffset.y, 
							(tmp->Pane->currentRotation.x*360.0f) / 6.28f, (tmp->Pane->currentRotation.y*360.0f) / 6.28f, (tmp->Pane->currentRotation.z*360.0f) / 6.28f,
							(int)tmp->Pane->currentScaleX, (int)tmp->Pane->currentScaleY);
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "PANE %s = \"%s\", size(%d x %d), origin(%d, %d), rot( %d, %d, %d), scale(%d, %d)", 
							tmp->Name, name,
							tmp->Pane->m_pTextureList->m_width, tmp->Pane->m_pTextureList->m_height, 
							(int) tmp->Pane->currentOffset.x, (int) tmp->Pane->currentOffset.y, 
							(tmp->Pane->currentRotation.z*360.0f) / 6.28f, (tmp->Pane->currentRotation.y*360.0f) / 6.28f, (tmp->Pane->currentRotation.z*360.0f) / 6.28f,
							(int)tmp->Pane->currentScaleX, (int)tmp->Pane->currentScaleY);
					}
					else
					{
						gos_TextStringLength( &width, &height, "PANE %s = undefined", tmp->Name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "PANE %s = undefined", tmp->Name ); 
					}
					line += height;
				}
			}
			break;
		case VAR_FONT3D:
			{
				if (tmp->ArraySize)
				{
					for(int i=0; i < tmp->ArraySize; i++)
					{
						gos_TextSetPosition( 16, line);
						if (tmp->pSurfaces[i])
						{
							gos_TextStringLength( &width, &height, "FONT3D %s[%d] = (unknown)", tmp->Name, i );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "FONT3D %s[%d] = (unknown)", tmp->Name, i );
						}
						else
						{
							gos_TextStringLength( &width, &height, "FONT3D %s[%d] = undefined", tmp->Name, i );
							ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
							gos_TextDraw( "FONT3D %s[%d] = undefined", tmp->Name, i ); 
						}
						line += height;
					}
				}
				else
				{
					if (tmp->Surface)
					{
   						gos_TextSetPosition( 16, line);
						gos_TextStringLength( &width, &height, "FONT3D %s = (unknown)", tmp->Name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "FONT3D %s = (unknown)", tmp->Name );
					}
					else
					{
						gos_TextStringLength( &width, &height, "FONT3D %s = undefined", tmp->Name );
						ShowSpewDrawBackground( 16, line, width+16, line+height, 0x7f000000 );
						gos_TextDraw( "FONT3D %s = undefined", tmp->Name ); 
					}
					line += height;
				}
			}
			break;
		}
		tmp = tmp->pNext;
	}
	nLastPos = line;

	return bRet;
}

void ScriptSpewOutput(char* spew)
{
	#ifdef _DEBUG
	memcpy(gScriptSpewLog[0], gScriptSpewLog[1], SPEWLINE_LENGTH*32);
	strcpy(gScriptSpewLog[29], pObject->Name);
	if (pObject->pParentVariable)
	{
		if (pObject->pParentVariable->ArraySize)
		{
			char tmp[32];
			for(int i=0; i < pObject->pParentVariable->ArraySize; i++)
			{
				if (pObject->pParentVariable->pValues[i] == (int) pObject)
				{
					strcat(gScriptSpewLog[29], "[");
					strcat(gScriptSpewLog[29], itoa(i,tmp,10));
					strcat(gScriptSpewLog[29], "]");
				}
			}
		}
	}
	strcat(gScriptSpewLog[29],": ");
	strncat(gScriptSpewLog[29], spew, SPEWLINE_LENGTH - strlen(gScriptSpewLog[29] -2)) ;
	ScriptOutput(gScriptSpewLog[29]);
	strcat(gScriptSpewLog[29],"\n");
	#else
	spew=spew;
	#endif
}

void ShowSpewDrawBackground(DWORD x1, DWORD y1, DWORD x2, DWORD y2, DWORD color)
{
	gos_VERTEX verts[4];
	gos_SetRenderState(gos_State_Texture, 0);
	gos_SetRenderState(gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha);
	gos_SetRenderState( gos_State_Clipping, 2 );

	if (y1 >= (DWORD)Environment.screenHeight)
		return;
	
	if (y2 >= (DWORD)Environment.screenHeight)
		y2 = Environment.screenHeight-1;

	verts[0].x = (float) x1;
	verts[0].y = (float) y1;
	verts[0].z = 0.0;
	verts[0].rhw = 1.0;
	verts[0].argb =	color;
	verts[0].frgb = 0;
	verts[0].u = 0.0f;
	verts[0].v = 0.0f;

	verts[1].x = (float) x2;
	verts[1].y = (float) y1;
	verts[1].z = 0.0;
	verts[1].rhw = 1.0;
	verts[1].argb =	color;
	verts[1].frgb = 0;
	verts[1].u = 1.0f;
	verts[1].v = 0.0f;

	verts[2].x = (float) x2;
	verts[2].y = (float) y2;
	verts[2].z = 0.0;
	verts[2].rhw = 1.0;
	verts[2].argb =	color;
	verts[2].frgb = 0;
	verts[2].u = 1.0f;
	verts[2].v = 1.0f;

	verts[3].x = (float) x1;
	verts[3].y = (float) y2;
	verts[3].z = 0.0;
	verts[3].rhw = 1.0;
	verts[3].argb =	color;
	verts[3].frgb = 0;
	verts[3].u = 0.0f;
	verts[3].v = 1.0f;

	gos_DrawQuads( verts, 4);
}

void ShowScriptSpewOutput()
{
	#ifdef LAB_ONLY
	gos_SetupViewport( false, 1.0f, false, 0, 0.0f, 0.0f, 1.0f, 1.0f);
	gos_TextSetRegion(0, 0, Environment.screenWidth, Environment.screenHeight);
	gos_TextSetAttributes( gScriptFont3d, 0xff00ff00, 1, false, true, true, false );

	DWORD width, height;
	int scanline = 16;

	for(int i=0; i < 30 && scanline+16 < Environment.screenHeight; i++)
	{
		if (gScriptSpewLog[i][0])
		{
			gos_TextSetAttributes( gScriptFont3d, 0xff00ff00, 1, false, true, true, false );
			gos_TextStringLength( &width, &height, gScriptSpewLog[i] );
			gos_TextSetPosition( 16, scanline);
			ShowSpewDrawBackground( 16, scanline, width+16, scanline+height, 0x7f000000 );
			gos_TextDraw( gScriptSpewLog[i] ); 
			scanline += height;
		}
	}
	#endif
}


void _stdcall gosScript_Command(HGOSSCRIPT Handle, const char * name, gosScript_Cmd cmd, void * parameter)
{
	if (cmd == gosScript_Cmd_MAILBOX)
	{
		if (parameter == NULL)
			STOP(("gosScript_Cmd_MAILBOX requires a valid parameter pointer"));
	}
	if (cmd == gosScript_Cmd_ChangeValue)
	{
		PAUSE(("gosScript_Cmd_ChangeValue has not be implemented"));
		return;
	}
	//
	// Make sure that scripts are running.
	//
	SavePosition();
	if (!ScriptsRunning)
		STOP(( "gosScript has not been initialized" ));

	//
	// strlwr
	//
	char variableOrObjectName[128];
	strcpy(variableOrObjectName, name);
	strlwr((char *)variableOrObjectName);



	//
	// Check for valid script handle....
	//
	SCRIPT * tmp = pListofScripts;
	while (tmp)
	{
		if ((SCRIPT *) Handle == tmp)
		{
			break;
		}
		tmp = tmp->pNext;
	}
	if (!tmp)
		STOP(("Script handle is invalid"));

	//
	// handle was valid. crap. now the real work begins....
	// find the object or variable within the script...
	pScript = Handle;
	pObject = Handle->pMainObject;
	pLine = (char *) variableOrObjectName;
//
// DISABLE caching!
//
	KeywordCache[(int)pLine&(MAXCACHE-1)].Address=0;

	int val = GetKeyword();

	if (val != VAR_OBJECT)
	{
		if (cmd != gosScript_Cmd_ChangeValue)
		{
			PAUSE(("Client application attempted to send a message to a non-object in a script"));
		}
	}
	else
	{
		OBJECT * p = (OBJECT *) *pLastVariable;
		switch(cmd)
		{
		case MSG_GUI_ACTIVATE:
			p->bActive = true;
			SendScriptMessage( (OBJECT *) *pLastVariable, MSG_GUI_ACTIVATE );		// send GUI_CREATE to object
			break;

		case MSG_GUI_DEACTIVATE:
			p->bActive = false;
			SendScriptMessage( p, MSG_GUI_DEACTIVATE );		// send GUI_CREATE to object
			break;

		case MSG_GUI_UNFOCUS:
			if (pFocusedObject)
			{
				SendScriptMessage(pFocusedObject, MSG_GUI_UNFOCUS);
			}
			pFocusedObject = NULL;
			pFocusedScript = NULL;
			break;

		case MSG_GUI_FOCUS:
			// return if this object already HAS focus
			if ( pFocusedObject == p)
				break;

			// if another object has focus, notify it that it has lost focus
			if (pFocusedObject)
			{
				SendScriptMessage(pFocusedObject, MSG_GUI_UNFOCUS);
				pFocusedObject = NULL;
				pFocusedScript = NULL;
			}
			// finally, focus the object
			pFocusedObject = p;
			pFocusedScript = p->pScript;
			gos_KeyboardFlush();
			SendScriptMessage(pFocusedObject, MSG_GUI_FOCUS);
			break;
		case MSG_GUI_MAILBOX:
			{
				g_mailStack++;
				if (g_mailStack > MAX_MAILSTACK)
				{
					PAUSE(("gosScript_Command: Mail is nesting too deeply"));
					break;
				}
				int val = (int) *((int *)parameter);
				g_scriptPostedInteger[g_mailStack][0] = val;
				g_scriptMailPoster[g_mailStack] = (OBJECT *) -1;
				SendScriptMessage(p, MSG_GUI_MAILBOX );		
				g_mailStack--;
				gosASSERT(g_mailStack >= 0);
			}
			break;

		default: 
			SendScriptMessage( p, (MESSAGES) cmd );
			break;

		}
	}
	RestorePosition();
}

void GetJoystickInput()
{
	gosJoystick_SetPolling(ScriptPointerDevice,true);
	float valx = gosJoystick_GetAxis(ScriptPointerDevice,JOY_XAXIS);
	if (valx > .1f || valx < -.1f)
		ScriptMousePosition->x += float2long(valx*10.0f);
	float valy = gosJoystick_GetAxis(ScriptPointerDevice,JOY_YAXIS);
	if (valy > .1f || valy < -.1f)
		ScriptMousePosition->y += float2long(valy*10.0f);

	//
	// keep the joystick-controlled pointer in-bounds
	//
	if (ScriptMousePosition->x > Environment.screenWidth)
		ScriptMousePosition->x = Environment.screenWidth;
	else
	if (ScriptMousePosition->x < 0)
		ScriptMousePosition->x = 0;

	if (ScriptMousePosition->y > Environment.screenHeight)
		ScriptMousePosition->y = Environment.screenHeight;
	else
	if (ScriptMousePosition->y < 0)
		ScriptMousePosition->y = 0;

	bool b[5];
	gosJoystick_Info ji;
	gosJoystick_GetInfo(ScriptPointerDevice, &ji);
	for(unsigned int i=0; i < 5; i++)
	{
		if ( i < ji.nButtons )
			b[i] = gosJoystick_ButtonStatus(ScriptPointerDevice,i);
		else
			b[i] = 0;

		if (b[i])
		{
			switch (ButtonPrev[i])
			{
				case BUTTON_FREE:
					Button[i] = BUTTON_PRESSED;
					break;
				case BUTTON_PRESSED:
					Button[i] = BUTTON_HELD;
					break;
			}
		}
		else
		{
			switch (ButtonPrev[i])
			{
				case BUTTON_FREE:
				case BUTTON_RELEASED:
					Button[i] = BUTTON_FREE;
					break;
				case BUTTON_PRESSED:
				case BUTTON_HELD:
					Button[i] = BUTTON_RELEASED;
					break;
			}
		}
		ButtonPrev[i] = Button[i];
	}
}

#ifdef LAB_ONLY
void ShowExpenseReport()
{
	// draw the most expensive render/execute objects.
	DrawRect(16,16, Environment.screenWidth-16, Environment.screenHeight-16, 0x7f000000);
	ScriptDrawLine(16,16, Environment.screenWidth-16, 16, 0x7f00ff00);
	ScriptDrawLine(Environment.screenWidth-16,16, Environment.screenWidth-16 , Environment.screenHeight-16, 0x7f00ff00);
	ScriptDrawLine(16,Environment.screenHeight-16, Environment.screenWidth-16, Environment.screenHeight-16, 0x7f00ff00);
	ScriptDrawLine(16,16, 16, Environment.screenHeight-16, 0x7f00ff00);
	FlushLineBuffer();

	//---------------------------------------------
	// Order all Objects in reverse-draw-order 
	//	  for event processing and script execution
	//---------------------------------------------
	pScript = pListofScripts;
	pStart = pObjectArray;
	OBJECT *pObj = NULL;
	totalObjectNumber = 0;

	int Number = 0;

	while (pScript)
	{
		pObj = pScript->pListofObjects;
		while (pObj)
		{
			if(  pObj->bActive && pObj->pFunction && pScript->dwPaused != 2 )
			{
				if (ModalScripts && (*pObj->Priority)<0x2000)
				{
				}
				else
				{
					++Number;
				
					GrowObjectArray(Number, &pStart);
			
					*pStart++ = pObj;
				}
			}
			pObj = pObj->pNext;
		}
		pScript = pScript->pNext;
	}

	//
	// Sort the array by priority in execution order (highest first)
	//
	totalObjectNumber = Number;
	
	qsort( pObjectArray, totalObjectNumber, sizeof(OBJECT *), CompareObjectsExpense );

	OBJECT * itr = pObjectArray[0];
	DWORD line = 32;
	gos_TextSetRegion( 17,17, Environment.screenWidth-17, Environment.screenHeight-17);
	gos_TextSetPosition( 17, 17);
	gos_TextSetAttributes( gScriptFont3d, 0xffff0000, 1, false, true, true, false );
	gos_TextDraw("Execute (ms) / Draw (ms)   Object\n");
	DWORD h,w;
	gos_TextStringLength( &w, &h, "(Press <SPACEBAR> to freeze/unfreeze this report)" );
	gos_TextSetPosition( Environment.screenWidth/2 - w/2, Environment.screenHeight-32);
	gos_TextDraw("(Press <SPACEBAR> to freeze/unfreeze this report)\n");
	int i = 0;
	int max = (Environment.screenHeight - 64)/ 16;

	if (gFreezeExpenses)
	{
		for (i = 0; i < 32 && gScriptExpenseReport[i][0]; i++)
		{
			gos_TextSetAttributes( gScriptFont3d, 0xff00ff00, 1, false, true, true, false );
			gos_TextSetPosition( 17, line);
			gos_TextDraw(gScriptExpenseReport[i]);
			line += 16;
		}

		if (gos_GetKeyStatus(KEY_SPACE) == BUTTON_RELEASED)
			gFreezeExpenses = ! gFreezeExpenses;

	}
	else
	{
		if (gos_GetKeyStatus(KEY_SPACE) == BUTTON_RELEASED)
			gFreezeExpenses = ! gFreezeExpenses;

		while (i < max && i < totalObjectNumber)
		{
			if (itr)
			{
				gos_TextSetAttributes( gScriptFont3d, 0xff00ff00, 1, false, true, true, false );
				gos_TextSetPosition( 17, line);
				if (itr->pParentVariable && itr->pParentVariable->ArraySize)
				{
					int num; 
					for(num = 0; num < itr->pParentVariable->ArraySize; num++) 
					{
						if (itr == (OBJECT *) itr->pParentVariable->pCubes[num])
							break;
					}
		
					gos_TextDraw( "/proportional=0  %.2f      %.2f   /proportional=1%s[%d] running %s", itr->timeInExecute*1000.0f, itr->timeInDraw*1000.0f, itr->Name, num, itr->pFunction ? itr->pFunction->Name : "Nothing");
					if (gFreezeExpenses && i < 32)
						sprintf(gScriptExpenseReport[i], "/proportional=0  %.2f      %.2f   /proportional=1%s[%d] running %s", itr->timeInExecute*1000.0f, itr->timeInDraw*1000.0f, itr->Name, num, itr->pFunction ? itr->pFunction->Name : "Nothing");
				}
				else
				{
					gos_TextDraw( "/proportional=0  %.2f      %.2f   /proportional=1%s running %s", itr->timeInExecute*1000.0f, itr->timeInDraw*1000.0f, itr->Name, itr->pFunction ? itr->pFunction->Name : "Nothing" );
					if (gFreezeExpenses && i < 32)
						sprintf(gScriptExpenseReport[i], "/proportional=0  %.2f      %.2f   /proportional=1%s running %s", itr->timeInExecute*1000.0f, itr->timeInDraw*1000.0f, itr->Name, itr->pFunction ? itr->pFunction->Name : "Nothing" );
				}
				line += 16;
			}
			i++;
			itr = pObjectArray[i];
		}
		if (gFreezeExpenses && i < 32)
			gScriptExpenseReport[i][0] = 0;
	}

}

int __cdecl CompareObjectsExpense( const void* arg1, const void *arg2 )
{
	OBJECT * o1 = *((OBJECT **) arg1);
	OBJECT * o2 = *((OBJECT **) arg2);

	if (!o1)
		return 1;
	if (!o2)
		return -1;
	if (o1->timeInExecute + 
		o1->timeInDraw >=

		o2->timeInExecute + 
		o2->timeInDraw)
		return -1;
	else
		return 1;
}

void ShowScriptsLoaded()
{
	DrawRect(16,16, Environment.screenWidth-16, Environment.screenHeight-16, 0x7f000000);
	ScriptDrawLine(16,16, Environment.screenWidth-16, 16, 0x7f00ff00);
	ScriptDrawLine(Environment.screenWidth-16,16, Environment.screenWidth-16 , Environment.screenHeight-16, 0x7f00ff00);
	ScriptDrawLine(16,Environment.screenHeight-16, Environment.screenWidth-16, Environment.screenHeight-16, 0x7f00ff00);
	ScriptDrawLine(16,16, 16, Environment.screenHeight-16, 0x7f00ff00);
	FlushLineBuffer();


	pScript = pListofScripts;
	totalObjectNumber = 0;

	int Number = 0;

	while (pScript)
	{

		gos_TextSetPosition( 17, 17 + 12*Number);
		gos_TextSetAttributes( gScriptFont3d, 0xffff0000, 1, false, true, true, false );
		gos_TextDraw(pScript->pFileNames->LongFileName);
	   	pScript = pScript->pNext;
		Number++;
	}
}

#endif