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






//
// JIM - 
//
//
// Currently there is no check for variables being redefined of a different type. I think this is dangerous.
//
// OBJECT fred;
// FONT   fred;   is currently legal!
//
//
// 'Script Constants' true, false etc... cannot ever be -1 - that would be 'not found' from GetKeyword
//
//
//



extern DWORD FindKeyWord();
extern bool gIsDeclaration;

extern int g_scriptLineColor;
extern CUBE g_textMargins;
extern gosEnum_TextWrap g_textWrapMode;

extern bool ScriptsRunning;
extern REGVAR* pScriptRegisteredVariables;
extern OBJECT* pFocusedObject;
extern SCRIPT* pFocusedScript;

extern CUBE g_textMargins;

extern VARIABLE* pLastVariableObject;
extern int pLastVariableObjectIndex;
extern bool gScript_InDraw;
extern bool	bIgnoreMouseMessages;

extern DWORD g_mailStack;
extern int g_scriptPostedInteger[][8];
extern OBJECT * g_scriptMailPoster[];

extern DWORD gosScript_localizationFile;

extern HGOSHEAP gScriptHeap[];
extern HGOSHEAP DefaultHeap;
extern bool theIMEstate;
extern DWORD gFloatPrecision;


void __stdcall gosScript_RegisterVariable( const char* Name, void* address, gosEnum_VarType vt, int arraysize, void * instance)
{
	#ifdef _DEBUG
		gosASSERT( Name && (strlen(Name)+4)<256 );
		if( !ScriptsRunning )
			STOP(( "Attempting to register a gosScript variable without gosScript processor initialized" ));
		if( !address)
			STOP(( "Attempt to register a NULL address" ));
		if( arraysize>65535 )
			STOP(( "Array size too large %d",arraysize ));
	#endif

	REGVAR * rv = (REGVAR *) gos_Malloc(sizeof(REGVAR)+strlen(Name)+4, gScriptHeap[3]);

	//-------------------------------
	// store new registered variable
	//-------------------------------
	strcpy(rv->Name, "$$");
	strcat(rv->Name, Name);
	strcat(rv->Name, "$$");
	rv->Value = (int )address;
	rv->Type = (BYTE)(vt + KEY_TYPE);
	rv->ArraySize = (WORD)arraysize;
	rv->NameLength = (BYTE)(strlen(Name)+4);
	rv->Instance = (int) instance;

	char* pName=rv->Name;
	while( *pName )
	{
		if( *pName>='A' && *pName<=(char)'Z' )
			*pName+=32;
		pName++;
	}

	//-------------------------------
	// insert at head of linked list
	//-------------------------------
	rv->pNext = pScriptRegisteredVariables;	//(if pScriptRegisteredVariables is NULL it is passed to pNext)
	pScriptRegisteredVariables = rv;
}


void __stdcall gosScript_RegisterCallback( const char* Name, GOSSCRIPTCALLBACK address, gosEnum_VarType vt, int arraysize, void* instance )
{
	#ifdef _DEBUG
		gosASSERT( Name && (strlen(Name)+4)<256 );
		if (!ScriptsRunning)
			STOP(("Attempting to register a gosScript callback without gosScript processor initialized"));
		if( arraysize>65535 )
			STOP(( "Array size too large %d",arraysize ));
	#endif
	REGVAR * rv = (REGVAR *) gos_Malloc(sizeof(REGVAR)+strlen(Name)+4, gScriptHeap[3]);

	//-------------------------------
	// store new registered variable
	//-------------------------------
	strcpy(rv->Name, "$$");
	strcat(rv->Name, Name);
	strcat(rv->Name, "$$");

	char* pName=rv->Name;
	while( *pName )
	{
		if( *pName>='A' && *pName<='Z' )
			*pName+=32;
		pName++;
	}

	rv->Value = (int )address;
	rv->Type = (BYTE)(vt + KEY_TYPE);
	rv->ArraySize = (WORD)arraysize;
	rv->NameLength = (BYTE)(strlen(Name)+4);
	rv->Instance = (int) instance;

	//-------------------------------
	// insert at head of linked list
	//-------------------------------
	rv->pNext = pScriptRegisteredVariables;	//(if pScriptRegisteredVariables is NULL it is passed to pNext)
	pScriptRegisteredVariables = rv;
}

void __stdcall gosScript_UnregisterVariable( const char* Name, void* instance)
{
	#ifdef _DEBUG
		if (!ScriptsRunning)
			STOP(("Attempting to unregister a gosScript variable without gosScript processor initialized"));
		gosASSERT( Name && (strlen(Name)+4)<256 );
	#endif
	char tmp[256];

	// add $'s to Name
	strcpy(tmp, "$$");
	strcat(tmp, Name);
	strcat(tmp, "$$");
	
	char* pName=tmp;
	while( *pName )
	{
		if( *pName>='A' && *pName<='Z' )
			*pName+=32;
		pName++;
	}

	REGVAR * pPrev = NULL;
	REGVAR * rv = pScriptRegisteredVariables;
	while (rv)
	{
		if ((int)instance == rv->Instance && stricmp(tmp, rv->Name) == 0)
		{
			if (pPrev)
			{
				pPrev->pNext = rv->pNext;
			}
			else
			{
				pScriptRegisteredVariables = rv->pNext;
			}
			gos_Free(rv);
			return;
		}
		pPrev = rv;
		rv = rv->pNext;
	}
}

void __stdcall gosScript_UnregisterAll( void* instance )
{
	if (!ScriptsRunning)
		STOP(("Attempting to unregister a gosScript variable without gosScript processor initialized"));

	REGVAR * pPrev = NULL;
	REGVAR * rv = pScriptRegisteredVariables;
	REGVAR * pNext = NULL;
	while (rv)
	{
		pNext = rv->pNext;
		if ((int)instance == rv->Instance)
		{
			if (pPrev)
				pPrev->pNext = rv->pNext;
			else
				pScriptRegisteredVariables = rv->pNext;
			SPEW(( GROUP_SCRIPTS, "unregistering %s(0x%x)", rv->Name, instance  ));
			gos_Free(rv);
		}
		else
		{
			pPrev = rv;
		}
		rv = pNext;
	}
}


void __stdcall gosScript_UnregisterCallback( const char* Name, void* instance)
{
	#ifdef _DEBUG
		if (!ScriptsRunning)
			STOP(("Attempting to unregister a gosScript callback without gosScript processor initialized"));
		gosASSERT( Name && (strlen(Name)+4)<256 );
	#endif
	char tmp[256];

	// add $'s to Name
	strcpy(tmp, "$$");
	strcat(tmp, Name);
	strcat(tmp, "$$");
	
	char* pName=tmp;
	while( *pName )
	{
		if( *pName>='A' && *pName<='Z' )
			*pName+=32;
		pName++;
	}

	REGVAR * pPrev = NULL;
	REGVAR * rv = pScriptRegisteredVariables;
	while (rv)
	{
		if ((int)instance == rv->Instance && stricmp(tmp, rv->Name) == 0)
		{
			if (pPrev)
			{
				pPrev->pNext = rv->pNext;
			}
			else
			{
				pScriptRegisteredVariables = rv->pNext;
			}
			gos_Free(rv);
			return;
		}
		pPrev = rv;
		rv = rv->pNext;
	}
	STOP(( "Couldn't find variable '%s' to unregister", Name ));
}


extern DWORD FindHash;
//
// Used to add a variable to the correct scope
//
void AddVariable( OBJECT * pObj, VAR_SCOPE NewScope, VARIABLE* newVariable )
{
	char* temp=pLine;
	pLine=newVariable->Name;
	FindKeyWord();
	newVariable->Hash=(WORD)(FindHash&65535);
	pLine=temp;
	
	if (CheckStringAgainstReserved(newVariable->Name))
		ScriptError("Tried to use a reserved keyword as variable name: \"%s\"", newVariable->Name);

	if( NewScope==SCOPE_LOCAL )
	{
		newVariable->pNext=pTempVariables;					// Add variable to temp variables
		pTempVariables=newVariable;
	}
	else if( NewScope==SCOPE_OBJECT )
	{
		newVariable->pNext=pObj->pVariables;				// Add variable to object variables
		pObj->pVariables=newVariable;
	}
	else
	{
		newVariable->pNext=pScript->pMainObject->pVariables;			// Add variable to GLOBAL scope
		pScript->pMainObject->pVariables=newVariable;
	}
}





