/*********************************                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           /*********************************
**   GBCEditor Ver 1.0.0         **
**   Programmed by Ryan Best    **
**   ©Copyright 1992, Ryan Best **
**********************************
*
******** VAR INITS  *************/ 
 

#include "Packages.h"
#include "Sound.h"
#include "stdlib.h"
#include "stdio.h"
#include "files.h"

#define BASE_RES_ID			400
#define	GAME_WINDOW			401				
#define	DUNGEON_WINDOW		402				/* not used currently  */


#define	OKAY_ITEM			1
#define	CANCEL_ITEM			2
#define	ROLLER_ITEM			5
#define	TEXT_ITEM			4
	
#define NIL_POINTER			0L
#define MOVE_TO_FRONT		(WindowPtr)-1L
#define REMOVE_ALL_EVENTS	0
#define ADD_CHECKMARK		TRUE
#define REMOVE_CHECKMARK	FALSE
#define DRAG_THRESHOLD		30

#define	UNDEAD				1
#define	INSECT				2
#define	DRAGON				3
#define	HUMAN				4
#define	BLOB				5
#define	GASEOUS				6
#define	DNGMSTR				7
#define	ANIMAL				8
#define	HUMANOID			9
#define	OTHER				10
#define	DEFENDER			11
#define	BURNEDITEM			12

#define	NIL_STRING			"\p"
#define	IGNORED_STRING		NIL_STRING
#define	NIL_FILE_FILTER		NIL_POINTER
#define	NIL_DIALOG_HOOK		NIL_POINTER

#define MIN_SLEEP			0L
#define NIL_MOUSE_REGION	0L

#define WNE_TRAP_NUM		0x60
#define UNIMPL_TRAP_NUM		0x9F

#define NEW_ITEM			1			/* File Menu	*/
#define	OPEN_ITEM			2
#define	CLOSE_ITEM			3
#define SAVE_ITEM			4
#define QUIT_ITEM			6

#define ABOUT_ITEM			1			/* Apple Menu	*/
#define	ABOUT_HELP			2

#define UNDO_ITEM			1			/* Edit Menu	*/
#define	CUT_ITEM			2
#define	COPY_ITEM			3
#define PASTE_ITEM			4
#define CLEAR_ITEM			5
 
#define APPLE_MENU_ID		BASE_RES_ID
#define FILE_MENU_ID		BASE_RES_ID+1
#define	EDIT_MENU_ID		BASE_RES_ID+2

#define ABOUT_ALERT_ID		400
#define	ABOUT_HELP_ID		401
#define NO_ROLL_ID			403

WindowPtr	gPictureWindow, gGameWindow;
Boolean		gDone, gWNEImplemented;
EventRecord	gTheEvent;
MenuHandle	gAppleMenu,gEditMenu,gFileMenu,gOptionsMenu,gSpecialMenu;
PicHandle	gThePicture;
int			gSndOn=0,gPauseOn=1,gPanicOn=0, gInCastle, gPartyNum,gNewChar,
			gCurItem, gInPrison, gSndNum,gLevelCounter;
DialogPtr	gDialog;
RGBColor	gNameBack, gStatsBack;

struct	CreatureInfo 
{
	Str255			name;
	unsigned char	type;
	unsigned char	status;		/* For use in editor only */
	unsigned char	instore;	/* Unused variable */
	unsigned char	level;
	Byte			attrib;
	Byte			dmg;
	Byte			def;
	Byte			hits;
};

struct	CreatureInfo	GameCreatures[104];						

/********************************** main *****************************/

main()
{
	ToolBoxInit();
	MenuBarInit();
	VarInit();
	OpenGame();
	MainLoop();
}

/******************************* VarInit ************************/
VarInit()
{
int	z;



	for (z=0;z<=104;z++)
		GameCreatures[z].status=99;		/* all slots open */
		
	gCurItem = 0;
	gLevelCounter=-1;					/* counts items per level */

}
/******************************* ToolBoxInit ************************/

ToolBoxInit()
{
	InitGraf (&thePort);
	InitFonts();
	FlushEvents (everyEvent, REMOVE_ALL_EVENTS);
	InitWindows();
	InitMenus();
	TEInit();
	InitDialogs (NIL_POINTER);
	InitCursor();
}

