/*********************************                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           /*********************************
**   DungEditor 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	NORTHWALL			130
#define	NORTHDOOR			135
#define	SOUTHWALL			131
#define	SOUTHDOOR			134
#define	WESTWALL			128
#define	WESTDOOR			132
#define	EASTWALL			129
#define	EASTDOOR			133
#define	NOWALL				136

#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	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;
Boolean		gDone, gWNEImplemented;
EventRecord	gTheEvent;
MenuHandle	gAppleMenu,gEditMenu,gFileMenu,gOptionsMenu,gSpecialMenu;
PicHandle	gThePicture;
int			gSndOn=0,gPauseOn=1,gPanicOn=0,gCurItem;
long		gLevel;			
DialogPtr	gDialog;
RGBColor	gColorBack;
Rect		gRoomRect, gWallRect;
CIconHandle	gNorthWall,gNorthDoor,gSouthWall,gSouthDoor,gWestWall,
			gWestDoor,gEastWall,gEastDoor,gNoWall;

struct	DungInfo 
{
	unsigned int	XY[10][10];		/*  x, y  rooms location */
	unsigned int	N[100];			/* 100 rooms w/north walls */
	unsigned int	S[100];			/* 100 rooms w/south walls */
	unsigned int	E[100];			/* 100 rooms w/east walls */
	unsigned int	W[100];			/* 100 rooms w/west walls */
	unsigned int	SA[100];
};
 
struct	DungInfo	TheDungeon[13];	/* 13 levels of 100 rooms */					

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

main()
{
	ToolBoxInit();
	MenuBarInit();
	VarInit();
	WindowInit();
	GetDateTime(&randSeed);				/* randomize using datetme */
	NewDungeon();
	MainLoop();
}

/******************************* VarInit ************************/
VarInit()
{
int	z,x,count,y;

	gCurItem = 0;

	gNorthWall=GetCIcon(NORTHWALL);
	gNorthDoor=GetCIcon(NORTHDOOR);
	gSouthWall=GetCIcon(SOUTHWALL);
	gSouthDoor=GetCIcon(SOUTHDOOR);
	gWestWall=GetCIcon(WESTWALL);
	gWestDoor=GetCIcon(WESTDOOR);
	gEastWall=GetCIcon(EASTWALL);
	gEastDoor=GetCIcon(EASTDOOR);
	gNoWall=GetCIcon(NOWALL);	
	
	gColorBack.red=52020;		 
	gColorBack.blue=39015;
	gColorBack.green=52020;
	
RGBBackColor(&gColorBack);	
		
for (gLevel=0;gLevel<=12;gLevel++)	/* initialize file */
{
for (x=0;x<=100;x++)
	{
		TheDungeon[gLevel].N[x]=0;
		TheDungeon[gLevel].S[x]=0;		
		TheDungeon[gLevel].E[x]=0;
		TheDungeon[gLevel].W[x]=0;
		TheDungeon[gLevel].SA[x]=0;
	}
}						

for (gLevel=0;gLevel<=12;gLevel++)
{
count=-1;
for (y=0;y<=9;y++)		/** sets all variables to correct room #s. */
  {
	for (x=0;x<=9;x++)
	{
		count++;
		TheDungeon[gLevel].XY[x][y]=count;
	}
  }
 }
}
/******************************* 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);
	gAppleMenu = GetMHandle(APPLE_MENU_ID);
	gEditMenu  = GetMHandle(EDIT_MENU_ID);
	AddResMenu(gAppleMenu, 'DRVR');
	DrawMenuBar();
}

/********************** WindowInit ******************************/
WindowInit()
{
	gPictureWindow=GetNewCWindow(BASE_RES_ID, NIL_POINTER, 
		MOVE_TO_FRONT);
	ShowWindow(gPictureWindow);
	SetPort(gPictureWindow);
}		

/********************** 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;
	int			x;

	thePart= FindWindow(gTheEvent.where, &whichWindow);
	switch(thePart)
	{
		case inMenuBar:
			menuChoice = MenuSelect(gTheEvent.where);
			HandleMenuChoice(menuChoice);
			break;
		case inSysWindow:
			SystemClick(&gTheEvent, whichWindow);
			break;
		case inContent:
			EditRoom();
			break; 
		}
}

/************************ EditRoom ****************************/