//
// Executes the current instruction line
//
void ExecuteCommand()
{
//
//	What scope are variables?
//
	VAR_SCOPE NewScope=SCOPE_LOCAL;
	if( CurrentMessage==MSG_GUI_CREATE )
	{
		if( pScript->pMainObject==pObject )
		{
			NewScope=SCOPE_GLOBAL;
		}
		else
		{
			NewScope=SCOPE_OBJECT;
		}
	}
//
// Try and match routines
//
	if( CurrentKeyword>250 )
	{
		if( CurrentKeyword!=253 && FirstKeywordChar[*(BYTE*)pLine] )
		{
			int Function=FindRoutine();
			if( Function!=-1 )
			{
				ExecuteFunction(Function);
				return;
			}
		}
		if( CurrentKeyword==255 )
		{
			*pCurrentKeyword=253;
		}
		CurrentKeyword=GetKeyword();
	}
//
// Get the keyword
//
	int Keyword=CurrentKeyword;

	switch( Keyword )												// Decode command
	{
		case KEY_PRECISION:
			{
				#ifdef _DEBUG
				if (*pLine != '(')
					ScriptError("Missing lead parathesis");
				#endif
				pLine++;
				int val = (int) FloatGetExpression();
				if (val < 0)
					ScriptError("Syntax: printprecision(<var_int pval>) where pval >= 0");
				gFloatPrecision = val;

				if( *pLine==' ' )
					pLine++;

				#ifdef _DEUBG
				if( *pLine!= ')' )
					ScriptError("Missing end parathesis");
				#endif
				pLine++;
				return;

			}

		case KEY_PAUSEMEDIA:
			{
				int kw = GetKeyword();
				if (kw == VAR_MOVIE)
				{
					gosVideo_SetPlayMode((HGOSVIDEO)*pLastVariable, gosVideo_Pause);
					return;
				}

				int channel = -1;
				if (kw == VAR_INT)
					channel = *pLastVariable;
				else
					channel = GetExpression();
#ifdef _DEBUG
				if (channel < 0 || channel > Environment.soundChannels)
					ScriptError("Syntax Error: valid sound channels are 0-",Environment.soundChannels-1);

#endif
				gosAudio_SetChannelPlayMode(channel, gosAudio_Pause);
				return;
			}
		case KEY_CONTINUEMEDIA:
			{
				int kw = GetKeyword();
				if (kw == VAR_MOVIE)
				{
					gosVideo_SetPlayMode((HGOSVIDEO)*pLastVariable, gosVideo_Continue);
					return;
				}

				int channel = -1;
				if (kw == VAR_INT)
					channel = *pLastVariable;
				else
					channel = GetExpression();
#ifdef _DEBUG
				if (channel < 0 || channel > Environment.soundChannels)
					ScriptError("Syntax Error: valid sound channels are 0-",Environment.soundChannels-1);

#endif
				gosAudio_SetChannelPlayMode(channel, gosAudio_Continue);
				return;
			}
		case KEY_GETCLIPBOARD:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Missing lead parathesis");
			#endif
			pLine++;

			#ifdef _DEBUG
			int kw = GetKeyword();
			if (kw != VAR_STRING)
				ScriptError("Syntax Error: GetClipboard(<var_string> str, <var_int> maxLen)");
			#else
			GetKeyword();
			#endif
			char * lpString = (char *) *pLastVariable;
			char ** lplpString = (char **) pLastVariable;

			if( *pLine==' ' )
				pLine++;

			#ifdef _DEBUG
			if (*pLine != ',')
				ScriptError("Syntax Error: GetClipboard(<var_string> str, <var_int> maxLen)");
			#endif
			pLine++;

			int val = GetExpression();
			#ifdef _DEBUG
			if (val < 0)
				ScriptError("Syntax Error: passed a negative value to maxLen");
			#endif

			if( *pLine==' ' )
				pLine++;

			#ifdef _DEUBG
			if( *pLine!= ')' )
				ScriptError("Missing end parathesis");
			#endif
			pLine++;

			if (lpString)
				gos_Free(lpString);

			lpString = (char *) gos_Malloc(val+1, gScriptHeap[1]);

			*lplpString = lpString;
			
			gos_GetClipboardText( lpString, val );
			return;
		}
		break;

		case KEY_SETCLIPBOARD:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Missing lead parathesis");
			#endif
			pLine++;

			int kw = GetKeyword();
			char * lpString = NULL;
			if (kw != VAR_STRING)
			{
				lpString = GetString();
				if (lpString == NULL)
				{
				 	ScriptError("Syntax Error: SetClipboard(<var_string> str)");
					return;
				}
			}
			else
				lpString = (char *) *pLastVariable;

			if( *pLine==' ' )
				pLine++;

			#ifdef _DEBUG
			if( *pLine!=')' )
				ScriptError("Missing end parathesis");
			#endif
			pLine++;

			gos_SetClipboardText( lpString );
			return;
		}
		break;

		case KEY_SETCARET:
		{
			if( *pLine==' ' )
				pLine++;
			#ifdef _DEBUG
			if( *pLine!='(' )
			{
				ScriptError("Missing lead parathesis");
			 	return;
			}
			#endif
			pLine++;
			if( *pLine==' ' )
				pLine++;
			int x = GetExpression();
			if( *pLine==' ' )
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ',')
				ScriptError("Syntax Error: setcaret(<var_int x>, <var_int y>[, windowColor, borderColor, translucency, symbolsize, placement)");
			#endif
			pLine++;
			if( *pLine==' ' )
				pLine++;
			int y = GetExpression();
			if( *pLine==' ' )
				pLine++;
			if (*pLine != ',')
			{
				#ifdef _DEBUG
				if (*pLine != ')')
					ScriptError("Missing end parathesis");
				#endif
				gos_PositionIME(x,y);
				pLine++;
				return;
			}
			else
				pLine++;
			DWORD backgroundColor = GetExpression();
			backgroundColor;
			if( *pLine==' ' )
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ',')
				ScriptError("Syntax Error: setcaret(<var_int x>, <var_int y>[, windowColor, borderColor, translucency, symbolsize, placement,[symbolcolor]])");
			#endif
			pLine++;
			DWORD borderColor = GetExpression();
			borderColor;
			if( *pLine==' ' )
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ',')
				ScriptError("Syntax Error: setcaret(<var_int x>, <var_int y>[, windowColor, borderColor, translucency, symbolsize, placement,[symbolcolor]])");
			#endif
			pLine++;
			int opacity = GetExpression();
			opacity;
			if( *pLine==' ' )
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ',')
				ScriptError("Syntax Error: setcaret(<var_int x>, <var_int y>[, windowColor, borderColor, translucency, symbolsize, placement,[symbolcolor]])");
			#endif
			pLine++;
			int symbolSize = GetExpression();
			symbolSize;
			if( *pLine==' ' )
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ',')
				ScriptError("Syntax Error: setcaret(<var_int x>, <var_int y>[, windowColor, borderColor, translucency, symbolsize, placement,[symbolcolor]])");
			#endif
			pLine++;
			int placement = GetExpression();
			placement;
			if( *pLine==' ' )
				pLine++;
			DWORD symbolColor = 0;
			if (*pLine == ',')
			{
				pLine++;
				symbolColor = GetExpression();
				if( *pLine==' ' )
					pLine++;
			}
			#ifdef _DEBUG
			if (*pLine != ')')
				ScriptError("Missing end parathesis");
			#endif
			pLine++;
				
			gos_PositionIME(x,y);
			return;
		}
		case KEY_TOGGLEIME:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
			{
				ScriptError("Missing lead parathesis");
			 	return;
			}
			#endif
			pLine++;
			if( *pLine==' ' )
				pLine++;
			int value = GetExpression();
			#ifdef _DEBUG
			if (value != 0 && value!= 1)
				ScriptError("Syntax Error: toggleIME(<var_int 0 or 1>[, var_object])");
			#endif
			if (*pLine == ')')
			{
				pObject->dwIMEState = value;
				pLine++;
				gos_ToggleIME(value ? true: false);
				return;
			}
			if (*pLine == ' ')
				pLine++;
			if (*pLine != ',')
				ScriptError("Syntax Error: toggleIME(<var_int 0 or 1>[, var_object])");
			else
			{
				pLine++;
				int kw = GetKeyword();
				if (kw != VAR_INT && kw != VAR_OBJECT)
					ScriptError("Syntax Error: toggleIME(<var_int 0 or 1>[, var_object])");
				else
				{
					((OBJECT *)(*pLastVariable))->dwIMEState = value;
					if (((OBJECT *)(*pLastVariable)) == pFocusedObject)
						gos_ToggleIME(value ? true: false);
				}
				if (*pLine != ')')
					ScriptError("Syntax Error: toggleIME(<var_int 0 or 1>[, var_object])");
				else
					return;


			}
		}
		case KEY_ENABLEIME:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
			{
				ScriptError("Missing lead parathesis");
			 	return;
			}
			#endif
			pLine++;
			if( *pLine==' ' )
				pLine++;
			int value = GetExpression();
			#ifdef _DEBUG
			if (value != 0 && value!= 1)
				ScriptError("Syntax Error: enableIME(<var_int 0 or 1>[, var_object])");
			#endif
			if (*pLine == ')')
			{
				pObject->dwAvailIME = value;
				pLine++;
				gos_EnableIME(value ? true: false);
				return;
			}
			if (*pLine == ' ')
				pLine++;
			if (*pLine != ',')
				ScriptError("Syntax Error: enableIME(<var_int 0 or 1>[, var_object])");
			else
			{
				pLine++;
				int kw = GetKeyword();
				if (kw != VAR_INT && kw != VAR_OBJECT)
					ScriptError("Syntax Error: enableIME(<var_int 0 or 1>[, var_object])");
				else
				{
					((OBJECT *)(*pLastVariable))->dwAvailIME = value;
					if (((OBJECT *)(*pLastVariable)) == pFocusedObject)
						gos_EnableIME(value ? true: false);
				}
				if (*pLine != ')')
					ScriptError("Syntax Error: enableIME(<var_int 0 or 1>[, var_object])");
				else
					return;


			}
		}
		case KEY_GETSCRIPTINFO:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
			{
				ScriptError("Missing lead parathesis");
			 	return;
			}
			#endif
			pLine++;
			if( *pLine == ' ' )
				pLine++;

			#ifdef _DEBUG
			int arg = GetKeyword();
			if ( arg != VAR_OBJECT )
			{
				ScriptError("Syntax: getscriptinfo(<var_object obj>, <var_string str>, <var_int instance>)");
			 	return;
			}
			#else
			GetKeyword();
			#endif
			
			OBJECT * o = (OBJECT *) *pLastVariable;
			if( *pLine == ' ' )
				pLine++;
			
			#ifdef _DEBUG
			if (*pLine != ',')
				ScriptError("Syntax: getscriptinfo(<var_object obj>, <var_string str>, <var_int instance>)");
			#endif

			pLine++;
			#ifdef _DEBUG
			arg = GetKeyword();
			if ( arg != VAR_STRING )
			{
				ScriptError("Syntax: getscriptinfo(<var_object obj>, <var_string str>, <var_int instance>)");
			 	return;
			}
			#else
			GetKeyword();
			#endif
									
			char * str = (char *)*pLastVariable;
			char ** lplpStr = (char **) pLastVariable;

			if( *pLine==' ' )
				pLine++;

			#ifdef _DEBUG
			if (*pLine != ',')
				ScriptError("Syntax: getscriptinfo(<var_object obj>, <var_string str>, <var_int instance>)");
			#endif

			pLine++;
			#ifdef _DEBUG
			arg = GetKeyword();
			if ( arg != VAR_INT )
			{
				ScriptError("Syntax: getscriptinfo(<var_object obj>, <var_string str>, <var_int instance>)");
			 	return;
			}
			#else
			GetKeyword();
			#endif

			if (str)
				gos_Free(str);
			FILENAME * ptr = o->pScript->pFileNames;
			while (ptr->pNext)
				ptr = ptr->pNext;
			str = (char *) gos_Malloc(strlen(ptr->LongFileName)+1, gScriptHeap[1]);
			*lplpStr = str;
			strcpy(str, ptr->LongFileName);
			*pLastVariable = o->pScript->Instance;
			if( *pLine==' ' )
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ')')
				ScriptError("Syntax: getscriptinfo(<var_object obj>, <var_string str>, <var_int instance>)");
			#endif
			return;
		};
		case KEY_MAKEABSOLUTE:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
			{
				ScriptError("Missing lead parathesis");
			 	return;
			}
			#endif
			pLine++;
			if( *pLine == ' ')
				pLine++;

			#ifdef _DEBUG
			int arg1 = GetKeyword();
			if( arg1 != VAR_POSITION )
			{
				ScriptError("Syntax: makeabsolute(<var_position>, [var_object])");
			 	return;
			}
			#else
			GetKeyword();
			#endif

			POSITION * save = (POSITION *) *pLastVariable;
			OBJECT * o = pObject;

			if( *pLine == ' ' )
				pLine++;
			if (*pLine == ')')
			{
				pLine++;
			}
			else
			if (*pLine != ',')
			{
				ScriptError("Missing end parathesis");
				return;
			}
			else
			{
				pLine++;
				// absolute is from another object....
				int arg2 = GetKeyword();
				if (arg2 != VAR_OBJECT)
				{
					ScriptError("Syntax: makeabsolute(<var_position>, [var_object])");
					return;
				}
				else
				{
					o = ((OBJECT *)*pLastVariable);
				}
			}

			POSITION pos = {0,0,0};
			while(o)
			{
				pos.x += o->Coordinates->x;
				pos.y += o->Coordinates->y;
				pos.z += o->Coordinates->z;
				if (*o->bPosRelative)
					o = o->pParentObject;
				else
					break;
			}

			save->x += pos.x;
			save->y += pos.y;
			save->z += pos.z;
			return;
		}

		case KEY_LIST:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();									// Try and match against keywords and variables
			pLine=Name;

			if( Exist==VAR_LIST )
			{		
				if( LastVariableScope==NewScope )
					ScriptError("List redefinition" );				// Already defined as a gaf at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();											// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_LIST;								// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;					// Not an array element
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();		// Get array size

				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif
			}

			if( newVariable->ArraySize )
			{
				newVariable->pLists = (gosScript_List**)gos_Malloc(newVariable->ArraySize*sizeof(DWORD*), gScriptHeap[3]);
																   
				for( int i=0; i<newVariable->ArraySize; i++ )
					newVariable->pLists[i]= new(gScriptHeap[3]) gosScript_List();
			}
			else
			{
				newVariable->pList = new(gScriptHeap[3]) gosScript_List();				// Load in doc
			}
			
			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			return;
		}

		case VAR_LIST:
		{
			ScriptError("Meaningless expression.");
			break;
		}

		case KEY_STRINGRESOURCE:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax: stringresource(<var_string file>)");
			pLine++;
			char* file = GetString();
			if( !file )
			{
				ScriptError("Syntax: stringresource(<var_string file>)");
			}
			#else
			pLine++;
			char* file = GetString();
			#endif

			if (gosScript_localizationFile)
			{
				gos_CloseResourceDLL(gosScript_localizationFile);
			}
			gosScript_localizationFile = gos_OpenResourceDLL(file);

			#ifdef _DEBUG
			if (*pLine != ')')
				ScriptError("Syntax: stringresource(<var_string file>)");
			#endif
			pLine++;
			break;
		}
		case KEY_ACTIVATE:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax: activate(<var_object>)");
			#endif
			pLine++;
			#ifdef _DEBUG
			int key = GetKeyword();
			if (key != VAR_OBJECT)
				ScriptError("Syntax: activate(<var_object>)");
			if (*pLine != ')')
				ScriptError("Syntax: activate(<var_object>)");
			#else
			GetKeyword();
			#endif
			pLine++;

			((OBJECT *)*pLastVariable)->bActive = true;
			SendScriptMessage( (OBJECT *) *pLastVariable, MSG_GUI_ACTIVATE );		// send GUI_CREATE to object
			break;
		}

		case KEY_DEACTIVATE:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax: deactivate(<var_object>)");
			#endif
			pLine++;
			#ifdef _DEBUG
			int key = GetKeyword();
			if (key != VAR_OBJECT)
				ScriptError("Syntax: deactivate(<var_object>)");
			if (*pLine != ')')
				ScriptError("Syntax: deactivate(<var_object>)");
			#else
			GetKeyword();
			#endif
			pLine++;
			//
			// If the cursor is in this object's region, be sure to send it 
			// a region_exited msg before deactivation.
			//
			OBJECT * target = (OBJECT *) *pLastVariable;
			if (target->bMouseInRegion)
				SendScriptMessage( target, MSG_REGION_EXITED );	

			target->bActive = false;
			SendScriptMessage( target, MSG_GUI_DEACTIVATE );		// send GUI_CREATE to object
			break;
		}

		case KEY_TERMINATE:
		{
			gos_TerminateApplication();
			break;
		}
		case KEY_TEXTUREHEAP:
		{
			#ifdef _DEBUG
			ScriptError("Legacy command - no longer required");
			#endif
			break;
		}
		case KEY_PENCOLOR:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax: setpencolor(var_int) or setpencolor(r,g,b,a)");
			#endif
			pLine++;
			g_scriptLineColor = GetExpression();
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ')' && *pLine != ',')
				ScriptError("Syntax: setpencolor(var_int) or setpencolor(r,g,b,a)");
			#endif
			if (*pLine == ')') 
			{	
				pLine++;
				return;
			}
			pLine++;
			int g,b,a;
			g = GetExpression();
			#ifdef _DEBUG
			if (*pLine != ',')
				ScriptError("Syntax: setpencolor(var_int) or setpencolor(r,g,b,a)");
			#endif
			pLine++;
			b = GetExpression();
			#ifdef _DEBUG
			if (*pLine != ',')
				ScriptError("Syntax: setpencolor(var_int) or setpencolor(r,g,b,a)");
			#endif
			pLine++;
			a = GetExpression();
			#ifdef _DEBUG
			if (*pLine != ')') 
				ScriptError("Syntax: setpencolor(var_int) or setpencolor(r,g,b,a)");
			#endif
			g_scriptLineColor = (g_scriptLineColor << 16) + (a<<24) + (g<<8) + b;
			pLine++;
			return;
		}
		case KEY_DRAWFRAME:
		{
			#ifdef _DEBUG
			if (gScript_InDraw == false)
				ScriptError(("Calling 'drawframe' outside GUI_DRAW is illegal"));
			#endif

			CUBE cube;

			*pCurrentLineFlags=GetCube( &cube, *pCurrentLineFlags );

			OBJECT * ptr = pObject;
			if (*ptr->bPosRelative)
			{
				while(ptr)
				{
					cube.p1.x += ptr->Coordinates->x;
					cube.p1.y += ptr->Coordinates->y;
					cube.p2.x += ptr->Coordinates->x;
					cube.p2.y += ptr->Coordinates->y;
					if (*ptr->bPosRelative)
						ptr = ptr->pParentObject;
					else
						break;
				}
			}
			ScriptDrawLine( cube.p1.x, cube.p1.y, cube.p2.x, cube.p1.y, g_scriptLineColor );
			ScriptDrawLine( cube.p2.x, cube.p1.y, cube.p2.x, cube.p2.y, g_scriptLineColor );
			ScriptDrawLine( cube.p2.x, cube.p2.y, cube.p1.x, cube.p2.y, g_scriptLineColor );
			ScriptDrawLine( cube.p1.x, cube.p2.y, cube.p1.x, cube.p1.y, g_scriptLineColor );
			return;
		}		
		case KEY_DRAWRECT:
		{
			#ifdef _DEBUG
			if (gScript_InDraw == false)
				ScriptError(("Calling 'drawrect' outside GUI_DRAW is illegal"));
			#endif

			CUBE cube;

			*pCurrentLineFlags=GetCube( &cube, *pCurrentLineFlags );

			OBJECT * ptr = pObject;
			if (*ptr->bPosRelative)
			{
				while(ptr)
				{
					cube.p1.x += ptr->Coordinates->x;
					cube.p1.y += ptr->Coordinates->y;
					cube.p2.x += ptr->Coordinates->x;
					cube.p2.y += ptr->Coordinates->y;
					if (*ptr->bPosRelative)
						ptr = ptr->pParentObject;
					else
						break;
				}
			}
			DrawRect(cube.p1.x,cube.p1.y,cube.p2.x,cube.p2.y,g_scriptLineColor);

			return;
		}
		case KEY_DRAWFRAMELOCAL:
		{
			#ifdef _DEBUG
			if (gScript_InDraw == false)
				ScriptError(("Calling 'ldrawframe' outside GUI_DRAW is illegal"));
			#endif

			CUBE cube;

			*pCurrentLineFlags=GetCube( &cube, *pCurrentLineFlags );

			OBJECT * ptr = pObject;
			while(ptr)
			{
				cube.p1.x += ptr->Coordinates->x;
				cube.p1.y += ptr->Coordinates->y;
				cube.p2.x += ptr->Coordinates->x;
				cube.p2.y += ptr->Coordinates->y;
				if (*ptr->bPosRelative)
					ptr = ptr->pParentObject;
				else
					break;
			}
			ScriptDrawLine( cube.p1.x, cube.p1.y, cube.p2.x, cube.p1.y, g_scriptLineColor );
			ScriptDrawLine( cube.p2.x, cube.p1.y, cube.p2.x, cube.p2.y, g_scriptLineColor );
			ScriptDrawLine( cube.p2.x, cube.p2.y, cube.p1.x, cube.p2.y, g_scriptLineColor );
			ScriptDrawLine( cube.p1.x, cube.p2.y, cube.p1.x, cube.p1.y, g_scriptLineColor );
			return;
		}		
		case KEY_DRAWRECTLOCAL:
		{
			#ifdef _DEBUG
			if (gScript_InDraw == false)
				ScriptError(("Calling 'ldrawrect' outside GUI_DRAW is illegal"));
			#endif

			CUBE cube;
			*pCurrentLineFlags=GetCube( &cube, *pCurrentLineFlags );

			OBJECT * ptr = pObject;
			while(ptr)
			{
				cube.p1.x += ptr->Coordinates->x;
				cube.p1.y += ptr->Coordinates->y;
				cube.p2.x += ptr->Coordinates->x;
				cube.p2.y += ptr->Coordinates->y;
				if (*ptr->bPosRelative)
					ptr = ptr->pParentObject;
				else
					break;
			}
			DrawRect(
				cube.p1.x,
				cube.p1.y,
				cube.p2.x,
				cube.p2.y,
				g_scriptLineColor);

			return;
		}
		case KEY_INITIALIZE:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax error: initialize(<var_object>");
			#endif
			pLine++;
			#ifdef _DEBUG
			int kw = GetKeyword();
			if (kw != VAR_OBJECT)
				ScriptError("Syntax error: initialize(<var_object>");
			#else
			GetKeyword();
			#endif
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ')')
				ScriptError("Syntax error: initialize(<var_object>");
			#endif
			pLine++;
			SendScriptMessage( (OBJECT *) *pLastVariable, MSG_GUI_INIT );		// send GUI_CREATE to object
			return;
		}
		case KEY_FORCEEXEC:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax error: force_execute(<var_object>");
			#endif
			pLine++;
			#ifdef _DEBUG
			int kw = GetKeyword();
			if (kw != VAR_OBJECT)
				ScriptError("Syntax error: force_execute(<var_object>");
			#else
			GetKeyword();
			#endif
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ')')
				ScriptError("Syntax error: force_execute(<var_object>");
			#endif
			pLine++;
			SendScriptMessage( (OBJECT *) *pLastVariable, MSG_GUI_EXECUTE );		// send GUI_CREATE to object
			return;
		}
		case KEY_FILL:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax error: fill<var_pane)=<var_int r>, <var_int g>, <var_int b>, <var_int a>");
			#endif
			pLine++;
			int kw = GetKeyword();
			int * save = (int *) *pLastVariable;
			#ifdef _DEBUG
			if (kw != VAR_PANE && kw != VAR_BITMAP)
				ScriptError("Syntax error: fill<var_pane)=<var_int r>, <var_int g>, <var_int b>, <var_int a>");
			#endif
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ')')
				ScriptError("Syntax error: fill<var_pane)=<var_int r>, <var_int g>, <var_int b>, <var_int a>");
			#endif
			pLine++;
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != '=')
				ScriptError("Syntax error: fill<var_pane)=<var_int r>, <var_int g>, <var_int b>, <var_int a>");
			#endif
			pLine++;

			DWORD dwcolor;
			int val = GetExpression();
			if (*pLine == ' ')
				pLine++;
			if (*pLine == ',')
			{
				pLine++;
				POSITION p;
				GetPosition(&p,1);
				dwcolor = (p.z << 24) + (val << 16) + (p.x<<8) + p.y;
			}
			else
			{
				int r = (val & 0xff000000) >> 24;
				int g = (val & 0xff0000) >> 16;
				int b = (val & 0xff00) >> 8;
				int a = (val & 0xff);
				dwcolor = (a<<24) + (r<<16) + (g<<8) + b;
			}
			
			if (kw == VAR_PANE)
			{
				#ifdef _DEBUG
				if( !((gos_Pane *) save)->GetSurface() )
				{
					ScriptError("This pane was not flagged as is_volatile when it was created");
				}
				#endif
				gos_ClearSurface(((gos_Pane *) save)->GetSurface(), dwcolor);
			}
			else
			if (kw == VAR_BITMAP)
			{
				gos_ClearSurface((HGOSSURFACE) save, dwcolor);
			}
	
			return;
		}
		case KEY_NOCONSUME:
		{
			bIgnoreMouseMessages = false;
			return;
		}
		case KEY_POSITION:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();									// Try and match against keywords and variables
			pLine=Name;

			if( Exist==VAR_POSITION )
			{
				if( LastVariableScope==NewScope )
					ScriptError("Position redefinition" );			// Already defined as a bitmap at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();											// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_POSITION;							// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;					// Not an array element
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();		// Get array size

				#ifdef _DEBUG
				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				#endif
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif

				newVariable->pPosition= (POSITION*) gos_Malloc(newVariable->ArraySize*sizeof(POSITION*), gScriptHeap[3]);

				POSITION temppos={0,0,0};								// Default position

				if (*pLine ==  ' ')
					pLine++;

				if( *pLine=='=' )
				{
					pLine++;
					GetPosition( &temppos );
					for( int i=0; i<newVariable->ArraySize; i++ )			// Make all positions the default value
					{
						newVariable->pValues[i] = (int) gos_Malloc(sizeof(POSITION), gScriptHeap[3]);
						memcpy((char *)newVariable->pValues[i],&temppos,sizeof(POSITION));
					}
				}
				else
				{
					for( int i=0; i<newVariable->ArraySize; i++ )			// Make all positions the default value
					{
						newVariable->pValues[i] = (int) gos_Malloc(sizeof(POSITION), gScriptHeap[3]);
						memset((char *)newVariable->pValues[i],0,sizeof(POSITION));
					}
				}
			}
			else
			{
				newVariable->pPosition= (POSITION*) gos_Malloc(sizeof(POSITION), gScriptHeap[3]);
				POSITION temppos={0,0,0};								// Default position

				if (*pLine == ' ')
					pLine++;
				if( *pLine=='=' )
				{
					pLine++;
					GetPosition( &temppos );
				}
				memcpy(newVariable->pPosition,&temppos,sizeof(POSITION));
			}

			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			return;
		}

//
// CUBE definition (ie: cube region=<pos> to <pos>)
//
		case KEY_CUBE:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();									// Try and match against keywords and variables
			pLine=Name;

			if( Exist==VAR_CUBE )
			{
				if( LastVariableScope==NewScope )
					ScriptError("Position redefinition" );			// Already defined as a bitmap at current scope?
			}
			else
				if (Exist != -1)
					if( !CheckStringAgainstReserved(Name) )
						ScriptError("Invalid variable name" );
			#else
			GetKeyword();											// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_CUBE;							// Create new variable
			newVariable->ArraySize=0;							// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();	// Get array size

				#ifdef _DEBUG
				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				#endif
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif


				CUBE cube;
				memset(&cube,0,sizeof(CUBE));
					
				newVariable->pCubes = (CUBE**) gos_Malloc(newVariable->ArraySize*sizeof(CUBE *), gScriptHeap[3]);

				if(*pLine == ' ')
					pLine++;

				if( *pLine=='=' )
				{
					pLine++;
					GetCube( &cube );
				}

				for( int i=0; i<newVariable->ArraySize; i++ )			// Make all positions the default value
				{
					newVariable->pCubes[i] = (CUBE *) gos_Malloc(sizeof(CUBE), gScriptHeap[3]);
					memcpy(newVariable->pCubes[i],  &cube,sizeof(CUBE));
				}
			}
			else
			{
				CUBE* cube = (CUBE*) gos_Malloc(sizeof(CUBE), gScriptHeap[3]);
				memset(cube,0,sizeof(CUBE));
				newVariable->pCube = cube;
				if(*pLine == ' ')
					pLine++;

				if( *pLine=='=' )
				{
					pLine++;
					GetCube( cube );
				}
			}

			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			return;
		}
//
// BITMAP definition (ie: bitmap fred="fred.bmp" )
//
		case KEY_BITMAP:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();									// Try and match against keywords and variables
			pLine=Name;

			if( Exist==VAR_BITMAP )
			{
				if( LastVariableScope==NewScope )
					ScriptError("Bitmap redefinition" );			// Already defined as a bitmap at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();											// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_BITMAP;							// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();				// Get array size
	
				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif
			}
//
// Arrays of bitmaps are treated all individually ie: Bitmap[20]="fred.bmp" will load 20 copies of "fred.bmp"
//
			if( newVariable->ArraySize  > 0)
			{
				HGOSSURFACE* surf = (HGOSSURFACE*)gos_Malloc(newVariable->ArraySize*sizeof(HGOSSURFACE), gScriptHeap[3]);
				newVariable->pSurfaces=surf;

				if (*pLine ==' ')
					pLine++;
				if( *pLine=='=' )
				{
					pLine++;

					char* Name=GetString();							// If string is null, don't load surface
					static char tmp[128];

					for( int i=0; i<newVariable->ArraySize; i++ )
					{
						HGOSSURFACE surf=0;
						sprintf(tmp,Name,i+1);
						gos_LoadSurface(tmp, &surf,1);				// Load in surface
						newVariable->pSurfaces[i]=surf;
					}
				}
				else
				{
					for( int i=0; i<newVariable->ArraySize; i++ )
						newVariable->pSurfaces[i]=0;	
				}
			}
			else
			{
				HGOSSURFACE surf=0;
				if( *pLine=='=' )
				{
					pLine++;
					char* Name=GetString();							// If string is null, don't load surface
					if (!Name)
					{
						int val = GetExpression();
						if (val)
							ScriptError("Syntax: bitmap <name> = <var_string> or NULL");
					}
					else
						gos_LoadSurface(Name, &surf,1);					// Load in surface
				}
				newVariable->Surface=surf;
			}
			
			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			return;
		}
//
// MOVIE definition (ie: bitmap fred="fred.bmp" )
//
		case KEY_MOVIE:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();									// Try and match against keywords and variables
			pLine=Name;

			if( Exist==VAR_MOVIE )
			{
				if( LastVariableScope==NewScope )
					ScriptError("Movie redefinition" );				// Already defined as a bitmap at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();											// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_MOVIE;							// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();				// Get array size

				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif

			}