/**************************** MenuBarInit *****************************/

MenuBarInit()
{
	Handle	myMenuBar;
	
	myMenuBar =   GetNewMBar(BASE_RES_ID);	  /* Menu Index */
	SetMenuBar(myMenuBar);
	gFileMenu  = GetMHandle(FILE_MENU_ID);
	gAppleMenu = GetMHandle(APPLE_MENU_ID);
	gEditMenu  = GetMHandle(EDIT_MENU_ID);
	AddResMenu(gAppleMenu, 'DRVR');
	DrawMenuBar();
}

/********************** HandleEvent ***********************************/

HandleEvent()
{
	char	theChar;
	GrafPtr	oldPort;
	Rect	myRect;
	
	if (gWNEImplemented)
		WaitNextEvent(everyEvent,&gTheEvent,MIN_SLEEP,NIL_MOUSE_REGION);
	else
	{
		SystemTask();
		GetNextEvent(everyEvent, &gTheEvent);
	}
	
	switch (gTheEvent.what)
	{
		case updateEvt:							/* need to update chars too! */
 			GetPort(&oldPort);		 
			SetPort((WindowPtr)gTheEvent.message);
			BeginUpdate((WindowPtr)gTheEvent.message);
			EndUpdate((WindowPtr)gTheEvent.message);
 			SetPort(oldPort); 
			break;
		case nullEvent:
			HandleNull();
			break;
		case mouseDown:
			HandleMouseDown();
			break;
		case keyDown:
		case autoKey:
			theChar = gTheEvent.message & charCodeMask;
			if ((gTheEvent.modifiers & cmdKey) != 0)
				HandleMenuChoice(MenuKey(theChar));
			break;
	}
}

/********************** HandleNull ***********************************/

HandleNull()
{
	
}

/********************** HandleMouseDown ******************************/

HandleMouseDown()
{
	WindowPtr	whichWindow;
	short int	thePart;
	long int	menuChoice, windSize;
	
	thePart= FindWindow(gTheEvent.where, &whichWindow);
	switch(thePart)
	{
		case inMenuBar:
			menuChoice = MenuSelect(gTheEvent.where);
			HandleMenuChoice(menuChoice);
			break;
		case inSysWindow:
			SystemClick(&gTheEvent, whichWindow);
			break;
		}
}

/********************** HandleMenuChoice *****************************/

HandleMenuChoice(menuChoice)
long int	menuChoice;

{
	int	theMenu;
	int	theItem;
	
	if (menuChoice!=0)
	{
		theMenu = HiWord(menuChoice);
		theItem = LoWord(menuChoice);
		switch (theMenu)
		{
			case APPLE_MENU_ID:
				HandleAppleChoice(theItem);
				break;
			case FILE_MENU_ID:
				HandleFileChoice(theItem);
				break;
		}
		HiliteMenu(0);
	}
}

/********************** HandleAppleChoice *****************************/

HandleAppleChoice(theItem)
int	theItem;

{
	Str255		accName;
	int			accNumber;
	short int	itemNumber;
	DialogPtr	AboutDialog;
	
	switch(theItem)
	{
		case ABOUT_ITEM:
			NoteAlert(ABOUT_ALERT_ID,NIL_POINTER);
			break;
		case ABOUT_HELP:
			NoteAlert(ABOUT_HELP_ID,NIL_POINTER);
			break;
		default:
			GetItem(gAppleMenu, theItem, accName);
			accNumber=OpenDeskAcc(accName);
			break;
	}
}

/********************** HandleFileChoice *****************************/

HandleFileChoice(theItem)
int	theItem;
{
Boolean	Stop_Now;

	switch(theItem)
	{
		case NEW_ITEM:
			break;
		case OPEN_ITEM:
			OpenGame();
			break;
		case SAVE_ITEM:
			SaveGame();
			break;
		case QUIT_ITEM:
			gDone=TRUE;
			break;
	
	}
}


/********************** Mainloop ***********************************/

MainLoop()
{
	gDone = FALSE;
	gWNEImplemented = (NGetTrapAddress(WNE_TRAP_NUM, ToolTrap)!=
					   NGetTrapAddress(UNIMPL_TRAP_NUM, ToolTrap));
	while(gDone==FALSE)
	{
		HandleEvent();
	}
}