EditRoom()
{

int			slot, z,zz,x,y,inRect,roomNo; 
Handle		itemHandle;
Rect		itemRect,wallTypeRect;
Str255		text;
short		status;

roomNo=-1;					/* current room no */

for (y=0;y<=9;y++)			/* y down loop */	
{
	for (x=0;x<=9;x++)		/* x across loop */
	{
	  SetRect(&itemRect,40+(x*16),60+(y*16),56+(x*16),76+(y*16));
		roomNo++;
		  if (PtInRect(gTheEvent.where, &itemRect))
			{
				InvertRect(&itemRect);
				goto roomfound;
			}
	}
}

return;
			
roomfound:	
	TheDungeon[gLevel].XY[x][y]=roomNo;
		TextMode(srcCopy);
			MoveTo(320,30);DrawString("\pRoom No:ÊÊ");
		NumToString(TheDungeon[gLevel].XY[x][y],text);
	ParamText(text,0,0,0);
	
	MoveTo(380,30);DrawString(text);
		MoveTo(320,50);DrawString("\pRoom No:ÊÊ");	
			NumToString(gLevel,text);
			MoveTo(380,50);DrawString(text);	
		roomNo=TheDungeon[gLevel].XY[x][y];
	EditDialog(itemRect,roomNo);
}
/************************ EditDialog ****************************/

EditDialog(itemRect,roomNo)
Rect	itemRect;
int		roomNo;
{

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


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

			GetDItem(gDialog, 1, &itemType, &itemHandle, &itemRect);
					
			GetDItem(gDialog, 4, &itemType, &itemHandle, &itemRect);
			NumToString(TheDungeon[gLevel].N[roomNo],text);
			SetIText(itemHandle, text);	

			GetDItem(gDialog, 5, &itemType, &itemHandle, &itemRect);
			NumToString(TheDungeon[gLevel].S[roomNo],text);
			SetIText(itemHandle, text);
						
			GetDItem(gDialog, 6, &itemType, &itemHandle, &itemRect);
			NumToString(TheDungeon[gLevel].E[roomNo],text);
			SetIText(itemHandle, text);
			
			GetDItem(gDialog, 7, &itemType, &itemHandle, &itemRect);
			NumToString(TheDungeon[gLevel].W[roomNo],text);
			SetIText(itemHandle, text);

			GetDItem(gDialog, 8, &itemType, &itemHandle, &itemRect);
			NumToString(TheDungeon[gLevel].SA[roomNo],text);
			SetIText(itemHandle, text);			
			
			
	while (dialogDone == FALSE)
	{
		ModalDialog(NIL_POINTER, &itemHit);
			switch (itemHit)
			{
				case 1:			/* YES ... & exit program 		*/
					dialogDone = TRUE;
						GetDItem(gDialog, 4, &itemType, &itemHandle, &itemRect);			  /* North */
						GetIText(itemHandle, text);
						StringToNum(text, &number);
						if (number==1)
							TheDungeon[gLevel].S[roomNo-10]=number;
						if (number==2)
								TheDungeon[gLevel].S[roomNo-10]=number;
								TheDungeon[gLevel].N[roomNo]=number;
						
						GetDItem(gDialog, 5, &itemType, &itemHandle, &itemRect);			  /* South */
						GetIText(itemHandle, text);
							StringToNum(text, &number);
						if (number==1)
							TheDungeon[gLevel].N[roomNo+10]=number;
						if (number==2)
							TheDungeon[gLevel].N[roomNo+10]=number;
							TheDungeon[gLevel].S[roomNo]=number;
						
						GetDItem(gDialog, 6, &itemType, &itemHandle, &itemRect);			  /* East */
						GetIText(itemHandle, text);
							StringToNum(text, &number);
						if (number==1)							
								TheDungeon[gLevel].W[roomNo+1]=number;
						if (number==2)								
							TheDungeon[gLevel].W[roomNo+1]=number;
							TheDungeon[gLevel].E[roomNo]=number;
				
						
						GetDItem(gDialog, 7, &itemType, &itemHandle, &itemRect);			  /* West */
						GetIText(itemHandle, text);
							StringToNum(text, &number);
						if (number==1)
							TheDungeon[gLevel].E[roomNo-1]=number;
						if (number==2)
							TheDungeon[gLevel].E[roomNo-1]=number;							
							TheDungeon[gLevel].W[roomNo]=number;
						
						GetDItem(gDialog, 8, &itemType, &itemHandle, &itemRect);			  /* Spec. Attrib */
						GetIText(itemHandle, text);
							StringToNum(text, &number);
							TheDungeon[gLevel].SA[roomNo]=number;
						DisposeDialog(gDialog);
						SetPort(gPictureWindow);
						NewDungeon();							
					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();
	}
}

/************************ TurnOffButton ****************************/	
TurnOffButton()
{
int				itemType;
Handle			itemHandle;
Rect			itemRect;	
ControlHandle	control;
int				z;
  
for (z=13;z<=24;z++)				
	{
	
	}  
}

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

	SFReply		reply;
	Point		myPoint;
	SFTypeList	typeList;
	int			numTypes,itemType, z,x,itemHit, inPrison,  dialogDone = FALSE;
	long		count;
	short		rc,fRefNum;	
	Handle		itemHandle;
	Rect		itemRect;
	Str255		text;	
	
	myPoint.h	=100;
	myPoint.v	= 100;
	typeList[0] = 'RJG1';
	numTypes	= 1;


	 gDialog=GetNewDialog(500, NIL_POINTER, MOVE_TO_FRONT);
 		ShowWindow(gDialog);
 		  SetPort(gDialog);
			
	while (dialogDone == FALSE)
	{
		ModalDialog(NIL_POINTER, &itemHit);
			switch (itemHit)
			{
				case 1:		
					dialogDone = TRUE;
						GetDItem(gDialog, 3, &itemType, &itemHandle, &itemRect);			   
						GetIText(itemHandle, text);
						StringToNum(text,&gLevel);	
						DisposeDialog(gDialog);
 		  				SetPort(gPictureWindow);					
					break;

			}
	} 		
				
	FSOpen("\pDungeon",0,&fRefNum);		
		count = (sizeof(struct DungInfo)*13);   
	 	FSRead ( fRefNum, &count, ((Ptr)TheDungeon));
		FSClose (fRefNum);
		fRefNum=0;	 	 
		  
		NewDungeon();
}