//
// Arrays of movie are treated all individually ie: movie[20]="fred.avi" will load 20 copies of "fred.avi"
//
			if( newVariable->ArraySize )
			{
				HGOSVIDEO* vid = (HGOSVIDEO*)gos_Malloc(newVariable->ArraySize*sizeof(HGOSVIDEO), gScriptHeap[3]);
				newVariable->pVideos=vid;

				if( *pLine=='=' )
				{
					pLine++;

					char* Name=GetString();							// If string is null, don't load surface
					for( int i=0; i<newVariable->ArraySize; i++ )
					{
						HGOSVIDEO vid=0;
						gosVideo_CreateResource( &vid, Name );				// Load in surface
						newVariable->pVideos[i]=vid;
					}
				}
				else
				{
					for( int i=0; i<newVariable->ArraySize; i++ )
						newVariable->pVideos[i]=0;	
				}
			}
			else
			{
				HGOSVIDEO vid=0;
				if( *pLine=='=' )
				{
					pLine++;
					char* Name=GetString();							// If string is null, don't load surface
					gosASSERT(Name != NULL);
					gosVideo_CreateResource( &vid, Name );					// Load in surface
				}
				newVariable->Video=vid;
			}
			
			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			return;
		}

		case KEY_STOPMEDIA:
		{
			int kw = GetKeyword();

			if (kw == VAR_MOVIE)
			{
				// its a movie
				HGOSVIDEO vid = (HGOSVIDEO) *pLastVariable;
				gosVideo_SetPlayMode(vid, gosVideo_Stop);
				return;
			}
			else
			if (kw == VAR_PANE)
			{
				gos_Pane * p = (gos_Pane*)*pLastVariable;
				if (!p->hVideo)
					ScriptError("That pane does render a movie");
				else
					p->Stop();
				return;
			}
			else
			if (kw == VAR_INT)
			{
				gosAudio_SetChannelPlayMode(*pLastVariable,gosAudio_Stop);
				return;
			}
			else
			{
				if( kw == -1 )												// If the value is null, play nothing
				{
					int exp = GetExpression();
					gosAudio_SetChannelPlayMode(exp,gosAudio_Stop);
					return;
				}
			}
			ScriptError("Syntax error, stop <var_int channel or var_movie>" );
			return;
		}
//
// GAF definition (ie: gaf fred="fred.gaf" )
//
		case KEY_GAF:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();									// Try and match against keywords and variables
			pLine=Name;

			if( Exist==VAR_GAF )
			{
				if( LastVariableScope==NewScope )
					ScriptError("GAF redefinition" );				// Already defined as a gaf at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();											// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_GAF;								// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();				// Get array size

				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif

			}
//
// Arrays of gafs are treated all individually ie: gaf[20]="fred.gaf" will load 20 copies of "fred.gaf"
//
			if( newVariable->ArraySize )
			{
				HGOSGAF* gaf = (HGOSGAF*)gos_Malloc(newVariable->ArraySize*sizeof(HGOSGAF), gScriptHeap[3]);
				newVariable->pGAFs=gaf;

				if( *pLine=='=' )
				{
					pLine++;

					char* Name=GetString();							// If string is null, don't load surface
#ifdef _ARMOR
					if (Name && !gos_DoesFileExist(Name))
						ScriptError("Cannot locate the file \"%s\"",Name);
#endif
					for( int i=0; i<newVariable->ArraySize; i++ )
					{
						HGOSGAF gaf=0;
						gos_CreateGAFResource(&gaf, Name);				// Load in gaf
						newVariable->pGAFs[i]=(HGOSGAF)gaf;
					}
				}
				else
				{
					for( int i=0; i<newVariable->ArraySize; i++ )
						newVariable->pGAFs[i]=0;	
				}
			}
			else
			{
				HGOSGAF gaf=0;
				if( *pLine=='=' )
				{
					pLine++;
					char* Name=GetString();							// If string is null, don't load surface
#ifdef _ARMOR
					if (Name && !gos_DoesFileExist(Name))
						ScriptError("Cannot locate the file \"%s\"",Name);
#endif
					gos_CreateGAFResource(&gaf,Name);					// Load in gaf
				}
				newVariable->Gaf=gaf;
			}
			
			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			return;
		}
		case KEY_SETFRAME:
		{
			if (*pLine == ' ')
				pLine++;
			if (*pLine != '(')
				ScriptError("Syntax: setframe(<var_gaf>, <expr>);");
			else 
				pLine++;
			int kw = GetKeyword();
			if (kw != VAR_GAF)
				ScriptError("Syntax: setframe(<var_gaf>, <expr>);");
			HGOSGAF gaf = (HGOSGAF)*pLastVariable;
			if (*pLine == ' ')
				pLine++;
			if (*pLine != ',')
				ScriptError("Syntax: setframe(<var_gaf>, <expr>);");
			else 
				pLine++;
			int val = GetExpression();
			if (*pLine == ' ')
				pLine++;
			if (*pLine != ')')
				ScriptError("Syntax: setframe(<var_gaf>, <expr>);");
			else 
				pLine++;
			if( 0==gaf )
				ScriptError("This gaf is not yet loaded");
			HGOSSURFACE surf;
			gos_GetGAFFrame(gaf, val, &surf);
			return;
		}
// print_position
		case KEY_PRINT_POSITION:
		{
			if (*pLine != '=')
				ScriptError("print_position was expecting '='");
			else
				pLine++;

			POSITION pos;
			*pCurrentLineFlags = GetPosition( &pos, *pCurrentLineFlags );

			gosScript_TextSetLocation(pos.x,pos.y);
			return;
		}
// print_bitmap
		case KEY_PRINT_BITMAP:
		{
			if (*pLine != '=')
				ScriptError("print_bitmap was expecting '='");

			pLine++;
			int kw = GetKeyword();
			if (kw == VAR_PANE)
			{
				gosScript_TextSetSurface(((gos_Pane *)*pLastVariable)->GetSurface());
				return;
			}

			if( kw != VAR_BITMAP )
			{
				ScriptError("print_bitmap was expecting <bitmap> as arg" );			// Already defined as a bitmap at current scope?
			}

			gosScript_TextSetSurface((HGOSSURFACE) *pLastVariable);
			return;
		}
// print_bitmap
		case KEY_PRINT_FONT:
		{
			#ifdef _DEBUG
			if (*pLine != '=')
				ScriptError("print_font was expecting '='");
			#endif
			pLine++;
			if(*pLine == ' ')
				pLine++;

			if( VAR_FONT!=GetKeyword() )
			{
				ScriptError("print_font was expecting <font> as arg" );			// Already defined as a bitmap at current scope?
			}

			gosScript_TextSelectFont((HGOSFONT) *pLastVariable);
			return;
		}
// print <string>
		case KEY_PRINT_MARGINS:
		{
			#ifdef _DEBUG
			if (*pLine != '=')
				ScriptError("print_margins was expecting '='");
			#endif
			pLine++;
			*pCurrentLineFlags=GetCube( &g_textMargins, *pCurrentLineFlags );
			return;
		}
// colorkey <bitmap>
		case KEY_COLORKEY:
		{
			if(*pLine == ' ')
				pLine++;
			int kw = GetKeyword();
			if (kw != VAR_BITMAP && kw != VAR_FONT && kw != VAR_GAF)
			{
				ScriptError("colorkey was expecting <bitmap> or <font>");
			}
			if(*pLine == ' ')
				pLine++;
			if (*pLine != ',')
				ScriptError("colorkey was expecting ','");
			else
				pLine++;

			int val = GetExpression();
			if (val)
			{
				if (kw == VAR_GAF)
				{
					gos_MakeChromaKeySurface( gos_GetSurface((HGOSGAF) *pLastVariable), true);
				}
				else
				{
					gos_MakeChromaKeySurface( (HGOSSURFACE) *pLastVariable, true );
				}
			}
			else
			{
				if (kw == VAR_GAF)
				{
					gos_MakeChromaKeySurface( gos_GetSurface((HGOSGAF) *pLastVariable), false);
				}
				else
				{
					gos_MakeChromaKeySurface( (HGOSSURFACE) *pLastVariable, false );
				}
			}
			return;
		}
// bitmap_clear <bitmap>
		case KEY_BITMAPCLEAR:
		{
			if(*pLine == ' ')
				pLine++;
			int kw = GetKeyword();
			if (kw != VAR_BITMAP)
			{
				ScriptError("bitmap_clear was expecting <bitmap>");
			}
			if(*pLine == ' ')
				pLine++;
			if (*pLine != ',')
				ScriptError("bitmap_clear was expecting ', <color>'");
			else
				pLine++;

			HGOSSURFACE bm = (HGOSSURFACE) *pLastVariable;
			int val = GetExpression();
			gos_ClearSurface( bm, val );
			return;
		}
// bitmap_refresh <bitmap>
		case KEY_BITMAPREFRESH:
		{
			if(*pLine == ' ')
				pLine++;
			int kw = GetKeyword();
			if (kw != VAR_BITMAP)
			{
				ScriptError("bitmap_refresh was expecting <bitmap>");
			}
			gos_RestoreSurface(((HGOSSURFACE)*pLastVariable));
			return;
		}
// print <string>
		case KEY_WRAPWORD:
		{
			gosScript_TextSetWrapMode(GOSWRAP_WORD);
			return;
		}
		case KEY_WRAPLETTER:
		{
			gosScript_TextSetWrapMode(GOSWRAP_CHAR);
			return;
		}

		case KEY_WRAPNONE:
		{
			gosScript_TextSetWrapMode(GOSWRAP_NONE);
			return;
		}


		case KEY_PRINT:
		{
			while(1)
			{
				if( *pLine==' ' )
					pLine++;

				if( *pLine=='"')
					gosScript_TextOut(GetString());
				else
				{
//					char* pTemp=pLine;
					int Type=GetKeyword();
//					pLine=pTemp;
					
					if( VAR_STRING==Type )
						gosScript_TextOut((char *)*pLastVariable);
					else
					if( VAR_INT==Type )
					{
						static char tmp[32];
						sprintf(tmp,"%d",*pLastVariable);
						gosScript_TextOut(tmp);
					}
					else
					if( VAR_FLOAT==Type )
					{
						static char tmp[32];
						sprintf(tmp,"%.2f",*pLastVariable);
						gosScript_TextOut(tmp);
					}
					else
					{
						static char tmp[32];
						sprintf(tmp,"%d",GetExpression());
						gosScript_TextOut(tmp);
					}
				}
				if (*pLine == ' ')
					pLine++;
				if( *pLine!=',' )
					return;

				pLine++;
			}
			return;
		}

		case KEY_FOCUS:
		{
				int Exist;
				OBJECT * targ = NULL;
				if (*pLine == ' ')
					pLine++;
				if (*pLine != '(')
					goto focus_syntax;
				else 
					pLine++;
				Exist=GetKeyword();
				if( Exist==VAR_OBJECT || Exist == VAR_INT)
				{
					if (*pLine == ' ')
						pLine++;
					if (*pLine != ')')
						goto focus_syntax;
					else
						pLine++;
					targ = (OBJECT *)*pLastVariable;
					// return if this object already HAS focus
					if ( pFocusedObject == targ)
						return;

					// 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 = targ;
					pFocusedScript = targ->pScript;
					gos_KeyboardFlush();
					SendScriptMessage(pFocusedObject, MSG_GUI_FOCUS);
					return;
				}
				else
				{
					// the parameter isn't any object; the only other valid parameter is zero
					int val = GetExpression();
					if (*pLine == ' ')
						pLine++;
					if (*pLine != ')')
						goto focus_syntax;
					else
						pLine++;
					if (val == 0)
					{
						if (pFocusedObject)
							SendScriptMessage(pFocusedObject, MSG_GUI_UNFOCUS);
						pFocusedObject = NULL;
						pFocusedScript = NULL;
						return;
					}
				}
focus_syntax:
				ScriptError("Syntax error: focus(<var_object> or <NULL>)");
				break;
	
	   	}
		case KEY_UNFOCUS:
		{
			if (pFocusedObject)
			{
				SendScriptMessage(pFocusedObject, MSG_GUI_UNFOCUS);
			}
			pFocusedObject = NULL;
			pFocusedScript = NULL;
			return;
		}

//
// FONT definition (ie: font fred="fred.bmp" )
//
		case KEY_FONT:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();									// Try and match against keywords and variables
			pLine=Name;

			if( Exist==VAR_FONT )
			{
				if( LastVariableScope==NewScope )
					ScriptError("Script Error: font redefinition" );// Already defined as a bitmap at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();											// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_FONT;								// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine==0 )											// Defined, but no init of a variable
			{
				newVariable->Value=0;
			}
			else
			{
				if( *pLine != '=' )
					ScriptError("Syntax error: Expected 'font <Name> = \"file\"'" );	// Bad first character or a reserved keyword
	
				pLine++;

				char* Name=GetString();								// If string is null, don't load surface

				if(*pLine == ' ') 
					pLine++;
				if (*pLine != ',')
					ScriptError("Syntax error: Font was expecting ','");
				else
					pLine++;


				int w = GetExpression();
				if(*pLine == ' ') 
					pLine++;
				if (*pLine != ',')
					ScriptError("Syntax error: Font was expecting ','");
				else
					pLine++;


				int h = GetExpression();
				if(*pLine == ' ') 
					pLine++;
				if (*pLine != ',')
					ScriptError("Syntax error: Font was expecting ','");
				else
					pLine++;


				int proportional = GetExpression();
				
				HGOSFONT font=0;

				if( *Name!=0 )
				{
					if (proportional)
					{
						gosScript_CreateFont(&font, Name, w, h, true);
					}
					else
					{
						gosScript_CreateFont(&font, Name, w, h, false);
					}
				}
				gosScript_TextSetWrapMode(GOSWRAP_WORD);
				newVariable->Value=(int)font;
			}
			
			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			
			return;
		}
//
// FONT3D definition (ie: font3d fred="fred.bmp" )
//
		case KEY_FONT3D:
		{
			char* Name=pLine;
			#ifdef _DEBUG
			int Exist=GetKeyword();									// Try and match against keywords and variables
			pLine=Name;

			if( Exist==VAR_FONT3D )
			{
				if( LastVariableScope==NewScope )
					ScriptError("font3d redefinition" );			// Already defined as a bitmap at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();											// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_FONT3D;							// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();				// Get array size
	
				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif

			}
//
// Arrays of panes are treated all individually ie: Bitmap[20]="fred.bmp" will load 20 copies of "fred.bmp"
//
			if( newVariable->ArraySize  > 0)
			{
				HGOSFONT3D * f3ds = (HGOSFONT3D*)gos_Malloc(newVariable->ArraySize*sizeof(HGOSFONT3D), gScriptHeap[3]);
				newVariable->pFont3ds=f3ds;

				if (*pLine ==' ')
					pLine++;
				if( *pLine=='=' )
				{
					pLine++;

					char* Name=GetString();							// If string is null, don't load surface
					if (!Name) 
						ScriptError("When instantiating a font, a path or TTF name must be specifiec");
					static char tmp[128];
					if (*pLine ==' ')
						pLine++;
					
					for( int i=0; i<newVariable->ArraySize; i++ )
					{
						sprintf(tmp,Name,i+1);
						HGOSFONT3D fds = gos_LoadFont(Name, 0);
						newVariable->pFont3ds[i]=fds;
					}
				}
				else
				{
					for( int i=0; i<newVariable->ArraySize; i++ )
						newVariable->pFont3ds[i]=0;	
				}
			}
			else
			{
				HGOSFONT3D f3d=0;
				if( *pLine=='=' )
				{
					pLine++;
					char* Name=GetString();							// If string IS null, don't load surface

					if (Name == NULL)
						ScriptError("When instantiating a font, a path or TTF name must be specifiec");
					if (*pLine ==' ')
						pLine++;

					gos_PushCurrentHeap(gScriptHeap[2]);
					f3d = gos_LoadFont(Name, 0); 
					gos_PopCurrentHeap();
				}
				newVariable->pFont3d=f3d;
			}
			
			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			return;
		}

		case KEY_PRINT3D_POSITION:
		{
			#ifdef _DEBUG
			if (*pLine != '=')
				ScriptError("Syntax Error: print3d_position = <var_position>");
			#endif
			pLine++;

			POSITION pos;

			if( *pCurrentLineFlags&1 )
			{
				GetPosition( &pos, *pCurrentLineFlags&2 );
			}
			else
			{
				DWORD pos1=GetPosition( &pos );
				*pCurrentLineFlags=1 + (pos1 ? 2 : 0);
			}

			OBJECT * ptr = pObject;
			if (*ptr->bPosRelative)
			{
				while(ptr)
				{
					pos.x += ptr->Coordinates->x;
					pos.y += ptr->Coordinates->y;
					pos.z += ptr->Coordinates->z;
					if (*ptr->bPosRelative)
						ptr = ptr->pParentObject;
					else
						break;
				}
			}

			gos_TextSetPosition(pos.x, pos.y);

			return;
		}

		case KEY_LPRINT3D_POSITION:
		{
			#ifdef _DEBUG
			if (*pLine != '=')
				ScriptError("Syntax Error: print3d_position = <var_position>");
			#endif
			pLine++;

			POSITION pos;

			if( *pCurrentLineFlags&1 )
			{
				GetPosition( &pos, *pCurrentLineFlags&2 );
			}
			else
			{
				DWORD pos1=GetPosition( &pos );
				*pCurrentLineFlags=1 + (pos1 ? 2 : 0);
			}

			OBJECT * ptr = pObject;
			while(ptr)
			{
				pos.x += ptr->Coordinates->x;
				pos.y += ptr->Coordinates->y;
				pos.z += ptr->Coordinates->z;
				if (*ptr->bPosRelative)
					ptr = ptr->pParentObject;
				else
					break;
			}

			gos_TextSetPosition(pos.x, pos.y);

			return;
		}

		case KEY_PRINT3D_MARGINS:
		{
			#ifdef _DEBUG
			if (*pLine != '=')
				ScriptError("Syntax Error: print3d_margins = <var_cube>");
			#endif
			pLine++;

			*pCurrentLineFlags=GetCube( &g_textMargins, *pCurrentLineFlags );
	
			OBJECT * ptr = pObject;
			if (*ptr->bPosRelative)
			{
				while(ptr)
				{
					g_textMargins.p1.x += ptr->Coordinates->x;
					g_textMargins.p1.y += ptr->Coordinates->y;
					g_textMargins.p2.x += ptr->Coordinates->x;
					g_textMargins.p2.y += ptr->Coordinates->y;
					if (*ptr->bPosRelative)
						ptr = ptr->pParentObject;
					else
						break;
				}
			}

			// do some clipping
			if (g_textMargins.p1.x < 0) g_textMargins.p1.x = 0;
			if (g_textMargins.p2.x < 0) g_textMargins.p2.x = 0;
			if (g_textMargins.p1.y < 0) g_textMargins.p1.y = 0;
			if (g_textMargins.p2.y < 0) g_textMargins.p2.y = 0;
			if (g_textMargins.p1.x >= g_textMargins.p2.x)
				g_textMargins.p2.x = g_textMargins.p1.x+1;
			if (g_textMargins.p1.y >= g_textMargins.p2.y)
				g_textMargins.p2.y = g_textMargins.p1.y+1;

			gos_TextSetRegion(g_textMargins.p1.x, g_textMargins.p1.y, g_textMargins.p2.x, g_textMargins.p2.y);

			return;
		}

		case KEY_LPRINT3D_MARGINS:
		{
			#ifdef _DEBUG
			if (*pLine != '=')
				ScriptError("Syntax Error: lprint3d_margins = <var_cube>");
			#endif
			pLine++;

			GetCube(&g_textMargins);

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

			// do some clipping
			if (g_textMargins.p1.x < 0) g_textMargins.p1.x = 0;
			if (g_textMargins.p2.x < 0) g_textMargins.p2.x = 0;
			if (g_textMargins.p1.y < 0) g_textMargins.p1.y = 0;
			if (g_textMargins.p2.y < 0) g_textMargins.p2.y = 0;

			if (g_textMargins.p1.x >= g_textMargins.p2.x)
				g_textMargins.p2.x = g_textMargins.p1.x+1;
			if (g_textMargins.p1.y >= g_textMargins.p2.y)
				g_textMargins.p2.y = g_textMargins.p1.y+1;

			gos_TextSetRegion(g_textMargins.p1.x, g_textMargins.p1.y, g_textMargins.p2.x, g_textMargins.p2.y);

			return;
		}

		case KEY_PRINT3D_ATTRIBUTES:
		{
			int handle, color, just=0;
			float size;
			bool wrap, prop, bold, italic, NoCodes=0;
			
			if (*pLine++ != '=')
				goto ErrorPrint3D;

			if (GetKeyword() != VAR_FONT3D)
				goto ErrorPrint3D;
			handle = *pLastVariable;

			if (handle == NULL)
				ScriptError("An uninitialized font3d is being passed to print3d_attributes");

			if (*pLine++ != ',')
				goto ErrorPrint3D;
			color = GetExpression();

			if (*pLine++ != ',')
				goto ErrorPrint3D;
			size = FloatGetExpression();

			if (*pLine++ != ',')
				goto ErrorPrint3D;
			wrap = 0!=GetExpression();

			if (*pLine++ != ',')
				goto ErrorPrint3D;
			prop = 0!=GetExpression();

			if (*pLine++ != ',')
				goto ErrorPrint3D;
			bold = 0!=GetExpression();

			if (*pLine++ != ',')
				goto ErrorPrint3D;
			italic = 0!=GetExpression();

			if (*pLine++ == ',')
				just = GetExpression();
			else 
				goto DonePrint3D;

			if (*pLine++ != ',')
				goto DonePrint3D;
			NoCodes = 0!=GetExpression();

DonePrint3D:
			gos_TextSetAttributes( (HGOSFONT3D)handle, color, size, wrap, prop, bold, italic, just, NoCodes );
			return;

ErrorPrint3D:
			ScriptError("Syntax Error: print3d_attributes = <var_font3d font>, <var_int color>, <var_float size>, <var_int wrap>, <var_int proportional>, <var_int bold>, <var_int italic>, [<var_int just>, <var_int DisableEmbeddedCodes>]");

		}

		case KEY_PRINT3D:
		{
			FlushLineBuffer();
			while(1)
			{
				char * str = NULL;
				if( *pLine==' ' )
					pLine++;

				str = GetString();
				
				if( str )
				{
					gos_CacheTextDraw(str,-1);
				}
				else
				{
					int Type=GetKeyword();
					
					if( VAR_STRING==Type )
					{
						gos_CacheTextDraw((char *)*pLastVariable,-1);
					}
					else if( VAR_INT==Type )
					{
						static char tmp[32];
						int Len=sprintf(tmp,"%d",*pLastVariable);
						gos_CacheTextDraw(tmp,Len);
					}
					else if( VAR_FLOAT==Type )
					{
						char precision[64];
						sprintf(precision, "%c.%df", '%', gFloatPrecision);
						static char tmp[32];
						int Len=sprintf(tmp,precision,*((float*)pLastVariable));
						gos_CacheTextDraw(tmp,Len);
					}
					else
					{
						int value = GetExpression();
						static char tmp[32];
						int Len=sprintf(tmp,"%d",value);
						gos_CacheTextDraw(tmp,Len);
					}
				}

				if (*pLine == ' ')
					pLine++;
				if( *pLine!=',' )
					return;

				pLine++;
			}
			return;
		}

		case KEY_CLEARZBUFFER:
		{
			FlushLineBuffer();
			static gos_VERTEX pVertices[4];
		
			// do some clipping
			float x1 = 0;
			float x2 = (float) Environment.screenWidth;
			float y1 = 0;
			float y2 = (float) Environment.screenHeight;
			
		
			memset( pVertices, 0, sizeof(pVertices) );
			pVertices[0].rhw	= 1.0f;
			pVertices[1].rhw	= 1.0f;
			pVertices[2].rhw	= 1.0f;
			pVertices[3].rhw	= 1.0f;
		
			pVertices[0].x		= x1;
			pVertices[0].y		= y1;
			pVertices[0].z      = 0.99999f;
			pVertices[0].argb	= 0x00000000;
		
			pVertices[1].x		= x1;
			pVertices[1].y		= y2;
			pVertices[1].z      = 0.99999f;
			pVertices[1].argb	= 0x00000000;
		
			pVertices[2].x		= x2;
			pVertices[2].y		= y2;
			pVertices[2].z      = 0.99999f;
			pVertices[2].argb	= 0x00000000;
		
			pVertices[3].x		= x2;
			pVertices[3].y		= y1;
			pVertices[3].z      = 0.99999f;
			pVertices[3].argb	= 0x00000000;
		
			gos_SetRenderState( gos_State_Texture, 0 );
			gos_SetRenderState( gos_State_ZWrite, true );
			gos_SetRenderState( gos_State_ZCompare, 0 );
			gos_SetRenderState( gos_State_AlphaMode, gos_Alpha_AlphaInvAlpha );
		
			gos_DrawQuads( pVertices, 4 );
			return;
		}