/************************ MainDialog ****************************/

MainDialog()
{

int			itemType, z,x,itemHit, inPrison,  dialogDone = FALSE; 
Handle		itemHandle;
Rect		itemRect;
Str255		text;

if (GameCreatures[104].status != 99)
{
	NoteAlert(128,NIL_POINTER);		/* no slots open */
}
 	gDialog=GetNewDialog(405, NIL_POINTER, MOVE_TO_FRONT);		 
		ShowWindow(gDialog);
		SetPort(gDialog);
		
		ListItem();
		
	GetDItem(gDialog, 11, &itemType, &itemHandle, &itemRect);
	SelIText ( gDialog,11,0,32767 );	
	
	NumToString(gCurItem,text);
	GetDItem(gDialog, 9, &itemType, &itemHandle, &itemRect);			/* get name */
	SetIText(itemHandle, text);
	

	while (dialogDone == FALSE)
	{
		ModalDialog(NIL_POINTER, &itemHit);
			switch (itemHit)
			{
				case 1:			/* DONE ... exit program 				*/
					SaveDialog();
					dialogDone = TRUE;
					DisposeDialog(gDialog);			 
					break;
				case 2:			/* ADD ... add it to the database 		*/
					for (x=0;x<=104;x++)
					  if (GameCreatures[x].status==99)
					  	{
					  	gCurItem=x;
					  	break;
					  	}
					NewItem();
					dialogDone = TRUE;
					DisposeDialog(gDialog);
					MainDialog();			 
					break;		 
				case 3:			/* SEARCH ... now go search for it		*/
					SearchItem();	
					break;
				case 5:			/* BACK ...backwards in database 	*/
					if (gCurItem-1<=0)
						gCurItem=0;
					else
						gCurItem--;
					ListItem();		 
					break;
				case 4:			/* FORWARD */
			    		gCurItem++;
						ListItem();
					break;	
				case 6:			/* MODIFY */
					NewItem();
					MainDialog();			 
					break;
				case 13:		/* UNDEAD */
 	  				TurnOffButton();									 
					GetDItem(gDialog, itemHit, &itemType, 
					&itemHandle, &itemRect);
					SetCtlValue (itemHandle,1);
					GameCreatures[gCurItem].type=UNDEAD;				 
					break;	
				case 14:		/* INSECT */
 	  				TurnOffButton();									 
					GetDItem(gDialog, itemHit, &itemType, 
					&itemHandle, &itemRect);
					SetCtlValue (itemHandle,1);
					GameCreatures[gCurItem].type=INSECT;				 
					break;
				case 15:		/* DRAGON */
 	  				TurnOffButton();									 
					GetDItem(gDialog, itemHit, &itemType, 
					&itemHandle, &itemRect);
					SetCtlValue (itemHandle,1);
					GameCreatures[gCurItem].type=DRAGON;				 
					break;						
				case 16:		/* HUMAN */
 	  				TurnOffButton();									 
					GetDItem(gDialog, itemHit, &itemType, 
					&itemHandle, &itemRect);
					SetCtlValue (itemHandle,1);
					GameCreatures[gCurItem].type=HUMANOID;				 
					break;
				case 17:		/* BLOB */
 	  				TurnOffButton();									 
					GetDItem(gDialog, itemHit, &itemType, 
					&itemHandle, &itemRect);
					SetCtlValue (itemHandle,1);
					GameCreatures[gCurItem].type=BLOB;				 
					break;						
				case 18:		/* GASEOUS */
 	  				TurnOffButton();									 
					GetDItem(gDialog, itemHit, &itemType, 
					&itemHandle, &itemRect);
					SetCtlValue (itemHandle,1);
					GameCreatures[gCurItem].type=GASEOUS;				 
					break;		
				case 19:		/* DNGMSTR */
 	  				TurnOffButton();									 
					GetDItem(gDialog, itemHit, &itemType, 
					&itemHandle, &itemRect);
					SetCtlValue (itemHandle,1);
					GameCreatures[gCurItem].type=DNGMSTR;				 
					break;	
				case 20:		/* ANIMAL */
 	  				TurnOffButton();									 
					GetDItem(gDialog, itemHit, &itemType, 
					&itemHandle, &itemRect);
					SetCtlValue (itemHandle,1);
					GameCreatures[gCurItem].type=ANIMAL;				 
					break;
				case 21:		/* HUMANOID */
 	  				TurnOffButton();									 
					GetDItem(gDialog, itemHit, &itemType, 
					&itemHandle, &itemRect);
					SetCtlValue (itemHandle,1);
					GameCreatures[gCurItem].type=HUMANOID;				 
					break;						
				case 22:		/* DEFENDER */
 	  				TurnOffButton();									 
					GetDItem(gDialog, itemHit, &itemType, 
					&itemHandle, &itemRect);
					SetCtlValue (itemHandle,1);
					GameCreatures[gCurItem].type=DEFENDER;				 
					break;
				case 23:		/* temp */
 	  				TurnOffButton();									 
					GetDItem(gDialog, itemHit, &itemType, 
					&itemHandle, &itemRect);
					SetCtlValue (itemHandle,1);
					GameCreatures[gCurItem].type=11;				 
					break;						
				case 24:		/* staff */
 	  				TurnOffButton();									 
					GetDItem(gDialog, itemHit, &itemType, 
					&itemHandle, &itemRect);
					SetCtlValue (itemHandle,1);
					GameCreatures[gCurItem].type=12;				 
					break;										
		}
	}
	
 }
 