/************************ 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 ("\pDungeon", 0, 'RJGB', 'RJG1');	
		FSOpen("\pDungeon",0,&fRefNum);
			
	/* now write data to file */

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

}

/************************ 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 3:			/* CANCEL ... no go search for it		*/
					gCurItem=999;
					MainLoop();	
					break;
			}
	}
}

/************************ NewDungeon ****************************/

NewDungeon()			/* displays dungeon icons */
{

int			z,zz,x,y,roomNo,wallType; 
Rect		roomRect,clearRect;

SetRect(&clearRect,30,20,350,300);
	EraseRect(&clearRect);	
		
x = 225;y = 30;

				MoveTo(50,30);
					DrawString("\pRoom Attributes:");
					MoveTo(x,30);DrawString("\pWall types:");
					MoveTo(x+20,56);DrawString("\p 5 = Poisoner");
					MoveTo(x+20,76);DrawString("\p11 = Teleporter");
					MoveTo(x+20,96);DrawString("\p13 = Extinguish Spells");
				 	MoveTo(x+20,116);DrawString("\p13 = Extinguish Spells");
				 	MoveTo(x+20,136);DrawString("\pEast Wall");
				 	MoveTo(x+20,156);DrawString("\pEast Door");
				 	MoveTo(x+20,176);DrawString("\pEast Door");
				 	MoveTo(x+20,196);DrawString("\pEast Door");

for (y=0;y<=9;y++)
{
for (x=0;x<=9;x++)
	{
	roomNo=TheDungeon[gLevel].XY[x][y];
		SetRect(&roomRect,40+(x*16),60+(y*16),56+(x*16),76+(y*16));
		
		if (TheDungeon[gLevel].N[roomNo]==0)
 			PlotCIcon(&roomRect,gNorthWall);
 		else if (TheDungeon[gLevel].N[roomNo]==1)
 			PlotCIcon(&roomRect,gNorthDoor);
		else if (TheDungeon[gLevel].N[roomNo]==2)
 			PlotCIcon(&roomRect,gNoWall);
 			 						
		if (TheDungeon[gLevel].S[roomNo]==0)
 			PlotCIcon(&roomRect,gSouthWall);
 		else if (TheDungeon[gLevel].S[roomNo]==1)
			PlotCIcon(&roomRect,gSouthDoor);
		else if (TheDungeon[gLevel].S[roomNo]==2)
 			PlotCIcon(&roomRect,gNoWall);
 			
		if (TheDungeon[gLevel].E[roomNo]==0)
 			PlotCIcon(&roomRect,gEastWall);
 		else if (TheDungeon[gLevel].E[roomNo]==1)
 			PlotCIcon(&roomRect,gEastDoor); 
		else if (TheDungeon[gLevel].E[roomNo]==2)
 			PlotCIcon(&roomRect,gNoWall);
 			
		if (TheDungeon[gLevel].W[roomNo]==0)
 			PlotCIcon(&roomRect,gWestWall);
 		else if (TheDungeon[gLevel].W[roomNo]==1)
 			PlotCIcon(&roomRect,gWestDoor);	
		else if (TheDungeon[gLevel].W[roomNo]==2)
 			PlotCIcon(&roomRect,gNoWall);
 	
 	 	if (TheDungeon[gLevel].SA[roomNo]>0)
 			InvertRect(&roomRect);	 		
 			
 	}
 }
}