//
// SOUND definition (ie: sound fred="fred.wav" )
//
		case KEY_SOUND:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();									// Try and match against keywords and variables
			pLine=Name;

			if( Exist==VAR_SOUND )
			{
				if( LastVariableScope==NewScope )
					ScriptError("Sound redefinition" );				// Already defined as a bitmap at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();											// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_SOUND;							// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();				// Get array size

				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif

				newVariable->pValues =(int*)gos_Malloc(sizeof(HGOSAUDIO)*newVariable->ArraySize, gScriptHeap[3]);
				if (*pLine == ' ')
					pLine++;
				char * string= NULL;
				if( *pLine=='=' )
				{
					pLine++;
					string = GetString();
				}
				if (*pLine == ' ')
					pLine++;
				
				int type = 0;
				if (*pLine == ',')
				{
					pLine++;
					type = GetExpression();
					if (type != 0 && type != 1 && type != 2)
						ScriptError("Expected st_cached, st_streamed, st_music");
				}

								
				for( int i=0; i<newVariable->ArraySize; i++ )
				{
					if (string)
					{
						HGOSAUDIO sound = NULL;
						switch(type)
						{
						case 0:
							gosAudio_CreateResource(&sound, gosAudio_CachedFile, string, 0,0,0, true);
							break;
						case 1:
							gosAudio_CreateResource(&sound, gosAudio_StreamedFile, string, 0,0,0, true);
							break;
						case 2:
							gosAudio_CreateResource(&sound, gosAudio_StreamedMusic, string, 0,0,0, true);
							break;
						}
						newVariable->pValues[i]=(int) sound;
					}
					else
					{
						newVariable->pValues[i]=NULL;
					}
				}
			}
			else
			if( *pLine==0 )											// Defined, but no init of a variable
			{
				newVariable->Value=0;
			}
			else
			{
				if( *pLine != '=' )
					ScriptError("Expected 'sound Name = \"file\"'" );	// Bad first character or a reserved keyword
	
				pLine++;

				char* Name=GetString();								// If string is null, don't load surface

				if (!Name)
					ScriptError("Expected \"sound Name = <var_string>\"" );	// Bad first character or a reserved keyword
				
				if (*pLine == ' ')
					pLine++;
				
				int type = 0;
				if (*pLine == ',')
				{
					pLine++;
					type = GetExpression();
					if (type != 0 && type != 1 && type != 2)
						ScriptError("Expected st_cached, st_streamed, st_music");
				}

				HGOSAUDIO sound=0;

				if( *Name!=0 )
				{
					switch(type)
					{
					case 0:
						gosAudio_CreateResource(&sound, gosAudio_CachedFile, Name, 0,0,0, true);
						break;
					case 1:
						gosAudio_CreateResource(&sound, gosAudio_StreamedFile, Name, 0,0,0, true);
						break;
					case 2:
						gosAudio_CreateResource(&sound, gosAudio_StreamedMusic, Name, 0,0,0, true);
						break;
					}
				}

				newVariable->Value=(int)sound;
			}
			
			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			
			return;
		}
//
// String Variables definition (ie: string fred="bite me" )
//

		case KEY_STRING:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();									// Try and match against keywords and variables
			pLine=Name;
			if( Exist==VAR_STRING )
			{
				if( LastVariableScope==NewScope )
					ScriptError("String Variable redefinition" );	// Already defined as an string at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();											// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_STRING;							// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();				// Get array size

				#ifdef _DEBUG
				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				#endif
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif

				newVariable->pValues =(int*)gos_Malloc(sizeof(char*)*newVariable->ArraySize, gScriptHeap[3]);
				char * string= NULL;
				if (*pLine ==' ')
					pLine++;
				if( *pLine=='=' )
				{
					pLine++;
					pLastVariable = NULL;
					string = GetString();
					if (string == NULL && pLastVariable == NULL)
					{
						int val = GetExpression();
						if (val != 0)
							ScriptError("Expected 'string Name = <string> or 0 or NULL'" );	// Bad first character or a reserved keyword
					}
				}
								
				for( int i=0; i<newVariable->ArraySize; i++ )
				{
					if (string)
					{
						newVariable->pValues[i]=(int) gos_Malloc(strlen(string)+1, gScriptHeap[3]);
						memset((void *) newVariable->pValues[i],0,strlen(string)+1);
						memcpy((void *) newVariable->pValues[i],string,strlen(string));
					}
					else
					{
						newVariable->pValues[i]=NULL;
					}
				}
			}
			else
			if( *pLine==0 )											// Defined, but no init of a variable
			{
				newVariable->Value=0;
			}
			else
			{
				#ifdef _DEBUG
				if( *pLine != '=' )
					ScriptError("Expected 'string Name = <string>'" );	// Bad first character or a reserved keyword
				#endif
				pLine++;
				pLastVariable = NULL;
				char* Name=GetString();
				if (Name == NULL && pLastVariable == NULL)
				{
					int val = GetExpression();
					if (val != 0)
						ScriptError("Expected 'string Name = <string> or 0 or NULL'" );	// Bad first character or a reserved keyword
				}
				if (Name)
				{
					newVariable->Value = (int) gos_Malloc(strlen(Name)+1, gScriptHeap[3]);
					memcpy((char *) newVariable->Value, (char *) Name, strlen(Name));
					((char *) newVariable->Value)[strlen(Name)] = 0;
				}
				else
				{
					newVariable->Value = (int) gos_Malloc(4, gScriptHeap[3]);
					((char *) newVariable->Value)[0] = 0;
				}
			}								   
			
			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			
			return;
		}
//
// FLOAT Variables definition (ie: float fred=12.3 )
//
		case KEY_FLOAT:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();
			pLine=Name;
			if( Exist==VAR_FLOAT )
			{
				if( LastVariableScope==NewScope )
					ScriptError("Variable redefinition" );			// Already defined as an INT at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_FLOAT;							// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();				// Get array size

				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif

				float* pFloats=(float*)gos_Malloc(sizeof(int)*newVariable->ArraySize, gScriptHeap[3]);

				newVariable->pfValues=pFloats;

				float Value=0;
				if( *pLine=='=' )
				{
					pLine++;
					Value=FloatGetExpression();
				}
								
				for( int i=0; i<newVariable->ArraySize; i++ )
				{
					newVariable->pfValues[i]=(float)Value;
				}
			}
			else
			{
				if( *pLine==0 )										// Defined, but no init of a variable
				{
					newVariable->fValue=0.0f;
				}
				else
				{
					if( *pLine != '=' )
						ScriptError("Expected 'float Name = value'" );// Bad first character or a reserved keyword
		
					pLine++;

					newVariable->fValue=FloatGetExpression();
				}
			}			

			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			return;
		}

		case KEY_INT:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();
			pLine=Name;
			if( Exist==VAR_INT )
			{
				if( LastVariableScope==NewScope )
					ScriptError("Variable redefinition" );			// Already defined as an INT at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_INT;								// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();				// Get array size

				#ifdef _DEBUG
				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				#endif
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif

				int* pInts=(int*)gos_Malloc(sizeof(int)*newVariable->ArraySize, gScriptHeap[3]);

				newVariable->pValues=pInts;

				int Value=0;
				if( *pLine=='=' )
				{
					pLine++;
					Value=GetExpression();
				}
								
				for( int i=0; i<newVariable->ArraySize; i++ )
				{
					newVariable->pValues[i]=Value;
				}
			}
			else
			{
				if( *pLine==0 )										// Defined, but no init of a variable
				{
					newVariable->Value=0;
				}
				else
				{
					#ifdef _DEBUG
					if( *pLine != '=' )
						ScriptError("Expected 'int Name = value'" );// Bad first character or a reserved keyword
					#endif

					pLine++;

					newVariable->Value=GetExpression();
				}
			}			

			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			return;
		}
//
// BITMAP variable reference (ie: bitmap="new bitmap")
//
		case VAR_BITMAP:
		{
			if (*pLine == ' ')
				pLine++;
			if( *pLastVariable!=0)
			{
				gos_DestroySurface( (HGOSSURFACE*)&(*pLastVariable) );
				*pLastVariable=0;									// Destroy any previous bitmap
			}
			if( *pLine != '=' )
				ScriptError("Expected 'Bitmap = <string> or <var_bitmap>" );		// Bad first character or a reserved keyword

			pLine++;

			long * save = pLastVariable;
			char * Name = NULL;
			int kw = GetKeyword();
			if ( kw == VAR_BITMAP)
			{
				return;
			}
			else
			if ( kw == VAR_STRING)
			{
				Name = (char *)*pLastVariable;
			}
			else
				Name=GetString();									// If string is null, don't load surface
			
			HGOSSURFACE surf=0;
			if (Name == 0)
			{
				ScriptError("Expected 'bitmap = <string> or <var_bitmap>");
			}
			if( *Name!=0 )
			{
				gos_LoadSurface(Name, &surf,1);
			}

			*save=(int)surf;
			return;
		}

//
// MOVIE variable reference (ie: movie="<Name>.avi")
//
		case VAR_MOVIE:
		{
			if (*pLine == ' ')
				pLine++;
			if( *pLastVariable!=0)
			{
				gosVideo_DestroyResource( (HGOSVIDEO*)&(*pLastVariable) );
				*pLastVariable=0;									// Destroy any previous bitmap
			}

			if( *pLine != '=' )
				ScriptError("Expected '<movie var> = \"Name\"'" );		// Bad first character or a reserved keyword
			else
				pLine++;

			long * save = pLastVariable;
			int kw = GetKeyword();
			if ( kw == VAR_MOVIE)
			{
				return;
			}
			pLastVariable = save;
			char* Name=GetString();									// If string is null, don't load surface

			HGOSVIDEO vid=0;

			if( *Name!=0 )
			{
				gosVideo_CreateResource(&vid, Name);
			}

			*save=(int)vid;
			return;
		}

//
// GAF variable reference (ie: gaf="<Name>.gaf")
//
		case VAR_GAF:
		{
			if (*pLine == ' ')
				pLine++;
			if( *pLastVariable!=0)
			{
				gos_DestroyGAFResource( (HGOSGAF*)&(*pLastVariable) );
				*pLastVariable=0;									// Destroy any previous bitmap
			}
			if( *pLine != '=' )
				ScriptError("Expected '<gaf var> = \"Name\"'" );		// Bad first character or a reserved keyword

			pLine++;

			long * save = pLastVariable;
			char * savedpLine = pLine;
			int kw = GetKeyword();
			if ( kw == VAR_GAF)
			{
				return;
			}
			pLine = savedpLine;
			pLastVariable = save;
			char* Name=GetString();									// If string is null, don't load surface
#ifdef _ARMOR
			if (Name && !gos_DoesFileExist(Name))
				ScriptError("Cannot locate the file \"%s\"",Name);
#endif
			pLastVariable = save;
			
			HGOSGAF gaf=0;

			if( Name!=0 )
			{
				gos_CreateGAFResource(&gaf, Name );
			}

			*save=(int)gaf;
			return;
		}

//
// FONT variable reference (ie: font="new bitmap" or font= <font>)
//
		case VAR_FONT:
		{
			if (*pLine == ' ')
				pLine++;
			if( *pLastVariable!=0 )
			{
				gos_DestroySurface( (HGOSSURFACE*)&(*pLastVariable) );
				*pLastVariable=0;									// Destroy any previous bitmap
			}
			
			if( *pLine != '=' )
				ScriptError("Expected 'Bitmap = \"Name\"'" );		// Bad first character or a reserved keyword

			pLine++;

			long * save = pLastVariable;
			int kw = GetKeyword();
			if ( kw == VAR_FONT)
			{
				return;
			}
			pLastVariable = save;
			char* Name=GetString();									// If string is null, don't load surface
			
			HGOSSURFACE surf=0;

			if( *Name!=0 )
			{
				gos_LoadSurface(Name, &surf,1);
			}

			*pLastVariable=(int)surf;
			return;
		}

//
// FONT variable reference (ie: font="new bitmap" or font= <font>)
//
		case VAR_FONT3D:
		{
			if (*pLine == ' ')
				pLine++;
			if( *pLastVariable!=0 )
			{
				gos_DeleteFont( (HGOSFONT3D)(*pLastVariable) );
				*pLastVariable=0;									// Destroy any previous bitmap
			}
			
			if (*pLine == ' ')
				pLine++;

			if( *pLine != '=' )
				ScriptError("Expected '<var_font3d> = \"Name\"'" );		// Bad first character or a reserved keyword

			pLine++;

			char* Name = NULL;
			long * save = pLastVariable;
			int kw = GetKeyword();
			if ( kw == VAR_FONT3D)
			{
				// it would be nice to be able to addref a font!!!
				// but we can't at the moment!
				ScriptError("You can't set one font3d equal to another. Try using a pathname, instead.");
				return;
			}
			else
			if ( kw == VAR_STRING)
			{
				Name = (char *) *pLastVariable;
			}
			else
			{
				Name=GetString();									// If string is null, don't load surface
			}
			
			pLastVariable = save;
			HGOSFONT3D f3d=0;

			if( *Name!=0 )
			{
				if (*pLine == ' ')
					pLine++;
				f3d = gos_LoadFont(Name, 0);
			}

			*pLastVariable=(int)f3d;
			return;
		}


//
// SOUND variable reference (ie: sound="new sound")
//
		case VAR_SOUND:
		{
			if (*pLine == ' ')
				pLine++;
			if( *pLastVariable!=0 )
			{
				gosAudio_DestroyResource( (HGOSAUDIO*)&(*pLastVariable) );
			}
			
			if (*pLine == ' ')
				pLine++;
			if( *pLine != '=' )
				ScriptError("Expected 'sound= \"Name\"'" );		// Bad first character or a reserved keyword

			pLine++;

			long * tmp = pLastVariable;
			char * save = pLine;
			int kw = GetKeyword();
			if (kw == VAR_SOUND)
			{
				HGOSAUDIO sound=0;
				gosAudio_ResourceInfo sri;
				gosAudio_GetResourceInfo( (HGOSAUDIO)*pLastVariable, &sri );
				gosAudio_CreateResource( &sound, sri.eType, sri.lpstrPath );
				*tmp=(int)sound;
				pLastVariable = tmp;
				return;
			}
			else
			if (kw == VAR_STRING)
			{
				pLine = save;
			}
			char* Name=GetString();									// If string is null, don't load sound
			if (Name)
			{
				
			
				if (*pLine == ' ')
					pLine++;
				
				int type = 0;
				if (*pLine == ',')
				{
					pLine++;
					type = GetExpression();
					if (type != 0 && type != 1 && type != 2)
						ScriptError("Expected st_cached, st_streamed, or st_music");
				}

				HGOSAUDIO sound=0;

				if( *Name!=0 )
				{
					switch(type)
					{
					case 0:
						gosAudio_CreateResource(&sound, gosAudio_CachedFile, Name, 0,0,0, true);
						break;
					case 1:
						gosAudio_CreateResource(&sound, gosAudio_StreamedFile, Name, 0,0,0, true);
						break;
					case 2:
						gosAudio_CreateResource(&sound, gosAudio_StreamedMusic, Name, 0,0,0, true);
						break;
					}
				}
				*tmp=(int)sound;
			}
			else
			if (kw==-1 && *pLastVariable != 0)
				ScriptError("Expected 'sound= \"Name\"'" );		// Bad first character or a reserved keyword

			return;
		}

//
// STRING variable reference (ie: string "poo")
//
		case VAR_STRING:
		{
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if( *pLine != '=' )
				ScriptError("Expected 'string= \"text\"'" );		// Bad first character or a reserved keyword
			#endif

			pLine++;

			long * tmp = pLastVariable;

			pLastVariable = NULL;
			char* Name=GetString();
			if (Name == NULL && pLastVariable == NULL)
			{
				int val = GetExpression();
				if (val != 0)
					ScriptError("Expected 'string Name = <string> or 0 or NULL'" );	// Bad first character or a reserved keyword
			}

			pLastVariable = tmp;

			if (*pLastVariable != 0) 
			{
				gos_Free((char *)*pLastVariable );
				*pLastVariable = 0;
				if (Name == 0 || strlen(Name) == 0)
				{
					*pLastVariable = (int) gos_Malloc(1, gScriptHeap[3]);
					((char*)*pLastVariable)[0] = 0;
					return;
				}
			}
			
			if( Name != NULL && strlen(Name) != 0)
			{
				if ( *pLastVariable==0 ) 
					*pLastVariable = (int) gos_Malloc(strlen(Name)+1, gScriptHeap[3]);

				memcpy((char *)*pLastVariable,Name,strlen(Name));
				((char *) *pLastVariable)[strlen(Name)] = 0;
			}

			return;
		}