/************************ TurnOffButton ****************************/	
TurnOffButton()
{
int				itemType;
Handle			itemHandle;
Rect			itemRect;	
ControlHandle	control;
int				z;
  
for (z=13;z<=24;z++)				
	{
		GetDItem(gDialog, z, &itemType, &itemHandle, &itemRect);
		SetCtlValue (itemHandle,0);
	}  
}

/************************ SearchItem ****************************/

SearchItem()
{

int			itemType, z,x,y,itemHit,  dialogDone = FALSE; 
Handle		itemHandle;
Rect		itemRect;
Str255		text;

TurnOffButton();
	for (z=0;z<=104;z++)					 
	{
		GetDItem(gDialog, 11, &itemType, &itemHandle, &itemRect);	/* get name */
			GetIText(itemHandle, text);
		if ( EqualString ( GameCreatures[z].name, text, FALSE, FALSE ) )
			gCurItem=z;					 
	}
	NumToString(gCurItem,text);
	GetDItem(gDialog, 9, &itemType, &itemHandle, &itemRect);			/* get name */
	SetIText(itemHandle, text);	

	GetDItem(gDialog, 11, &itemType, &itemHandle, &itemRect);			/* get name */
	SetIText(itemHandle, GameCreatures[gCurItem].name);	

	GetDItem(gDialog, 26, &itemType, &itemHandle, &itemRect);			/* get sttu */
	NumToString(GameCreatures[gCurItem].instore,text);
	SetIText(itemHandle, text);	

	GetDItem(gDialog, 28, &itemType, &itemHandle, &itemRect);			/* get level */
	NumToString(GameCreatures[gCurItem].level,text);
	SetIText(itemHandle, text);	

	GetDItem(gDialog, 30, &itemType, &itemHandle, &itemRect);			/* get name */
	NumToString(GameCreatures[gCurItem].attrib,text);
	SetIText(itemHandle, text);	

	GetDItem(gDialog, 32, &itemType, &itemHandle, &itemRect);			/* get name */
	NumToString(GameCreatures[gCurItem].dmg,text);
	SetIText(itemHandle, text);	

	GetDItem(gDialog, 34, &itemType, &itemHandle, &itemRect);			/* get name */
	NumToString(GameCreatures[gCurItem].def,text);
	SetIText(itemHandle, text);	

	GetDItem(gDialog, 36, &itemType, &itemHandle, &itemRect);			/* get name */
	NumToString(GameCreatures[gCurItem].hits,text);
	SetIText(itemHandle, text);	

y=13;
	for (x=1;x<=12;x++)
		{
			if (GameCreatures[gCurItem].type == x)
			{
			GetDItem(gDialog, y, &itemType, &itemHandle, &itemRect);
			SetCtlValue (itemHandle,1);
			}
		  y++;
		}
} 
 /************************ NewItem ****************************/