//
// POSITION variable reference (ie: position=0,0,0)
//
		case VAR_POSITION:
		{
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if( *pLine != '=' )
				ScriptError("Expected '<position>= 0,0,0'" );		// Bad first character or a reserved keyword
			#endif

			pLine++;

			long* temp=pLastVariable;

			*pCurrentLineFlags = GetPosition( (POSITION*)*pLastVariable, *pCurrentLineFlags );

			pLastVariable=temp;

			return;
		}

//
// CUBE variable reference (ie: cube=<pos> to <pos>)
//
		case VAR_CUBE:
		{
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if( *pLine != '=' )
				ScriptError("Expected '<cube var>= <pos> to <pos> or <cube>'" );		// Bad first character or a reserved keyword
			#endif

			pLine++;

			long* temp=pLastVariable;

			*pCurrentLineFlags=GetCube( (CUBE*)*pLastVariable, *pCurrentLineFlags );

			pLastVariable=temp;

			return;
		}

//
// FLOAT Variable reference (ie: fred=bill+2 )
//
		case VAR_FLOAT:
		{
			if (*pLine == ' ')
				pLine++;

			float* pVar=(float *)pLastVariable;

			if( *pLine=='=' )
			{
				pLine++;
				*pVar=(float)FloatGetExpression();
				return;
			}
			if( *(pLine+1)=='=' )
			{
				if( *pLine=='+' )					// var+=			
				{
					pLine+=2;
					*pVar=*pVar+FloatGetExpression();
					return;
				}
				if( *pLine=='-' )					// var-=			
				{
					pLine+=2;
					*pVar=*pVar-FloatGetExpression();
					return;
				}
				if( *pLine=='*' )					// var*=			
				{
					pLine+=2;
					*pVar=*pVar*FloatGetExpression();
					return;
				}
				if( *pLine=='/' )					// var/=			
				{
					pLine+=2;
					*pVar=*pVar/FloatGetExpression();
					return;
				}
			}
			if( *pLine=='+' && *(pLine+1)=='+' )
			{
				*pLastVariable+=1;									// Post increment
				pLine+=2;
				return;
			}
			if( *pLine=='-' && *(pLine+1)=='-' )
			{
				*pLastVariable-=1;									// Post decrement
				pLine+=2;
				return;
			}
			ScriptError("Expected '<var_float> = value'" );		// Bad first character or a reserved keyword
			return;
		}
//
// INT Variable reference (ie: fred=bill+2 )
//
		case VAR_INT:
		{
			if (*pLine == ' ')
				pLine++;

			long* pVar=pLastVariable;
			
			if( *pLine=='=' )
			{
				pLine++;
				*pVar=GetExpression();
				return;
			}

			if( *(pLine+1)=='=' )
			{
				switch( *pLine )
				{
					case '+':
					{
						pLine+=2;
						*pVar=*pVar+GetExpression();
						return;
					}
					case '-':
					{
						pLine+=2;
						*pVar=*pVar-GetExpression();
						return;
					}
					case '*':
					{
						pLine+=2;
						*pVar=*pVar*GetExpression();
						return;
					}
					case '/':
					{
						pLine+=2;
						*pVar=*pVar/GetExpression();
						return;
					}
					case '&':
					{
						pLine+=2;
						*pVar=*pVar&GetExpression();
						return;
					}
					case '|':
					{
						pLine+=2;
						*pVar=*pVar|GetExpression();
						return;
					}
					case '^':
					{
						pLine+=2;
						*pVar=*pVar^GetExpression();
						return;
					}
					case '%':
					{
						pLine+=2;
						*pVar=*pVar%GetExpression();
						return;
					}
				}
			}
			if( *pLine=='+' && *(pLine+1)=='+' )
			{
				*pLastVariable+=1;									// Post increment
				pLine+=2;
				return;
			}
			if( *pLine=='-' && *(pLine+1)=='-' )
			{
				*pLastVariable-=1;									// Post decrement
				pLine+=2;
				return;
			}
			if( *pLine=='>' && *(pLine+1)=='>' && *(pLine+2)=='=' )	// var>>=			
			{
				pLine+=3;
				*pVar=*pVar>>GetExpression();
				return;
			}
			if( *pLine=='<' && *(pLine+1)=='<' && *(pLine+2)=='=' )	// var<<=			
			{
				pLine+=3;
				*pVar=*pVar<<GetExpression();
				return;
			}
			ScriptError( "Invalid syntax" );
			return;
		}
//
// Object definition ( object StartButton=Button )
//
		case KEY_OBJECT:
		{
			if (NewScope == SCOPE_LOCAL)
				ScriptError("Locally defined <VAR_OBJECTS> are meaningless. Predeclare it in GUI_CREATE first");
			char* Name=pLine;
			gIsDeclaration = true;
			int Exist=GetKeyword();									// Try and match against keywords and variables

			if( Exist==VAR_OBJECT  && LastVariableScope==NewScope )
				ScriptError("Object redefinition" ); // Already defined as an OBJECT?
			else pLine = Name;

			int Length=VariableLength();
			gIsDeclaration = false;

			if( *pLine=='[' )
			{
				VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

				newVariable->Type=VAR_OBJECT;							// Create new variable
				newVariable->ArraySize=0;								// Not an array element
				newVariable->NameLength=(BYTE)Length;
				memcpy( newVariable->Name, Name, Length );
				newVariable->Name[Length]=0;
	
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();				// Get array size

				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif

				newVariable->pValues =(int*)gos_Malloc(sizeof(OBJECT*)*newVariable->ArraySize, gScriptHeap[3]);

				if (*pLine == ' ')
					pLine++;
				FUNCTION * func = NULL;
				if( *pLine=='=' )
				{
					pLine++;
					func = GetFunction(pScript);
				}

				AddVariable( pObject, NewScope, newVariable);
								
				for( int i=0; i<newVariable->ArraySize; i++ )
				{
					OBJECT* NewObject=(OBJECT*)gos_Malloc(sizeof(OBJECT)+Length, gScriptHeap[3]);
					NewObject->bActive = true;
					NewObject->pParentObject=pObject;
					newVariable->pValues[i]=(int)NewObject;
					NewObject->pNext=pScript->pListofObjects;
					NewObject->pScript=pScript;
					NewObject->pParentVariable = newVariable;
		
					NewObject->bInFocus = false;
					NewObject->LastRan = (float) gos_GetElapsedTime(1);
					NewObject->bMouseInRegion = false;
					NewObject->bAddToDeathRow = false;
		
					NewObject->bPosRelative = false;
					NewObject->dwBlockingFlags = 0;
					NewObject->pFunction=func;
					NewObject->pVariables=0;
					NewObject->NameLength=Length;
					memcpy( NewObject->Name, Name, Length );
					NewObject->Name[Length]=0;
					NewObject->dwAvailIME = 0;
					NewObject->dwIMEState = 0;

		
					pScript->pListofObjects=NewObject;						// Add to list of objects
		
					CreateDefaultMemberVariables(NewObject, (int) *pScript->pMainObject->Priority);

					if (func)
						SendScriptMessage( NewObject, MSG_GUI_CREATE );		// send GUI_CREATE to object
				}
				return;
			}

			if (*pLine == ' ')
				pLine++;
			FUNCTION * func = NULL;
			if( *pLine=='=' )
			{
				pLine++;
				if (*pLine == ' ')
					pLine++;
				func = GetFunction(pScript);
			}

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);
			newVariable->Type=VAR_OBJECT;							// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			OBJECT* NewObject=(OBJECT*)gos_Malloc(sizeof(OBJECT)+Length, gScriptHeap[3]);
			NewObject->bActive = true;
			NewObject->pNext=pScript->pListofObjects;
			NewObject->pScript=pScript;
			NewObject->pParentObject=pObject;
			NewObject->pParentVariable = newVariable;
			NewObject->pParentObject=pObject;

			newVariable->Value = (int) NewObject;

			NewObject->bInFocus = false;
			NewObject->LastRan = (float) gos_GetElapsedTime(1);
			NewObject->AlwaysInRegion = false;
			NewObject->bMouseInRegion = false;
			NewObject->bAddToDeathRow = false;
			NewObject->bPosRelative = false;
			NewObject->dwBlockingFlags = 0;
			NewObject->dwAvailIME = 0;
			NewObject->dwIMEState = 0;


			NewObject->pFunction=func;
			NewObject->pVariables=0;
			NewObject->NameLength=Length;
			memcpy( NewObject->Name, Name, Length );
			NewObject->Name[Length]=0;

			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			pScript->pListofObjects=NewObject;						// Add to list of objects

			CreateDefaultMemberVariables(NewObject, (int) *pScript->pMainObject->Priority);

			if (func)
				SendScriptMessage( NewObject, MSG_GUI_CREATE );		// send GUI_CREATE to object

			return;
		}
//
// Object reference ( StartButton=DisabledButton )
//
		case VAR_OBJECT:
		{
			if (*pLine == ' ')
				pLine++;
			if( *pLine != '=' )
				ScriptError("Expected '<var_object> = function'" );	// Bad first character or a reserved keyword

			pLine++;

			OBJECT * NewObject = (OBJECT *)*pLastVariable;
			if (NewObject->pFunction)
			{
				// kill previous incarnation!
				SendScriptMessage( NewObject, MSG_GUI_DESTROY );
				NewObject->bAddToDeathRow = true;
				// ready to build a new one!
				VARIABLE * var = NewObject->pVariables;
				while(var)
				{
					VARIABLE * var2 = var->pNext;
					if (var->Type == VAR_OBJECT)
					{
						if (var->ArraySize == 0)
						{
							((OBJECT*)var->Value)->bAddToDeathRow = true;
							var->Value = 0;
						}
						else
						{
							for(int i=0; i < var->ArraySize; i++)
							{
								((OBJECT*)var->pValues[i])->bAddToDeathRow = true;
								var->pValues[i] = 0;
							}
						}
					}
					DeleteVariable(var);
					var = var2;
				}
				NewObject->pVariables = NULL;

				CreateDefaultMemberVariables( NewObject, (int) *pScript->pMainObject->Priority );
			}

			NewObject->bInFocus = false;
			NewObject->LastRan = (float) gos_GetElapsedTime(1);
			NewObject->bMouseInRegion = false;
			NewObject->bAddToDeathRow = false;
			NewObject->dwAvailIME = 0;
			NewObject->dwIMEState = 0;

			NewObject->pFunction=GetFunction(NewObject->pScript);
			if (NewObject->pFunction)
				SendScriptMessage( NewObject, MSG_GUI_CREATE );		// send GUI_CREATE to object
			return;
		}
//
// Spew command
//
		case KEY_SPEW:
		{
#ifdef LAB_ONLY
			char szFormat[32]; // jcem
			strcpy(szFormat, "");

			static char tmp[1024];
			int len = 0;
			tmp[0] = 0;
			while(1)
			{
				char * save = pLine;
				if( *pLine==' ' )
					pLine++;

				if( *pLine=='"') {
					const char* pcsz = GetString();
					if ((pcsz[0] == '%') && (pcsz[1] != '%')) {
						strcpy(szFormat, &pcsz[1]);
					} else {
						if ((pcsz[0] == '%') && (pcsz[1] == '%'))
							pcsz++;
						len += sprintf(&tmp[len],"%s ", pcsz);
					}
				} else
				{
#ifdef _DEBUG
					// disable cache for temporary...
					DWORD index=(int)pLine&(MAXCACHE-1);
					KeywordCache[index].Address=NULL;
#endif // _DEBUG
					int Type=GetKeyword();

					if (Type == -1)
					{
						char* string = GetString();
						if (string)
							len += sprintf(&tmp[len],"%s ",string);
						else
							len += sprintf(&tmp[len],"%.2f ",FloatGetExpression());
					}
					else
					if( VAR_STRING==Type )
						len += sprintf(&tmp[len],"%s ",(char *) *pLastVariable);
					else
					if (VAR_POSITION==Type)
						len += sprintf(&tmp[len],"{%d, %d, %d} ",((POSITION *)*pLastVariable)->x,((POSITION *)*pLastVariable)->y,((POSITION *)*pLastVariable)->z);
					else
					if( VAR_INT==Type )
					{
						pLine = save;

						if (szFormat[0] == 'x') {
							len += sprintf(&tmp[len],"%x ",GetExpression());
						} else {
						len += sprintf(&tmp[len],"%d ",GetExpression());
					}
					}
					else
					if( VAR_FLOAT==Type )
					{
						pLine = save;
						char precision[64];
						sprintf(precision, "%c.%df ", '%', gFloatPrecision);
						len += sprintf(&tmp[len],precision,FloatGetExpression());
					}
					else
					if(VAR_PANE==Type)
					{
						len += sprintf(&tmp[len],"(%s(%s), h:%d,w:%d) ",((char *)pLastVariableObject->Name), ((gos_Pane *) *pLastVariable)->GetSurfacePath(), ((gos_Pane *) *pLastVariable)->GetHeight(), ((gos_Pane *) *pLastVariable)->GetWidth());
					}
					else
					if (VAR_CUBE==Type)
					{
						len += sprintf
							(
								&tmp[len],"(%d,%d,%d to %d,%d,%d) ",
								((CUBE *)*pLastVariable)->p1.x, 
								((CUBE *)*pLastVariable)->p1.y, 
								((CUBE *)*pLastVariable)->p1.z, 
								((CUBE *)*pLastVariable)->p2.x, 
								((CUBE *)*pLastVariable)->p2.y, 
								((CUBE *)*pLastVariable)->p2.z
							);
					}
					else
						ScriptError("Cannot resolve variables in spew statement");
					strcpy(szFormat, "");
				}
				if( *pLine == ' ')
					pLine++;
				if( *pLine!=',' )
				{
					ScriptSpewOutput(tmp);
					return;
				}

				pLine++;
			}
#else
			break;
#endif
		}
//
// Preincrement (++variable)
//
		case KEY_INC:
		{
			if( VAR_INT!=GetKeyword() )
				ScriptError("Syntax error, '++int' expected" );

			*pLastVariable+=1;										// Save pointer to value
			return;
		}
//
// Predecrement (--variable)
//
		case KEY_DEC:
		{
			if( VAR_INT!=GetKeyword() )
				ScriptError("Syntax error, '--int' expected" );

			*pLastVariable-=1;										// Save pointer to value
			return;
		}

// script_run <string>
		case KEY_SCRIPT_RUN:
		{
			if(*pLine == ' ')
				pLine++;
			int Exist=GetKeyword();									// Try and match against keywords and variables
			char * string = NULL; 
			if( Exist==VAR_STRING )
			{
				string = (char *) *pLastVariable;
			}
			else
			{
				string = GetString();
			}

			if(*pLine == ' ')
				pLine++;

			if (*pLine != ',')
				ScriptError("Expecting ','");
			else
				pLine++;

			if(*pLine == ' ')
				pLine++;

			int priority = GetExpression();
			gosScript_ExecuteScript((char *)string, priority, (void *)pScript->Instance);
			return;
		}