NewItem()
{

int			itemType, z,x,itemHit, inPrison,  dialogDone = FALSE; 
Handle		itemHandle;
Rect		itemRect;
Str255		text;
long		number;

  	
  	GameCreatures[gCurItem].status=1;		/* good item */
	NumToString(gCurItem,text);		/* record # */
	GetDItem(gDialog, 9, &itemType, &itemHandle, &itemRect);			/* get name */
	SetIText(itemHandle, text);

	GetDItem(gDialog, 11, &itemType, &itemHandle, &itemRect);			/* get name */
	GetIText(itemHandle, GameCreatures[gCurItem].name);

	GetDItem(gDialog, 26, &itemType, &itemHandle, &itemRect);			/* get name */
	GetIText(itemHandle, text);											/* get type */
	StringToNum(text,&number);			 
	GameCreatures[gCurItem].instore=number;
		
	GetDItem(gDialog, 28, &itemType, &itemHandle, &itemRect);			/* get name */
	GetIText(itemHandle, text);											/* get type */
	if (gCurItem>=0 && gCurItem<=7)
		gLevelCounter=1;
	else if (gCurItem>=8 && gCurItem<=15)		/*** TOTAL NUMBER OF ITEMS = 104 **/
		gLevelCounter=2;
	else if (gCurItem>=16 && gCurItem<=23)
		gLevelCounter=3;
	else if (gCurItem>=24 && gCurItem<=31)
		gLevelCounter=4;
	else if (gCurItem>=32 && gCurItem<=39)
		gLevelCounter=5;		
	else if (gCurItem>=40 && gCurItem<=47)
		gLevelCounter=6;	
	else if (gCurItem>=48 && gCurItem<=55)
		gLevelCounter=7;		
	else if (gCurItem>=56 && gCurItem<=63)
		gLevelCounter=8;
	else if (gCurItem>=64 && gCurItem<=71)
		gLevelCounter=9;		
	else if (gCurItem>=72 && gCurItem<=79)
		gLevelCounter=10;	
	else if (gCurItem>=80 && gCurItem<=87)
		gLevelCounter=11;		
	else if (gCurItem>=88 && gCurItem<=95)
		gLevelCounter=12;		
	else if (gCurItem>=96 && gCurItem<=103)
		gLevelCounter=13;	
	NumToString(gLevelCounter,text);										
	SetIText(itemHandle, text);
	GameCreatures[gCurItem].level=gLevelCounter;
	
	GetDItem(gDialog, 30, &itemType, &itemHandle, &itemRect);			/* get name */
	GetIText(itemHandle, text);											/* get type */
	StringToNum(text,&number);			 
	GameCreatures[gCurItem].attrib=number;
	
	GetDItem(gDialog, 32, &itemType, &itemHandle, &itemRect);			/* get name */
	GetIText(itemHandle, text);											/* get type */
	StringToNum(text,&number);			 
	GameCreatures[gCurItem].dmg=number;
	
	GetDItem(gDialog, 34, &itemType, &itemHandle, &itemRect);			/* get DEF */
	GetIText(itemHandle, text);											/* get type */
	StringToNum(text,&number);			 
	GameCreatures[gCurItem].def=number;
	
	GetDItem(gDialog, 36, &itemType, &itemHandle, &itemRect);			/* get name */
	GetIText(itemHandle, text);											/* get type */
	StringToNum(text,&number);			 
	GameCreatures[gCurItem].hits=number;
	
}

/************************ OpenGame *************************************/
OpenGame()
{

	SFReply		reply;
	Point		myPoint;
	SFTypeList	typeList;
	int			numTypes;
	int			z;
	long		count;
	short		rc,fRefNum;	
	
	myPoint.h	=100;
	myPoint.v	= 100;
	typeList[0] = 'RJB1';
	numTypes	= 1;

		
	FSOpen("\pGBCreatures",0,&fRefNum);	
		count = (sizeof(struct CreatureInfo)*104);
	 	FSRead ( fRefNum, &count, ((Ptr)GameCreatures));
		FSClose (fRefNum);
		fRefNum=0;			/* set to invalid # to avoid disk wipe-outs! */

MainDialog();
}