// script_end <string>
		case KEY_SCRIPT_END:
		{
			if(*pLine == ' ')
				pLine++;
			char * string = NULL; 
			string = GetString();
			if (string == NULL)
			{
				if (*pLine == 0)
				{
					// kill the current script!
					pScript->bAddToDeathRow = true;
					return;
				}
				else
				{
					int kw = GetKeyword();
					if (kw !=VAR_OBJECT && kw != VAR_INT)
						ScriptError("Syntax Error: script_end <var_string>, <var_int>, or <var_object>)");
					else
					{
						OBJECT * ptr = (OBJECT *) *pLastVariable;
						SCRIPT * scr=pListofScripts;
						while( scr )
						{
							OBJECT * mo = scr->pMainObject;
							if (mo == ptr)
							{
								if ( (*pScript->pMainObject->Priority & 0x2000) && scr != pScript)
									ScriptError("Modal scripts cannot end scripts other than themselves");
								scr->bAddToDeathRow = true;
								return;
							}
							scr=scr->pNext;
						}
						STOP(("script_end could not find an main object called \"%s\"", ptr->Name));
					}
				}
			}
			else
			{
				int instance = -1;
				if( *pLine == ' ' )
					pLine++;
				if( *pLine == ',')
				{
					pLine++;
					instance = GetExpression();
				}

				SCRIPT * scr=pListofScripts;
				while( scr )
				{
					FILENAME * fn = scr->pFileNames;
					while( fn)
					{
						if (stricmp(fn->FileName,string) == 0 && (scr->Instance == instance || instance == -1))
						{

							if ((*pScript->pMainObject->Priority & 0x2000) && scr != pScript)
								ScriptError("Modal scripts cannot end scripts other than themselves");
							scr->bAddToDeathRow = true;
							return;
						}
						fn = fn->pNext;
					}
					scr=scr->pNext;
				}
			}
			ScriptError("Couldn't script_end script \"%s\"",string);
		}
		case KEY_SCRIPT_PAUSE:
		{
			char * string = NULL;
			int pauseType = 2;
			
			if(*pLine == ' ')
				pLine++;
			
			int Exist=GetKeyword();									// Try and match against keywords and variables
			int instance = -1;
			
			if( Exist==VAR_STRING )
				string = (char *) *pLastVariable;
			else
			if ( Exist==VAR_OBJECT || Exist == VAR_INT)
			{
				if (*pLastVariable == 1 || *pLastVariable == 2)
				{
					SendScriptMessage( pScript->pMainObject, MSG_GUI_PAUSE );
					pScript->dwPaused = *pLastVariable;
					SPEW((GROUP_SCRIPTS,"Pausing script called '%s'", pScript->pFileNames));
					return;
				}

				if( *pLine == ',' )
					pLine++;
				if( *pLine == ' ' )
					pLine++;
				pauseType = GetExpression();
				if( *pLine == ' ' )
					pLine++;
				if( *pLine == ',')
				{
					pLine++;
					instance = GetExpression();
				}

				OBJECT * ptr = (OBJECT *) *pLastVariable;
				SCRIPT * scr=pListofScripts;
				while( scr )
				{
					OBJECT * mo = scr->pMainObject;
					if (mo == ptr && instance == -1 || instance == scr->Instance)
					{
						SendScriptMessage( scr->pMainObject, MSG_GUI_PAUSE );
						scr->dwPaused = pauseType;
						SPEW((GROUP_SCRIPTS,"Pausing script '%s'",scr->pMainObject->Name));
						return;
					}
					scr=scr->pNext;
				}
				STOP(("script_pause could not find an main object called \"%s\"", ptr->Name));
			}

			else
			{
				string = GetString();
			}

			if (*pLine == ' ')
				pLine++;
			if (string != NULL && *pLine == ',')
			{
				if( *pLine == ',' )
					pLine++;
				if( *pLine == ' ' )
					pLine++;
				pauseType = GetExpression();
				if( *pLine == ' ' )
					pLine++;
				if( *pLine == ',')
				{
					pLine++;
					instance = GetExpression();
				}
			}
				
			if (string == NULL)
			{
				SendScriptMessage( pScript->pMainObject, MSG_GUI_PAUSE );
				pScript->dwPaused = pauseType;
				SPEW((GROUP_SCRIPTS,"Pausing script called '%s'", pScript->pFileNames));
				return;
			}

			SCRIPT * scr=pListofScripts;

			while( scr )
			{
				FILENAME * fn = scr->pFileNames;
				while( fn)
				{
					if ((instance == -1 || instance == scr->Instance) && (stricmp(fn->FileName,string) == 0 || stricmp(fn->LongFileName,string) == 0) )
					{
						SendScriptMessage( scr->pMainObject, MSG_GUI_PAUSE );
						scr->dwPaused = pauseType;
						SPEW((GROUP_SCRIPTS,"Pausing script called '%s'",string));
						return;
					}
					fn = fn->pNext;
				}
				scr=scr->pNext;
			}
			ScriptError("Couldn't script_pause script %s",string);
		}
		case KEY_SCRIPT_CONTINUE:
		{
			if(*pLine == ' ')
				pLine++;
			int instance = -1;
			int Exist=GetKeyword();									// Try and match against keywords and variables
			char * string = NULL; 
			if( Exist==VAR_STRING )
			{
				string = (char *) *pLastVariable;
			}
			else
			if ( Exist==VAR_OBJECT || Exist == VAR_INT)
			{

				if( *pLine == ' ' )
					pLine++;
				if( *pLine == ',')
				{
					pLine++;
					instance = GetExpression();
				}

				OBJECT * ptr = (OBJECT *) *pLastVariable;
				SCRIPT * scr=pListofScripts;
				while( scr )
				{
					OBJECT * mo = scr->pMainObject;
					if (mo == ptr && instance == -1 || instance == scr->Instance)
					{
						scr->dwPaused = 0;
						SendScriptMessage( scr->pMainObject, MSG_GUI_PAUSE );
						SPEW((GROUP_SCRIPTS,"Continuing script called '%s'",string));
						SendScriptMessage( scr->pMainObject, MSG_GUI_CONTINUE );
						return;
					}
					scr=scr->pNext;
				}
				STOP(("script_continue could not find an main object called \"%s\"", ptr->Name));
			}
			else
			{
				string = GetString();
			}

			SCRIPT * scr=pListofScripts;


			if( *pLine == ' ' )
				pLine++;

			if (*pLine == ',')
			{
				// an instance was specified
				instance = GetExpression();
				pLine++;
			}

			while( scr )
			{
				FILENAME * fn = scr->pFileNames;
				while( fn)
				{
					if ((instance == -1 || scr->Instance == instance) && (stricmp(fn->FileName,string) == 0 || stricmp(fn->LongFileName,string) == 0) )
					{
						scr->dwPaused = 0;
						SPEW((GROUP_SCRIPTS,"Continuing script called '%s'",string));
						SendScriptMessage( scr->pMainObject, MSG_GUI_CONTINUE );
						return;
					}
					fn = fn->pNext;
				}
				scr=scr->pNext;
			}
			ScriptError("Couldn't script_continue script %s",string);
		}
		case KEY_BLIT:
		{
			int kw = GetKeyword();
			if( VAR_BITMAP != kw && VAR_GAF != kw  && VAR_MOVIE != kw)
				ScriptError("Syntax error, blit <var_bitmap, var_movie,  or var_gaf>[<var_cube>], <var_pos> on <var_bitmap or var_pane>" );
			
			HGOSSURFACE surf;
			if (kw == VAR_BITMAP)
			{
				surf=(HGOSSURFACE)*pLastVariable;
			}
			else
			if (kw == VAR_MOVIE)
			{
				HGOSVIDEO vid = (HGOSVIDEO)*pLastVariable;
				gosVideo_ResourceInfo gv_ri;
				gosVideo_GetResourceInfo(vid, &gv_ri );
				gos_CreateMemorySurface(&surf,gv_ri.lpData,gv_ri.dwWidth,gv_ri.dwHeight,gv_ri.dwPitch);
			}
			else
			{
				HGOSGAF gaf = (HGOSGAF)*pLastVariable;
				surf=gos_GetSurface(gaf);
			}


			if( surf )												// Ignore blit if bitmap is NULL
			{
				if(*pLine == '(')
				{
					pLine++;
					if (*pLine == ' ')
						pLine++;
					CUBE cube;
					long * pLast = pLastVariable;

					*pCurrentLineFlags=GetCube( &cube, *pCurrentLineFlags );

					pLastVariable = pLast;
					if (*pLine == ' ')
						pLine++;
					if (*pLine != ')')
						ScriptError("Syntax error, blit <var_bitmap, var_movie,  or var_gaf>[<var_cube>], <var_pos> on <var_bitmap or var_pane>" );
					else
						pLine++;

					if (*pLine == ' ')
						pLine++;
					if( *pLine!=',' )
						ScriptError("Syntax error, blit <var_bitmap, var_movie,  or var_gaf>[<var_cube>], <var_pos> on <var_bitmap or var_pane>" );
					else
						pLine++;

					if (*pLine == ' ')
						pLine++;

					POSITION Position;
					GetPosition( &Position );

					if (*pLine == ' ')
						pLine++;
					if (*pLine != 'o')
					{
						ScriptError("Syntax error, blit <var_bitmap, var_movie,  or var_gaf>[<var_cube>], <var_pos> on <var_bitmap or var_pane>" );
					}
					else
					{
						pLine++;
						if (*pLine != 'n')
							ScriptError("Syntax error, blit <var_bitmap, var_movie,  or var_gaf>[<var_cube>], <var_pos> on <var_bitmap or var_pane>" );
						else
							pLine++;
						int kw2 = GetKeyword();
						if (kw2 != VAR_BITMAP && kw2 != VAR_PANE)
							ScriptError("Syntax error, blit <var_bitmap, var_movie,  or var_gaf>[<var_cube>], <var_pos> on <var_bitmap or var_pane>" );

						if (kw2 == VAR_BITMAP)
						{
							gos_BlitSurface( &cube, surf, Position.x, Position.y, (HGOSSURFACE) *pLastVariable );
						}
						else
						{
							if ( !((gos_Pane*) *pLastVariable) )
								ScriptError("Attempt to blit onto an uninitialized pane");

							if (!  ((gos_Pane*) *pLastVariable)->GetSurface())
								ScriptError("You cannot blit to a non-is_volatile pane");
							gos_BlitSurface( &cube, surf, Position.x, Position.y, ((gos_Pane*) *pLastVariable)->GetSurface() );
						}
					}

					return;
				}
				else
				if( *pLine!=',' )
					ScriptError("Syntax error, blit <var_bitmap, var_movie,  or var_gaf>[<var_cube>], <var_pos> on <var_bitmap or var_pane>" );

				pLine++;
				POSITION Position;
				GetPosition( &Position );

				if (*pLine == ' ')
					pLine++;
				if (*pLine != 'o')
				{
					ScriptError("Syntax error, blit <var_bitmap, var_movie,  or var_gaf>[<var_cube>], <var_pos> on <var_bitmap or var_pane>" );
				}
				else
				{
					pLine++;
					if (*pLine != 'n')
						ScriptError("Syntax error, blit <var_bitmap, var_movie,  or var_gaf>[<var_cube>], <var_pos> on <var_bitmap or var_pane>" );
					else
						pLine++;
					if (*pLine == ' ')
						pLine++;
					int kw2 = GetKeyword();
					if (kw2 == VAR_PANE)
					{
						if (!((gos_Pane*) *pLastVariable)->GetSurface())
						{
							ScriptError("You cannot blit to a non-votalile pane");
						}
						gos_BlitSurface( NULL, surf, Position.x, Position.y, ((gos_Pane*) *pLastVariable)->GetSurface() );
						if (kw == VAR_MOVIE) gos_DestroySurface(&surf);
						return;
					}
					if (kw2 != VAR_BITMAP)
						ScriptError("Syntax error, blit <var_bitmap or var_gaf>[<var_cube>], <var_pos> on <var_bitmap>" );

					gos_BlitSurface( NULL, surf, Position.x, Position.y, (HGOSSURFACE) *pLastVariable );
					if (kw == VAR_MOVIE) gos_DestroySurface(&surf);
				}

			}
			return;
		}
		case KEY_BITMAPCREATE:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();									// Try and match against keywords and variables
			pLine=Name;

			if( Exist==VAR_BITMAP )
			{
				if( LastVariableScope==NewScope )
					ScriptError("Bitmap redefinition" );			// Already defined as a bitmap at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();											// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_BITMAP;							// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();				// Get array size
	
				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif

			}
//
// Arrays of bitmaps are treated all individually ie: Bitmap[20]="fred.bmp" will load 20 copies of "fred.bmp"
//
			if( newVariable->ArraySize  > 0)
			{
				HGOSSURFACE* surf = (HGOSSURFACE*)gos_Malloc(newVariable->ArraySize*sizeof(HGOSSURFACE), gScriptHeap[3]);
				newVariable->pSurfaces=surf;

				if( *pLine=='=' )
				{
					pLine++;
					POSITION dim;
					GetPosition(&dim);
					
#ifdef LAB_ONLY
						if (dim.x == 0)
							ScriptError("Cannot create a bitmap with a width of 0");
						if (dim.y == 0)
							ScriptError("Cannot create a bitmap with a height of 0");
#endif
					for( int i=0; i<newVariable->ArraySize; i++ )
					{
						HGOSSURFACE surf=0;
						gos_CreateSurface(&surf, dim.x, dim.y);
						newVariable->pSurfaces[i]=surf;
					}
				}
				else
					ScriptError("No dimensions supplied for bitmap creation");
			}
			else
			{
				HGOSSURFACE surf=0;
				if( *pLine=='=' )
				{
					pLine++;
					POSITION dim;
					GetPosition(&dim);
#ifdef LAB_ONLY
					if (dim.x == 0)
						ScriptError("Cannot create a bitmap with a width of 0");
					if (dim.y == 0)
						ScriptError("Cannot create a bitmap with a height of 0");
#endif
					gos_CreateSurface(&surf, dim.x, dim.y);
					newVariable->Surface=surf;
				}
				else
					ScriptError("No dimensions supplied for bitmap creation");
			}
			
			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			return;
		}

		case KEY_ASSIGN:
			{
				int channel = GetExpression();
				while(*pLine == ' ')
					pLine++;
				if (*pLine != ',')
					ScriptError("Syntax: Assign: <var_int channel>, <var_sound snd>");
				pLine++;
				int kw = GetKeyword();

				if (kw == VAR_SOUND)
				{
					HGOSAUDIO snd = (HGOSAUDIO) *pLastVariable;
					if (!snd)
						ScriptError("Attempt to assign undefined sound to channel");
					else
						gosAudio_AssignResourceToChannel(channel, snd);
				}
				else
				{
					int expr = GetExpression();
					if (expr != 0)
						ScriptError("Syntax: Assign: <var_int channel>, <var_sound snd>");
					else
						gosAudio_AssignResourceToChannel(channel, 0);
				}
				return;
			}
//
// play command   syntax: play <sound>, <channel#>
//
		case KEY_PLAY:
		{
			int kw = GetKeyword();

			if (kw != VAR_SOUND && kw != VAR_MOVIE && kw != VAR_INT && kw != VAR_PANE)
			{
				int exp = GetExpression();
				gosAudio_SetChannelPlayMode(exp, gosAudio_PlayOnce);
			}

			if (kw == VAR_SOUND)
			{
				HGOSAUDIO sound=(HGOSAUDIO)*pLastVariable;

				if( sound )												// If the value is null, play nothing
				{
					if( *pLine!=',' )
						ScriptError("Syntax error, play <sound>, <channel#>" );

					pLine++;
		
					int exp = GetExpression();
				
					gosAudio_AssignResourceToChannel(exp, sound);
					gosAudio_SetChannelPlayMode(exp,gosAudio_PlayOnce);
				}
			}
			else
			if (kw == VAR_INT)
			{
				int channel = *pLastVariable;
				gosAudio_SetChannelPlayMode(channel, gosAudio_PlayOnce);
			}
			else
			if (kw == VAR_MOVIE)
			{
				// its a movie
				HGOSVIDEO vid = (HGOSVIDEO) *pLastVariable;
				gosVideo_SetPlayMode( vid,gosVideo_PlayOnceHold );
			}
			else
			if (kw == VAR_PANE)
			{
				gos_Pane * p = (gos_Pane*) *pLastVariable;
				if (!p->hVideo)
					ScriptError("That pane does render a movie");
				else
					p->Play();
			}
			return;
		}
//
// loop command   syntax: loop <sound>, <channel#>
//
		case KEY_LOOP:
		{
			int kw = GetKeyword();

			if (kw != VAR_SOUND && kw != VAR_MOVIE && kw != VAR_INT && kw != VAR_PANE)
			{
				int exp = GetExpression();
				gosAudio_SetChannelPlayMode(exp, gosAudio_Loop);
			}

			if (kw == VAR_SOUND)
			{
				HGOSAUDIO sound=(HGOSAUDIO)*pLastVariable;

				if( sound )												// If the value is null, play nothing
				{
					if( *pLine!=',' )
						ScriptError("Syntax error, loop <var_movie or var_sound>, <channel#>" );

					pLine++;
		
					int exp = GetExpression();
				
					gosAudio_AssignResourceToChannel(exp, sound);
					gosAudio_SetChannelPlayMode(exp,gosAudio_Loop);
				}
			}
			else
			if (kw == VAR_INT)
			{
				int channel = *pLastVariable;
				gosAudio_SetChannelPlayMode(channel, gosAudio_Loop);
			}
			else
			if (kw == VAR_MOVIE)
			{
				// its a movie
				HGOSVIDEO vid = (HGOSVIDEO) *pLastVariable;
				gosVideo_SetPlayMode(vid, gosVideo_Loop);
			}
			else
			if (kw == VAR_PANE)
			{
				gos_Pane * p = (gos_Pane*) *pLastVariable;
				if (!p->hVideo)
					ScriptError("That pane does render a movie");
				else
					p->Loop();
			}
			return;
		}
//
// line command   syntax: drawline <x1>,<y1> to <x1>,<y1>
//
		case KEY_LINE:
		{
			POSITION position1, position2;
			
			if( *pCurrentLineFlags&1 )
			{
				GetPosition( &position1, *pCurrentLineFlags&2 );

				pLine+=2;
				if( *pLine==' ' )
					pLine++;

				GetPosition( &position2, *pCurrentLineFlags&4 );

				ScriptDrawLine(position1.x, position1.y, position2.x, position2.y, g_scriptLineColor);
						}
			else
			{
				DWORD pos1=GetPosition( &position1 );

				if( *pLine!='t' && *(pLine+1)=='o' )
				{
					ScriptError("Syntax error: drawline <x1>,<y1> to <x1>,<y1>" );
				}
				pLine+=2;
				if( *pLine==' ' )
					pLine++;

				DWORD pos2=GetPosition( &position2 );

				ScriptDrawLine(position1.x, position1.y, position2.x, position2.y, g_scriptLineColor);
			
				*pCurrentLineFlags=1 + (pos1 ? 2 : 0) + (pos2 ? 4 : 0);
			}
			return;
		}

//
// line command   syntax: drawline <x1>,<y1> to <x1>,<y1>
//
		case KEY_LLINE:
		{
			CUBE cube;
			memset(&cube, 0, sizeof(cube));

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

			POSITION position1, position2;
			
			if( *pCurrentLineFlags&1 )
			{
				GetPosition( &position1, *pCurrentLineFlags&2 );

				pLine+=2;
				if( *pLine==' ' )
					pLine++;

				GetPosition( &position2, *pCurrentLineFlags&4 );

				ScriptDrawLine(cube.p1.x + position1.x, cube.p1.y + position1.y, cube.p1.x + position2.x, cube.p1.y + position2.y, g_scriptLineColor);
			}
			else
			{
				DWORD pos1=GetPosition( &position1 );

				if( *pLine!='t' && *(pLine+1)=='o' )
				{
					ScriptError("Syntax error: ldrawline <x1>,<y1> to <x1>,<y1>" );
				}
				pLine+=2;
				if( *pLine==' ' )
					pLine++;

				DWORD pos2=GetPosition( &position2 );

				ScriptDrawLine(cube.p1.x + position1.x, cube.p1.y + position1.y, cube.p1.x + position2.x, cube.p1.y + position2.y, g_scriptLineColor);
			
				*pCurrentLineFlags=1 + (pos1 ? 2 : 0) + (pos2 ? 4 : 0);
			}
			return;
		}

//
// Kill an object
//
		case KEY_KILL:
		{
			if(*pLine == ' ')
				pLine++;
			int key = GetKeyword();
			if (key != VAR_OBJECT)
			{
				ScriptError("syntax error, kill was expecting an object as a argument");
			}

			OBJECT *NewObject =((OBJECT *) *pLastVariable);
			if (NewObject->pFunction)
			{
				// kill previous incarnation!
				SendScriptMessage( NewObject, MSG_GUI_DESTROY );
				// ready to build a new one!
				VARIABLE * var = NewObject->pVariables;
				while(var)
				{
					VARIABLE * var2 = var->pNext;
					if (var->Type == VAR_OBJECT)
					{
						if (var->ArraySize == 0)
							((OBJECT*)var->Value)->bAddToDeathRow = true;
						else
						{
							for(int i=0; i < var->ArraySize; i++)
								((OBJECT*)var->pValues[i])->bAddToDeathRow = true;
						}

					}
					DeleteVariable(var);
					var = var2;
				}
				NewObject->pVariables = NULL;

				CreateDefaultMemberVariables( NewObject, (int) *pScript->pMainObject->Priority );

			}
			NewObject->pFunction = 0;
			return;
		}
// random
		case KEY_RANDOM:
		{
			return;
		}
		case KEY_DEBUG:
		{
#if defined(_DEBUG)
			PAUSE(("READY TO DEBUG"));
#endif
			return;
		}

		case KEY_PANE:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();									// Try and match against keywords and variables
			pLine=Name;

			if( Exist==VAR_PANE )
			{
				if( LastVariableScope==NewScope )
					ScriptError("Pane redefinition" );				// Already defined as a bitmap at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );		// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();											// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_PANE;							// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();				// Get array size
	
				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif

			}