/************************ SaveGame *************************************/
SaveGame()
{
SFReply		reply;
Point		myPoint;
short		rc,fRefNum;
int			z;
long		count;
FInfo		fndrInfo;
OSType		fdType;
OSType		fdCreator;

myPoint.h	=100;
myPoint.v	= 100;

 
	Create ("\pGBCreatures", 0, 'RJGB', 'RJG1');
	if (reply.good)
	{	
		FSOpen("\pGBCreatures",0,&fRefNum);
	}	
	/* now write data to file */


		FSOpen("\pGBCreatures",0,&fRefNum);
	count = (sizeof(struct CreatureInfo)*104);
	 	FSWrite ( fRefNum,&count, ((Ptr)GameCreatures));
		fndrInfo.fdType='RJG1';		/* set file creator type */
		fndrInfo.fdCreator='RJGB';
		SetFInfo ("\pGBCreatures",0, &fndrInfo );	 	
		FSClose (fRefNum);
		fRefNum=0;				 /* set to invalid # to avoid disk wipe-outs! */

}
/************************ ListItem ****************************/

ListItem()
{

int			itemType, z,x,y,itemHit, inPrison,  dialogDone = FALSE; 
Handle		itemHandle;
Rect		itemRect;
Str255		text;

TurnOffButton();
	
	NumToString(gCurItem,text);
	GetDItem(gDialog, 9, &itemType, &itemHandle, &itemRect);			/* get name */
	SetIText(itemHandle, text);

	GetDItem(gDialog, 11, &itemType, &itemHandle, &itemRect);			/* get name */
	SetIText(itemHandle, GameCreatures[gCurItem].name);	

	GetDItem(gDialog, 26, &itemType, &itemHandle, &itemRect);			/* get name */
	NumToString(GameCreatures[gCurItem].instore,text);
	SetIText(itemHandle, text);	

	GetDItem(gDialog, 28, &itemType, &itemHandle, &itemRect);			/* get name */
	NumToString(GameCreatures[gCurItem].level,text);
	SetIText(itemHandle, text);	

	GetDItem(gDialog, 30, &itemType, &itemHandle, &itemRect);			/* get name */
	NumToString(GameCreatures[gCurItem].attrib,text);
	SetIText(itemHandle, text);	

	GetDItem(gDialog, 32, &itemType, &itemHandle, &itemRect);			/* get name */
	NumToString(GameCreatures[gCurItem].dmg,text);
	SetIText(itemHandle, text);	

	GetDItem(gDialog, 34, &itemType, &itemHandle, &itemRect);			/* get name */
	NumToString(GameCreatures[gCurItem].def,text);
	SetIText(itemHandle, text);	

	GetDItem(gDialog, 36, &itemType, &itemHandle, &itemRect);			/* get name */
	NumToString(GameCreatures[gCurItem].hits,text);
	SetIText(itemHandle, text);	

y=13;
	for (x=1;x<=12;x++)
		{
			if (GameCreatures[gCurItem].type == x)
			{
			GetDItem(gDialog, y, &itemType, &itemHandle, &itemRect);
			SetCtlValue (itemHandle,1);
			}
		  y++;
		}
} 
/************************ SaveDialog ****************************/

SaveDialog()
{

int			itemType, z,x,itemHit, inPrison,  dialogDone = FALSE; 
Handle		itemHandle;
Rect		itemRect;
Str255		text;


 	gDialog=GetNewDialog(128, NIL_POINTER, MOVE_TO_FRONT);		 
		ShowWindow(gDialog);
		SetPort(gDialog);

			GetDItem(gDialog, 1, &itemType, &itemHandle, &itemRect);
			PenSize(2,2);	
			InsetRect(&itemRect, -3,-3);
			FrameRoundRect(&itemRect, 16, 16);
			PenNormal();
			
	while (dialogDone == FALSE)
	{
		ModalDialog(NIL_POINTER, &itemHit);
			switch (itemHit)
			{
				case 1:			/* YES ... & exit program 		*/
					SaveGame();
					dialogDone = TRUE;
					DisposeDialog(gDialog);
					ExitToShell();			 
					break;
				case 2:			/* NO ... exit, no save 		*/
					NewItem();
					dialogDone = TRUE;
					DisposeDialog(gDialog);
					ExitToShell(); 
					break;		 
				case 3:			/* CANCEL ... no go search for it		*/
					MainDialog();	
					break;
			}
	}
}