//
// Arrays of panes are treated all individually ie: Bitmap[20]="fred.bmp" will load 20 copies of "fred.bmp"
//
			if( newVariable->ArraySize  > 0)
			{
				gos_Pane ** panes = (gos_Pane**)gos_Malloc(newVariable->ArraySize*sizeof(gos_Pane*), gScriptHeap[3]);
				newVariable->pPanes=panes;

				if (*pLine ==' ')
					pLine++;
				if( *pLine=='=' )
				{
					pLine++;

					char* Name=GetString();							// If string is null, don't load surface
					static char tmp[128];
					for( int i=0; i<newVariable->ArraySize; i++ )
					{
						gos_Pane * pane=0;
						sprintf(tmp,Name,i+1);
						newVariable->pPanes[i]=pane;
					}
				}
				else
				{
					for( int i=0; i<newVariable->ArraySize; i++ )
						newVariable->pPanes[i]=0;	
				}
			}
			else
			{
				newVariable->Pane=0;
				if( *pLine=='=' )
				{
					pLine++;
					int alpha = -1;
					bool is_volatile = false; 

					char* Name=GetString(); // If string IS null, don't load surface
					if (Name == NULL)
						ScriptError("Syntax: pane <Name> = <var_string>,[<var_int>alpha[, 'is_volatile' or 'nonis_volatile']");
					if (*pLine == ' ')
						pLine++;
					if (*pLine == ',')
					{
						pLine++;
						int val = GetExpression();
						
						if (val == 0)
							alpha = 0;

						if (val == 1)
							alpha = 1;
						else
						if (val == 2)
							alpha = 2;

						if (val == 3)
							is_volatile = true;
						if (*pLine ==',')
						{
							pLine++;
							int val2 = GetExpression();
							if (val2 == 3)
								is_volatile = true;
							else
							if (val2 != 4)
								ScriptError("Syntax: pane <Name> = <var_string>,[<var_int>alpha[, 'is_volatile' or 'nonis_volatile']");
						}
						newVariable->Pane = new(gScriptHeap[1]) gos_Pane(Name,alpha,is_volatile);
					}
					else
					if (0==stricmp(".AVI", &Name[strlen(Name)-4])  || 0==stricmp(".MPEG", &Name[strlen(Name)-5]) || 0==stricmp(".MPG", &Name[strlen(Name)-4]))
					{
						newVariable->Pane = new(gScriptHeap[1]) gos_Pane(Name);
					}
					else
					{
							newVariable->Pane = new(gScriptHeap[1]) gos_Pane(Name,-1,false); 
					}
				}
			}
			
			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			return;
		}

		case KEY_PANE_CREATE:
		{
			char* Name=pLine;
			gIsDeclaration = true;
			#ifdef _DEBUG
			int Exist=GetKeyword();								// Try and match against keywords and variables
			pLine=Name;

			if( Exist==VAR_PANE )
			{
				if( LastVariableScope==NewScope )
					ScriptError("Pane redefinition" );			// Already defined as a bitmap at current scope?
			}
			else
			{
				if( Exist!=-1 || FirstKeywordChar[*pLine]==0 )
					ScriptError("Invalid name for variable" );	// Bad first character or a reserved keyword
			}
			#else
			GetKeyword();										// Try and match against keywords and variables
			pLine=Name;
			#endif

			int Length=VariableLength();
			gIsDeclaration = false;

			VARIABLE* newVariable=(VARIABLE*)gos_Malloc(sizeof(VARIABLE)+Length, gScriptHeap[3]);

			newVariable->Type=VAR_PANE;							// Create new variable
			newVariable->ArraySize=0;								// Not an array element
			newVariable->NameLength=(BYTE)Length;
			memcpy( newVariable->Name, Name, Length );
			newVariable->Name[Length]=0;

			if( *pLine=='[' )
			{
				pLine++;
				newVariable->ArraySize=(WORD)GetExpression();				// Get array size
	
				if( newVariable->ArraySize<1 )
					ScriptError( "Bad array size" );
				if( *pLine!=']' )
					ScriptError( "Expected ]" );
				pLine++;
				if( *pLine==' ' )
					pLine++;
				#ifdef _DEBUG
				if( *pLine=='[' )
					ScriptError( "Multi-dimensional arrays not supported" );
				#endif

			}
//
// Arrays of panes are treated all individually ie: Bitmap[20]="fred.bmp" will load 20 copies of "fred.bmp"
//
			if( newVariable->ArraySize  > 0)
			{
				gos_Pane ** panes = (gos_Pane**)gos_Malloc(newVariable->ArraySize*sizeof(gos_Pane*), gScriptHeap[3]);
				newVariable->pPanes=panes;

				if (*pLine ==' ')
					pLine++;
				if( *pLine=='=' )
				{
					pLine++;
	
					bool is_volatile = false;
					POSITION p;
					GetPosition(&p);
#ifdef LAB_ONLY
					if (p.x == 0)
						ScriptError("Cannot create a pane with a width of 0");
					if (p.y == 0)
						ScriptError("Cannot create a pane with a height of 0");
#endif
					if (*pLine == ',')
					{
						pLine++;
						int val = GetExpression();
						if (val == 3)
							is_volatile = true;
						else
						if (val != 4)
							ScriptError("Syntax error: pane_create <Name> = sizex, sizey [,alpha, <'is_volatile' or 'nonis_volatile']]");
					}
					for( int i=0; i<newVariable->ArraySize; i++ )
					{
						if (p.z == 0)
							newVariable->pPanes[i] = new(gScriptHeap[1]) gos_Pane(p.x, p.y, 0, is_volatile);
						else
						if (p.z == 1)
							newVariable->pPanes[i] = new(gScriptHeap[1]) gos_Pane(p.x, p.y, 1, is_volatile);
						else
						if (p.z == 2)
							newVariable->pPanes[i] = new(gScriptHeap[1]) gos_Pane(p.x, p.y, 2, true);
						else
						if (p.z == 3)
							newVariable->pPanes[i] = new(gScriptHeap[1]) gos_Pane(p.x, p.y, false, true);
						else
						if (p.z == 4)
							newVariable->pPanes[i] = new(gScriptHeap[1]) gos_Pane(p.x, p.y, false, false);
					}
				}
				else
				{
					for( int i=0; i<newVariable->ArraySize; i++ )
						newVariable->pPanes[i]=0;	
				}
			}
			else
			{
				gos_Pane * pane=0;
				if( *pLine=='=' )
				{
					pLine++;
					bool is_volatile = false;
					POSITION p;
					GetPosition(&p);
#ifdef LAB_ONLY
					if (p.x == 0)
						ScriptError("Cannot create a pane with a width of 0");
					if (p.y == 0)
						ScriptError("Cannot create a pane with a height of 0");
#endif

					if (*pLine == ',')
					{
						pLine++;
						int val = GetExpression();
						if (val == 3)
							is_volatile = true;
						else
						if (val != 4)
							ScriptError("Syntax error: pane_create <Name> = sizex, sizey [,alpha, <'is_volatile' or 'nonis_volatile']]");
					}

					if (p.z == 0)
						pane = new(gScriptHeap[1]) gos_Pane(p.x, p.y, 0, is_volatile);
					else
					if (p.z == 1)
						pane = new(gScriptHeap[1]) gos_Pane(p.x, p.y, 1, is_volatile);
					else
					if (p.z == 2)
						pane = new(gScriptHeap[1]) gos_Pane(p.x, p.y, 2, true);
					else
					if (p.z == 3)
						pane = new(gScriptHeap[1]) gos_Pane(p.x, p.y, false, true);
					else
					if (p.z == 4)
						pane = new(gScriptHeap[1]) gos_Pane(p.x, p.y, false, false);
				}
				newVariable->Pane=pane;
			}
			
			AddVariable( pObject, NewScope, newVariable );					// Link variable into correct list
			return;
		}

		case VAR_PANE:
		{
			if (*pLine == ' ')
				pLine++;
			if( *pLastVariable!=0)
			{
				delete ((gos_Pane *) *pLastVariable);
			}
			if( *pLine != '=' )
				ScriptError("Expected '<var_pane> = <var_int w, var_int h> or <var_pane> or <var_string>" );		// Bad first character or a reserved keyword
			else
				pLine++;

			if (*pLine == ' ')
				pLine++;
			gos_Pane  ** save = (gos_Pane **) pLastVariable;
			char * place = pLine;
			int kw = GetKeyword();
			if ( kw == VAR_BITMAP)
			{
				if (*pLine == ' ')
					pLine++;
				if (*pLine == ',')
				{
					int val = GetExpression();
					int val2 = 4;
					if (*pLine == ',')
					{
						val2 = GetExpression();
						if (!(val2 == 3 || val2 == 4))
							ScriptError("Syntax error: <var_pane> = sizex, sizey [,alpha, <'is_volatile' or 'nonis_volatile']]");

					}
					if (val == 1)
					{
						if (val2 == 3)
							*save = new(gScriptHeap[1]) gos_Pane(gos_GetSurfacePath((HGOSSURFACE ) *pLastVariable), 1, true);
						else
							*save = new(gScriptHeap[1]) gos_Pane(gos_GetSurfacePath((HGOSSURFACE ) *pLastVariable), 1, false);
					}
					else
					if (val == 2)
					{
						if (val2 == 3)
							*save = new(gScriptHeap[1]) gos_Pane(gos_GetSurfacePath((HGOSSURFACE ) *pLastVariable), 2, true);
						else
							*save = new(gScriptHeap[1]) gos_Pane(gos_GetSurfacePath((HGOSSURFACE ) *pLastVariable), 2, false);
					}
					else
					if (val == 0)
					{
						if (val2 == 3)
							*save = new(gScriptHeap[1]) gos_Pane(gos_GetSurfacePath((HGOSSURFACE ) *pLastVariable), 0, true);
						else
							*save = new(gScriptHeap[1]) gos_Pane(gos_GetSurfacePath((HGOSSURFACE ) *pLastVariable), 0, false);
					}
					else
					{
						if (val2 == 4)
							*save = new(gScriptHeap[1]) gos_Pane(gos_GetSurfacePath((HGOSSURFACE ) *pLastVariable), -1, true);
						else
							*save = new(gScriptHeap[1]) gos_Pane(gos_GetSurfacePath((HGOSSURFACE ) *pLastVariable), -1, false);
					}
				}
				else
				{
						*save = new(gScriptHeap[1]) gos_Pane(gos_GetSurfacePath((HGOSSURFACE ) *pLastVariable), -1, false);
				}
				return;
			}
			else
			if (kw == VAR_INT)
			{
				gos_Pane * pane = NULL;
				int val1 = *pLastVariable;

				if (*pLine == ' ')
					pLine++;
				if (*pLine != ',')
					ScriptError("<var_pane>=sizex,sizey[,alpha t/f, 'is_volatile' or 'nonis_volatile']");
				else
					pLine++;
				int val2 = GetExpression();

				if (*pLine == ' ')
					pLine++;
				if (*pLine == ',')
				{
					pLine++;
					int val3 = GetExpression();
					int val4 = 4;
					if (*pLine == ',')
					{
						pLine++;
						val4 = GetExpression();
					}

					switch(val3)
					{
					case 0:
						switch(val4)
						{
						case 3:
							// is is_volatile, has no alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,0,true); 
							break;
						case 4:
							// isn't is_volatile, has no alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,0,false); 
							break;
						default:
							ScriptError("Syntax error: <var_pane> = sizex, sizey[, <var_int alpha>, <'is_volatile' or <nonis_volatile>]");
							break;
						}
						break;

					case 1:
						switch(val4)
						{
						case 3:
							// is is_volatile, has alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,1,true); 
							break;
						case 4:
							// isn't is_volatile, has alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,1,false); 
							break;
						default:
							ScriptError("Syntax error: <var_pane> = sizex, sizey[, <var_int alpha>, <'is_volatile' or <nonis_volatile>]");
							break;
						}
						break;
					case 2:
						switch(val4)
						{
						case 3:
							// is is_volatile, has alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,2,true); 
							break;
						case 4:
							// isn't is_volatile, has alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,2,false); 
							break;
						default:
							ScriptError("Syntax error: <var_pane> = sizex, sizey[, <var_int alpha>, <'is_volatile' or <nonis_volatile>]");
							break;
						}
						break;

					case 3:
						// is is_volatile, no alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,false,true); 
						break;

					case 4:
						// isn't is_volatile, no alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,false,false); 
						break;
					default:
						ScriptError("Syntax error: <var_pane> = sizex, sizey[, <true/false alpha>, <'is_volatile' or <nonis_volatile>]");
						break;
					}
				}
				else
				{
					pane = new(gScriptHeap[1]) gos_Pane(val1, val2,false,false); 
				}

				*save = pane;
				return;
			}
			else
			if (kw == VAR_STRING)
			{
				pLine = place;
			}

			
			char* Name=GetString();									// If string is null, don't load surface
			if (Name)
			{
				pLastVariable = (long *) save;
			
				gos_Pane * pane=0;

				if (*pLine == ' ')
					pLine++;
				if (*pLine == ',')
				{
					pLine++;
					int val3 = GetExpression();
					int val4 = 4;
					if (*pLine == ',')
					{
						pLine++;
						val4 = GetExpression();
					}

					switch(val3)
					{
					case -1:
						switch(val4)
						{
						case 3:
							// is is_volatile, has no alpha
							pane = new(gScriptHeap[1]) gos_Pane(Name,-1,true); 
							break;
						case 4:
							// isn't is_volatile, has no alpha
							pane = new(gScriptHeap[1]) gos_Pane(Name,-1,false); 
							break;
						default:
							ScriptError("Syntax error: <var_pane> = <var_string>[, <var_int type>,] <'is_volatile' or <nonis_volatile>]");
							break;
						}
						break;

					case 0:
						switch(val4)
						{
						case 3:
							// is is_volatile, has no alpha
							pane = new(gScriptHeap[1]) gos_Pane(Name,0,true); 
							break;
						case 4:
							// isn't is_volatile, has no alpha
							pane = new(gScriptHeap[1]) gos_Pane(Name,0,false); 
							break;
						default:
							ScriptError("Syntax error: <var_pane> = <var_string>[, <var_int type>,] <'is_volatile' or <nonis_volatile>]");
							break;
						}
						break;

					case 1:
						switch(val4)
						{
						case 3:
							// is is_volatile, has alpha
							pane = new(gScriptHeap[1]) gos_Pane(Name,1,true); 
							break;
						case 4:
							// isn't is_volatile, has alpha
							pane = new(gScriptHeap[1]) gos_Pane(Name,1,false); 
							break;
						default:
							ScriptError("Syntax error: <var_pane> = <var_string>[, <var_int type>, <'is_volatile' or <nonis_volatile>]");
							break;
						}
						break;
					case 2:
						switch(val4)
						{
						case 3:
							// is is_volatile, has alpha
							pane = new(gScriptHeap[1]) gos_Pane(Name,2,true); 
							break;
						case 4:
							// isn't is_volatile, has alpha
							pane = new(gScriptHeap[1]) gos_Pane(Name,2,false); 
							break;
						default:
							ScriptError("Syntax error: <var_pane> = <var_string>[, <var_int type>, <'is_volatile' or <nonis_volatile>]");
							break;
						}
						break;


					case 3:
						// is is_volatile, no alpha
						pane = new(gScriptHeap[1]) gos_Pane(Name,-1,true); 
						break;

					case 4:
						// isn't is_volatile, no alpha
						pane = new(gScriptHeap[1]) gos_Pane(Name,-1,false); 
						break;
					default:
							ScriptError("Syntax error: <var_pane> = <var_string>[, <var_int type>, <'is_volatile' or <nonis_volatile>]");
						break;
					}
				}
				else
				if (0==stricmp(".AVI", &Name[strlen(Name)-4]) || 0==stricmp(".MPEG", &Name[strlen(Name)-5] ) || 0==stricmp(".MPG", &Name[strlen(Name)-4]) )
				{
					pane = new(gScriptHeap[1]) gos_Pane(Name);
				}
				else
				{
					pane = new(gScriptHeap[1]) gos_Pane(Name,-1,false); 
				}
				*save = pane;
				return;
			}
			else
			{
				gos_Pane * pane = NULL;
				int val1 = GetExpression();
				if (*pLine == ' ')
					pLine++;
				if (*pLine != ',')
					ScriptError("<var_pane>=[<var_int>, <var_int>] or [var_string]");
				else
					pLine++;
				int val2 = GetExpression();
				if (*pLine == ' ')
					pLine++;
				if (*pLine == ',')
				{
					pLine++;
					int val3 = GetExpression();
					int val4 = 4;
					if (*pLine == ',')
					{
						pLine++;
						val4 = GetExpression();
					}

					switch(val3)
					{
					case 0:
						switch(val4)
						{
						case 3:
							// is is_volatile, has no alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,0,true); 
							break;
						case 4:
							// isn't is_volatile, has no alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,0,false); 
							break;
						default:
							ScriptError("Syntax error: <var_pane> = sizex, sizey[, <true/false alpha>, <'is_volatile' or <nonis_volatile>]");
							break;
						}
						break;

					case 1:
						switch(val4)
						{
						case 3:
							// is is_volatile, has alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,1,true); 
							break;
						case 4:
							// isn't is_volatile, has alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,1,false); 
							break;
						default:
							ScriptError("Syntax error: <var_pane> = sizex, sizey[, <true/false alpha>, <'is_volatile' or <nonis_volatile>]");
							break;
						}
						break;

					case 2:
						switch(val4)
						{
						case 3:
							// is is_volatile, has alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,2,true); 
							break;
						case 4:
							// isn't is_volatile, has alpha
							pane = new(gScriptHeap[1]) gos_Pane(val1, val2,2,false); 
							break;
						default:
							ScriptError("Syntax error: <var_pane> = sizex, sizey[, <true/false alpha>, <'is_volatile' or <nonis_volatile>]");
							break;
						}
						break;

					case 3:
						// is is_volatile, no alpha
						pane = new(gScriptHeap[1]) gos_Pane(val1, val2,false,true); 
						break;

					case 4:
						// isn't is_volatile, no alpha
						pane = new(gScriptHeap[1]) gos_Pane(val1, val2,false,false); 
						break;
					default:
						ScriptError("Syntax error: <var_pane> = sizex, sizey[, <true/false alpha>, <'is_volatile' or <nonis_volatile>]");
						break;
					}
				}
				else
				{
					pane = new(gScriptHeap[1]) gos_Pane(val1, val2,false,false); 
				}
				*save = pane;
				return;
			}
			
			return;
		}
		
		case KEY_SCALE:
		{
			if (*pLine != '(')
				ScriptError("Syntax error: scale(<var_pane>)=<var_int x>, <var_int y>, <var_int z>");
			else 
				pLine++;
			int kw = GetKeyword();
			if (kw != VAR_PANE && kw != VAR_MOVIE)
				ScriptError("Syntax error: scale(<var_pane / var_movie>)=<var_int x>, <var_int y>, <var_int z>");
			if (kw == VAR_PANE)
			{
				gos_Pane * pane = (gos_Pane *) *pLastVariable;
				if (*pLine == ' ')
					pLine++;
				if (*pLine != ')')
					ScriptError("Syntax error: scale(<var_pane / var_movie >)=<var_int x>, <var_int y>, <var_int z>");
				else 
					pLine++;
				if (*pLine == ' ')
					pLine++;
				if (*pLine != '=')
					ScriptError("Syntax error: scale(<var_pane / var_movie >)=<var_int x>, <var_int y>, <var_int z>");
				else 
					pLine++;
	
				POSITION p;
				*pCurrentLineFlags = GetPosition( &p, *pCurrentLineFlags );
	
				pane->Scale((float) p.x / 100, (float) p.y / 100, (float) p.z / 100);
				return;
			}
			else
			if (kw == VAR_MOVIE)
			{
				HGOSVIDEO vid = (HGOSVIDEO) *pLastVariable;
				if (*pLine == ' ')
					pLine++;
				if (*pLine != ')')
					ScriptError("Syntax error: scale(<var_movie>)=<var_int x>, <var_int y>");
				else 
					pLine++;
				if (*pLine == ' ')
					pLine++;
				if (*pLine != '=')
					ScriptError("Syntax error: scale(<var_movie>)=<var_int x>, <var_int y>");
				else 
					pLine++;
	
				POSITION p;
				*pCurrentLineFlags = GetPosition( &p, *pCurrentLineFlags );

				if (p.x <= 0) 
					p.x = 1; // don't allow a scale of less than 1%	
				if (p.y <= 0) 
					p.y = 1; // don't allow a scale of less than 1%	
				gosVideo_Command(vid, gosVideo_SetScale, (float) p.x / 100, (float) p.y / 100);
				return;
			}
		}
		
		case KEY_ROTATE:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax error: rotation<var_pane)=<var_int x>, <var_int y>, <var_int z>");
			#endif
			pLine++;

			#ifdef _DEBUG
			int kw = GetKeyword();
			if (kw != VAR_PANE )
				ScriptError("Syntax error: rotation<var_pane)=<var_int x>, <var_int y>, <var_int z>");
			#else
			GetKeyword();
			#endif

			gos_Pane * pane = (gos_Pane *) *pLastVariable;

			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ')')
				ScriptError("Syntax error: rotation<var_pane)=<var_int x>, <var_int y>, <var_int z>");
			#endif
			pLine++;
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != '=')
				ScriptError("Syntax error: rotation<var_pane)=<var_int x>, <var_int y>, <var_int z>");
			#endif
			pLine++;

			POSITION p;
			*pCurrentLineFlags = GetPosition( &p, *pCurrentLineFlags );

			pane->Rotate((float) (p.x / 360.0f)*6.28f, (float) (p.y / 360.0f)*6.28f, (float) (p.z / 360.0f)*6.28f);
	   		return;
		}
		
		case KEY_ORIGIN:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax error: origin<var_pane)=<var_int x>, <var_int y>, <var_int z>");
			#endif
			pLine++;
			#ifdef _DEBUG
			int kw = GetKeyword();
			if (kw != VAR_PANE)
				ScriptError("Syntax error: origin<var_pane)=<var_int x>, <var_int y>, <var_int z>");
			#else
			GetKeyword();
			#endif
			gos_Pane * pane = (gos_Pane *) *pLastVariable;
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ')')
				ScriptError("Syntax error: origin<var_pane)=<var_int x>, <var_int y>, <var_int z>");
			#endif
			pLine++;
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != '=')
				ScriptError("Syntax error: origin<var_pane)=<var_int x>, <var_int y>, <var_int z>");
			#endif
			pLine++;

			POSITION p;
			*pCurrentLineFlags = GetPosition( &p, *pCurrentLineFlags );

			pane->Origin(p.x, p.y, p.z);
			return;
		}
		
		case KEY_COLOR:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax error: color<var_pane)=<var_int argb> or <var_int r>, <var_int g>, <var_int b>, <var_int a>");
			#endif
			pLine++;
			#ifdef _DEBUG
			int kw = GetKeyword();
			if (kw != VAR_PANE)
				ScriptError("Syntax error: color<var_pane)=<var_int argb> or <var_int r>, <var_int g>, <var_int b>, <var_int a>");
			#else
			GetKeyword();
			#endif
			gos_Pane * pane = (gos_Pane *) *pLastVariable;
			#ifdef _DEBUG
			if (!pane)
				ScriptError("Syntax error: color(<var_pane>) is being applied to an undefined pane");
			#endif
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ')')
				ScriptError("Syntax error: color<var_pane)=<var_int argb> or <var_int r>, <var_int g>, <var_int b>, <var_int a>");
			#endif
			pLine++;
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != '=')
				ScriptError("Syntax error: color<var_pane)=<var_int argb> or <var_int r>, <var_int g>, <var_int b>, <var_int a>");
			#endif
			pLine++;

			int val = GetExpression();
			if (*pLine == ' ')
				pLine++;
			if (*pLine == ',')
			{
				pLine++;
				POSITION p;
				GetPosition(&p,1);
				if( val>255 )
					val=255;
				else if( val<0 )
					val=0;
				if( p.x>255 )
					p.x=255;
				else if( p.x<0 )
					p.x=0;
				if( p.y>255 )
					p.y=255;
				else if( p.y<0 )
					p.y=0;
				if( p.z>255 )
					p.z=255;
				else if( p.z<0 )
					p.z=0;
				pane->Color( (val<<16) + (p.x<<8) + p.y + (p.z<<24) );
			}
			else
			{
				pane->Color(val);
			}
			return;
		}
		
		case KEY_ALPHAMODE:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax error: alphamode<var_pane)=<var_int x>");
			#endif
			pLine++;
			#ifdef _DEBUG
			int kw = GetKeyword();
			if (kw != VAR_PANE)
				ScriptError("Syntax error: alphamode<var_pane)=<var_int x>");
			#else
			GetKeyword();
			#endif
			gos_Pane * pane = (gos_Pane *) *pLastVariable;
			if (*pLine == ' ')
				pLine++;
			if (*pLine != ')')
				ScriptError("Syntax error: alphamode<var_pane)=<var_int x>");
			else 
				pLine++;
			if (*pLine == ' ')
				pLine++;
			if (*pLine != '=')
				ScriptError("Syntax error: alphamode<var_pane)=<var_int x>");
			else 
				pLine++;

			pane->AlphaMode((enum gos_AlphaMode)  GetExpression());

			return;
		}
		
		case KEY_RENDER:
		{
			#ifdef _DEBUG
			if (gScript_InDraw == false)
				ScriptError(("Calling 'render' outside GUI_DRAW is illegal"));
			#endif

			int kw = GetKeyword();

			#ifdef _DEBUG
			if (kw != VAR_PANE && kw != VAR_MOVIE)
				ScriptError("Syntax error: render <var_pane / var_movie>, (var_position)");
			#endif

			int var = *pLastVariable;

			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ',')
				ScriptError("Syntax error: render <var_pane / var_doc / var_movie>, (var_position)");
			#endif
			pLine++;
			if (*pLine == ' ')
				pLine++;

			POSITION p;
			*pCurrentLineFlags = GetPosition( &p, *pCurrentLineFlags );

			OBJECT * ptr = pObject;
			if (*ptr->bPosRelative)
			{
				while(ptr)
				{
					p.x += ptr->Coordinates->x;
					p.y += ptr->Coordinates->y;
					p.z += ptr->Coordinates->z;
					if (*ptr->bPosRelative)
						ptr = ptr->pParentObject;
					else
						break;
				}
			}

			if (*pLine == ' ')
				pLine++;

			if (kw == VAR_PANE)
			{
				#ifdef _DEBUG
				if (var == NULL)
					ScriptError("Syntax error: you attempted to render an uninitialized pane");
				#endif
				((gos_Pane *) var)->Render(p.x, p.y);
			}
			else
			if (kw == VAR_MOVIE)
			{
				#ifdef _DEBUG
				if (var == NULL)
					ScriptError("Syntax error: you attempted to render an uninitialized movie");
				#endif
				gosVideo_Command((HGOSVIDEO) var, gosVideo_SetCoords, (float) p.x, (float) p.y);
			}

			return;
		}
		case KEY_UPDATE:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax error: update<var_pane)");
			#endif
			pLine++;
			#ifdef _DEBUG
			int kw = GetKeyword();
			if (kw != VAR_PANE)
				ScriptError("Syntax error: update<var_pane)");
			#else
			GetKeyword();
			#endif
			gos_Pane * pane = (gos_Pane *) *pLastVariable;
			if (*pLine == ' ')
				pLine++;
			#ifdef _DEBUG
			if (*pLine != ')')
				ScriptError("Syntax error: update<var_pane)");
			if (pane->GetSurface() == NULL)
				ScriptError("This pane was not flagged as is_volatile when it was created");
			#endif
			pane->Update();
			return;
		}
		case KEY_REFRESH:
		{
			#ifdef _DEBUG
			if (*pLine != '(')
				ScriptError("Syntax error: refresh<var_pane)");
			#endif
			pLine++;
			int kw = GetKeyword();
			if (kw != VAR_PANE)
				ScriptError("Syntax error: refresh<var_pane)");
			gos_Pane * pane = (gos_Pane *) *pLastVariable;
			if (*pLine == ' ')
				pLine++;
			if (*pLine != ')')
				ScriptError("Syntax error: refresh<var_pane)");
			else 
				pLine++;

			if (pane->GetSurface() == NULL)
				ScriptError("This pane was not flagged as is_volatile when it was created");
			gos_RestoreSurface(pane->GetSurface());
			pane->Update();

			return;
		}
//
// Unknown command
//
		default:
			ScriptError("Keyword expected" );
	}
}










//
// Execute the next command(s)
//
//
// This routine deals with recursive commands (if, else, loops)
//
// It can also ignore the next command (which may be an if)
//
// Return Codes:
//
// RET_END   = End of file
// RET_NOR   = Normal exit
// RET_BREAK = break
// RET_CONT  = continue
//
//
DoCommandRet DoCommands( bool Execute, bool InCase, int NestingLevel)
{
	DoCommandRet result=RET_NOR;
	int Keyword=0,LastIF=0;

	while( GetNextLine() )
	{
#if defined(_DEBUG) && 1 // jcem
        static const char s_szFile[128] = "";
        static int s_msg = -1; // MSG_GUI_EXECUTE;
        static bool s_bBreak = false;
        static int s_nLine = 2117;
        static int s_nExecuteCheck = +1; // -1: no execute, 0: don't care, +1: yes execute

        if (s_bBreak) {
            if (!s_szFile[0] || strstr(pFileName, s_szFile)) {
                if ((s_msg == -1) || (CurrentMessage == s_msg)) {
		            if (CurrentLineNumber == s_nLine) {
                        if (!s_nExecuteCheck || ((s_nExecuteCheck == -1) && !Execute) || ((s_nExecuteCheck == +1) && Execute)) {
                            s_nLine++;
                            s_nLine--;
                        }
                    }
                }
            }
		}
#endif // _DEBUG
		if( *pLine=='{' )
		{
			pLine++;
			NestingLevel++;
			continue;								// Deal with multiple commands within {...}
		}
		if( *pLine=='}' )
		{
			pLine++;
			NestingLevel--;
			if (NestingLevel == -1 && InCase)
				return RET_END;
			if( NestingLevel<0 )
				ScriptError("Unexpected }");
			if(	NestingLevel==0 )	
				return result;		
			continue;
		}

		#ifdef _ARMOR
		char* pKeyWord=pLine;
		#endif
		Keyword=CurrentKeyword;
//
// BREAK command
//
		if( Keyword==KEY_BREAK )
		{
			if ( Execute )
			{
				Execute=0;
				if (InCase)
				{
					NestingLevel--;
					InCase = false;
				}

				result=RET_BREAK;
				if(	NestingLevel==0 )	
					return result;		
				continue;
			}
		}
//
// CONTINUE command
//
		if( Keyword==KEY_CONTINUE && Execute)
		{
			Execute=0;
			result=RET_CONT;
			if(	NestingLevel==0 )	
				return result;		
			continue;
		}
//
// RETURN command
//
		if (Keyword==KEY_RETURNFROMSECTION && Execute)
		{
			NestingLevel = 0;
			if (*pLine != 0)
			{
				g_scriptPostedInteger[g_mailStack][0] = GetExpression();
			}
			return RET_RETURN;
		}
//
// IF command
//
		if( Keyword==KEY_IF )
		{
			if( Execute && FloatGetExpression()!=0 )
			{
				LastIF=1;
				result=DoCommands(1);
			}
			else
			{
#ifdef _DEBUG // for debugging by jcem
                extern LINEINFO* pOldLineInfo;
                gosASSERT(pCurrentLineFlags == &pOldLineInfo->LineFlags);
#endif // _DEBUG
#ifdef _DEBUG
                if (CurrentLineNumber == 2118) {
                    CurrentLineNumber++;
                    CurrentLineNumber--;
                }
#endif // 
				LastIF=2;
				//if( *pCurrentLineFlags )
				//{
				//	pStartofLine=(char*)*pCurrentLineFlags;			// Remember where to skip to if IF condition fails
				//}
				//else
				{
					DWORD* IfData=pCurrentLineFlags;
					DoCommands(0);
					*IfData=(DWORD)pStartofLine;
				}
			}
			if( result==RET_BREAK || result==RET_CONT )
				Execute=0;
			if (result==RET_RETURN)
			{
				return RET_RETURN;
			}
			else
			if( NestingLevel!=0 || PeekNextLine() == KEY_ELSE )
				continue;
			return result;
		}
//
// SWITCH command
//
		if ( Keyword == KEY_SWITCH )
		{
			int tmpVal = 0;
			if( Execute )									// If skipping, ignore for
			{

				int FoundOpen=0;								// 1 if open parentesis used, closing required then
				if( *pLine=='(' )
				{
					FoundOpen=1;
					pLine++;
				}
	
				if( *pLine=='(' )
				{
					FoundOpen=1;
					pLine++;
				}
				if( *pLine==' ' )
					pLine++;
	
				tmpVal = GetExpression();
				if( *pLine==' ' )
					pLine++;
				if( *pLine!=')' )
					ScriptError("Missing parathesis" );
			}

			bool keepGoing = true;
			bool foundCase = false;
			bool ranCourse = false;
			int lastCase;
			do
			{
	   			result = DoCommands(Execute,1,0);
start_again:
				switch(result)
				{
				case RET_RETURN:
					keepGoing = false;
					if (Execute)
						return RET_NOR;
					else
						continue;
					break;
				case RET_END:
					keepGoing = false;
					//result = DoCommands(0,1,1);
					break;
				case RET_BREAK:
					result = RET_NOR;
					ranCourse = true;
					break;
				case RET_CASE:
					lastCase = GetExpression();
					if ((tmpVal == lastCase) || (foundCase && !ranCourse))
					{
						foundCase = true;
						result = DoCommands(Execute,1,1);
						goto start_again;
					}
					else
					{
						result = DoCommands(0,0,1);
						goto start_again;
					}
					break;
				case RET_DEFAULT:
					if (!foundCase)
						DoCommands(Execute,1,1);
					else
						DoCommands(0,1,1);
					keepGoing = false;
					break;
				default:
					keepGoing = false;
					break;
				}
			} while(keepGoing);

			continue;
		}
//
// CASE command
//
		if ( Keyword == KEY_CASE )
		{
			return RET_CASE;
		}
//
// DEFAULT commands
//
		if ( Keyword == KEY_DEFAULT )
		{
			return RET_DEFAULT;
		}
//
// ELSE command
//
		else if( Keyword==KEY_ELSE )
		{
			if( LastIF==0 )
				ScriptError("Not doing an 'if'" );
			if( !Execute || LastIF==1 )
				DoCommands(0);
			else
				result=DoCommands(1);
			if( result==RET_BREAK || result==RET_CONT )
				Execute=0;
			LastIF=0;
			if(	NestingLevel==0 )	
				return result;		
			continue;
		}
//
// Flag that last keyword was not an IF (used to validate ELSE command)
//
		LastIF=0;
//
// FOR command
//
		if( Keyword==KEY_FOR )
		{
			int FoundOpen=0;								// 1 if open parentesis used, closing required then
			
			if( !Execute )									// If skipping, ignore for
			{
#ifdef _DEBUG // for debugging by jcem
                extern LINEINFO* pOldLineInfo;
                gosASSERT(pCurrentLineFlags == &pOldLineInfo->LineFlags);
#endif // _DEBUG

				if( *pCurrentLineFlags )
				{
					pStartofLine=(char*)*pCurrentLineFlags;			// Remember where to skip to if IF condition fails
				}
				else
				{
					DWORD* SkipData=pCurrentLineFlags;
					DoCommands(0);
					*SkipData=(DWORD)pStartofLine;
				}
				if(	NestingLevel==0 )	
					return result;		
				continue;
			}
					
			if( *pLine=='(' )
			{
				FoundOpen=1;
				pLine++;
			}

			if( *pLine==' ' )
				pLine++;

			if( *pLine!=';'	)								// No init is valid
			{
				while(1)
				{
					CurrentKeyword=254;
					ExecuteCommand();						// Execute statement
				
					if( *pLine==' ' )
						pLine++;
						
					if( *pLine==',' )						// More than one statement maybe
					{
						pLine++;
						continue;
					}

					if( *pLine!=';' )
						ScriptError("Missing parameter" );

					break;
				}
			}

			pLine++;

#ifdef _DEBUG // for debugging by jcem
            extern LINEINFO* pOldLineInfo;
            LINEINFO* pLastLineInfo = pOldLineInfo;
#endif // _DEBUG
			char* pCondition=pLine;							// Save a pointer to start of condition
			char* pConditionLine=pStartofLine;				// Save a pointer to start of line
			DWORD* pFlagData=pCurrentLineFlags;					// Save a pointer to the flags
			int ForLine=CurrentLineNumber;					// Save the line number

			FloatGetExpression();							// Skip the condition expression

			if( *pLine!=';' )								// Move to statement
				ScriptError("Missing parameter" );
			pLine++;

			char* pStatement=pLine;							// Save a pointer to the statement

			while(1)
			{
				pLine=pCondition;
				pStartofLine=pConditionLine;				// Reset code pointer to condition
				pCurrentLineFlags=pFlagData;
				CurrentLineNumber=ForLine;

				if( 0==FloatGetExpression() )
					break;

				int retval=DoCommands(1);					// Execute the 'for' block

				pLine=pStatement;
				pStartofLine=pConditionLine;				// Reset code pointer to statement
				CurrentLineNumber=ForLine;
				pCurrentLineFlags=pFlagData;

				if( retval==RET_BREAK )
					break;
				if( retval==RET_RETURN )
					return RET_END;
				
				while(1)
				{
					CurrentKeyword=254;
					ExecuteCommand();						// Execute statement
				
					if( *pLine==' ' )
						pLine++;
						
					if( *pLine==',' )						// More than one statement
					{
						pLine++;
						continue;
					}

					if( FoundOpen && *pLine!=')' )
						ScriptError("Missing close parenthesis" );

					break;
				}
			}
#ifdef _DEBUG
            gosASSERT(pCurrentLineFlags == &pLastLineInfo->LineFlags);
#endif // _DEBUG
			if( *pCurrentLineFlags )
			{
				pStartofLine=(char*)*pCurrentLineFlags;			// Remember where to skip to if IF condition fails
			}
			else
			{
				DWORD* SkipData=pCurrentLineFlags;
				DoCommands(0);
				*SkipData=(DWORD)pStartofLine;
			}
			if(	NestingLevel==0 )	
				return result;		
			continue;
		}
//
// WHILE command
//
		if( Keyword==KEY_WHILE )
		{
			int FoundOpen=0;								// 1 if open parentesis used, closing required then
			
			if( !Execute )									// If skipping, ignore while
			{
#ifdef _DEBUG // for debugging by jcem
                extern LINEINFO* pOldLineInfo;
                gosASSERT(pCurrentLineFlags == &pOldLineInfo->LineFlags);
#endif // _DEBUG
				if( *pCurrentLineFlags )
				{
					pStartofLine=(char*)*pCurrentLineFlags;			// Remember where to skip to if IF condition fails
				}
				else
				{
					DWORD* SkipData=pCurrentLineFlags;
					DoCommands(0);
					*SkipData=(DWORD)pStartofLine;
				}
				if(	NestingLevel==0 )	
					return result;		
				continue;
			}
					
			if( *pLine=='(' )
			{
				FoundOpen=1;
				pLine++;
			}

			if( *pLine==' ' )
				pLine++;

#ifdef _DEBUG // for debugging by jcem
            extern LINEINFO* pOldLineInfo;
            LINEINFO* pLastLineInfo = pOldLineInfo;
#endif // _DEBUG
			char* pCondition=pLine;							// Save a pointer to start of condition
			char* pConditionLine=pStartofLine;				// Save a pointer to start of line
			int ForLine=CurrentLineNumber;					// Save the line number
			DWORD* pFlagData=pCurrentLineFlags;					// Save a pointer to the flags

			while( FloatGetExpression() )						// Do the while commands while true
			{
				int retval=DoCommands(1);					// Execute the 'while' block

				pLine=pCondition;
				pCurrentLineFlags=pFlagData;
				pStartofLine=pConditionLine;				// Reset code pointer to statement
				CurrentLineNumber=ForLine;

				if( retval==RET_BREAK )
					break;
			}
			
#ifdef _DEBUG
            gosASSERT(pCurrentLineFlags == &pLastLineInfo->LineFlags);
#endif // _DEBUG
			if( *pCurrentLineFlags )
			{
				pStartofLine=(char*)*pCurrentLineFlags;			// Remember where to skip to if IF condition fails
			}
			else
			{
				DWORD* SkipData=pCurrentLineFlags;
				DoCommands(0);
				*SkipData=(DWORD)pStartofLine;
			}
			if(	NestingLevel==0 )	
				return result;		
			continue;
		}
//
// DO command
//
		if( Keyword==KEY_DO )
		{
			if( !Execute )									// If skipping, ignore do...while
			{
#ifdef _DEBUG // for debugging by jcem
                extern LINEINFO* pOldLineInfo;
                gosASSERT(pCurrentLineFlags == &pOldLineInfo->LineFlags);
#endif // _DEBUG
				if( *pCurrentLineFlags )
				{
					pStartofLine=(char*)*pCurrentLineFlags;			// Remember where to skip to if IF condition fails
				}
				else
				{
					DWORD* SkipData=pCurrentLineFlags;
					DoCommands(0);
					*SkipData=(DWORD)pStartofLine;
				}
				GetNextLine();
				if( CurrentKeyword != KEY_WHILE )
					ScriptError("'while' expected" );				
				if(	NestingLevel==0 )	
					return result;		
				continue;
			}
					
			char* pCondition=pLine;							// Save a pointer to start of condition
			char* pConditionLine=pStartofLine;				// Save a pointer to start of line
			int ForLine=CurrentLineNumber;					// Save the line number
			int Condition,retval;
			DWORD* pFlagData=pCurrentLineFlags;					// Save a pointer to the flags

			do												// Do the while commands while true
			{
				pLine=pCondition;
				pStartofLine=pConditionLine;				// Reset code pointer to after do statement
				pCurrentLineFlags=pFlagData;
				CurrentLineNumber=ForLine;

				retval=DoCommands(1);						// Execute the 'while' block

				GetNextLine();

				if( CurrentKeyword != KEY_WHILE )				// Check the while condition
					ScriptError("'while' expected" );				

				if( retval==RET_BREAK )
					break;

				Condition=(int) FloatGetExpression();
			}
			while ( Condition );
			
			if(	NestingLevel==0 )	
				return result;		
			continue;
		}
//
// If not a potential block command and executing, do the next instruction
//
		if( Execute )
		{
			#ifdef _ARMOR
				pLine=pKeyWord;
				static char Buffer[32];
				strncpy( Buffer, pLine, 32 );
				Buffer[31]=0;
				char* pTemp=Buffer;
				while( *pTemp )
				{
					*pTemp++=(char)(*pTemp&127);
				}
				if( CurrentKeyword<250 )
				{
					SPEW((GROUP_VERBOSESCRIPTS, "%s(%d) : %s %s", pFileName,CurrentLineNumber,Keywords[CurrentKeyword],pLine));
				}
				else
				{
					SPEW((GROUP_VERBOSESCRIPTS, "%s(%d) : %s", pFileName,CurrentLineNumber,pLine));
				}
				#endif
			
			ExecuteCommand();
		}

		if(	NestingLevel==0 )	
			return result;									// If not nested then done
	}

	if( NestingLevel!=0 )
		ScriptError("Missing close brace" );

	return RET_END;
}



