#include <quickdraw.h>
#include <menu.h>
#include <window.h>
#include <dialog.h>
#include <textedit.h>
#include <event.h>
#include <desk.h>
#include <control.h>
#include <inits.h>
#include <package.h>
#include <pb.h>
#include <syserr.h>
#include <resource.h>
#define maxControls 10
#define sumControls 50
#define windowBase 200
#define dialogBase 300
#define menuBase 400
#define controlBase 500
#define numWindows 5
#define raceWind 0
#define classWind 1
#define statusWind 2
#define alignWind 3
#define statistWind 4
#define numRace 6
#define norace 0
#define human 1
#define elf 2
#define dwarf 3
#define gnome 4
#define hobbit 5
#define numClass 8
#define fighter 0
#define mage 1
#define priest 2
#define thief 3
#define bishop 4
#define samurai 5
#define lord 6
#define ninja 7
#define numStatus 8
#define healthy 0
#define afraid 1
#define asleep 2
#define paralysed 3
#define stoned 4
#define dead 5
#define ashes 6
#define lost 7
#define numAlign 4
#define noalign 0
#define nice 1
#define neutral 2
#define evil 3
#define numStatist 10
#define Strength 0
#define Intelligence 1
#define Piety 2
#define Vitality 3
#define Agility 4
#define Luck 5
#define Gold 6
#define Experience 7
#define ActHits 8
#define MaxHits 9
#define numDialogs 5
#define aboutDialog 0
#define saveDialog 1
#define charDialog 2
#define opWrDialog 3
#define ioErrDialog 4
#define saveItem 1
#define discardItem 2
#define cancelItem 3
#define numMenus 3
#define apMenu 0
#define fileMenu 1
#define charMenu 2
/* Start of character storage info */
#define charBlock 186 /* size of storage in file for each character */
#define nameLength 0
#define charName 1
#define raceLoc 33
#define classLoc 34
#define statusLoc 38
#define alignLoc 39
#define strengthLoc 40
#define IQLoc 41
#define pietyLoc 42
#define vitalityLoc 43
#define agilityLoc 44
#define luckLoc 45
#define goldLoc 54
#define experienceLoc 106
#define actHitsLoc 114
#define maxHitsLoc 116
/* Start of program info */
#define DlgTop 100
#define DlgLeft 85
MenuHandle myMenu[numMenus];
EventRecord curEvent;
WindowRecord wRecord;
WindowPtr curWindow, myWindow[numWindows];
ControlHandle curControl, myControl[numWindows][maxControls];
Rect limitRect;
short numControls[numWindows] = { numRace, numClass, numStatus, numAlign, numStatist };
short controlLoc[sumControls] = { raceLoc, classLoc, statusLoc, alignLoc, strengthLoc,
IQLoc, pietyLoc, vitalityLoc, agilityLoc,luckLoc,
goldLoc, experienceLoc, actHitsLoc, maxHitsLoc };
short curFile ;
unsigned char stat[charBlock];
Str255 * chName;
Boolean Dirty, ErrorFlag, FOPENED = FALSE;
setmenus() /* set up menus */
{
int menu;
myMenu[apMenu] = GetMenu(1);
AddResMenu(myMenu[apMenu], 'DRVR');
InsertMenu(myMenu[apMenu], 0);
for (menu = fileMenu; menu <= charMenu; menu++) {
myMenu[menu] = GetMenu(menuBase + menu);
InsertMenu(myMenu[menu], 0);
}
for (menu = 1; menu <= 4; menu++)
DisableItem(myMenu[charMenu], menu);
DisableItem(myMenu[fileMenu], 2);
DrawMenuBar();
}
initialize()
{
InitGraf(&thePort);
InitFonts();
SetEventMask(everyEvent - keyUpMask);
FlushEvents(everyEvent, 0);
InitWindows();
InitMenus();
TEInit();
InitDialogs(0L);
SetCursor(&arrow);
setmenus();
SetRect(&limitRect, 4, 24, 508, 338);
curWindow = 0L;
}
IOCheck(resCode) /* check for IO errors */
OSErr resCode;
{
int alertDlg, ignore;
long longresult;
Str255 * errString;
switch (resCode) {
case noErr : return;
case opWrErr : alertDlg = opWrDialog;
break;
default : alertDlg = ioErrDialogg;
longresult = resCode;
NumToString(longresult, errString);
ParamText(errString, "\P ", "\P ", "\P ");
}
InitCursor();
ignore = StopAlert(dialogBase + alertDlg, 0L);
ErrorFlag = TRUE;
}
openfile() /* ask for file to open */
{
Point dlgOrigin;
char fType[30];
SFReply theReply;
OSErr resultCode;
SetPt(&dlgOrigin, DlgTop, DlgLeft);
strcpy(fType, "SAVE");
SFGetFile(pass(dlgOrigin), "\P ", 0L, 1, fType, 0L, &theReply);
if (theReply.good) {
resultCode = FSOpen(theReply.fName, theReply.vRefNum, &curFile);
IOCheck(resultCode);
FOPENED = TRUE;
EnableItem(myMenu[fileMenu], 2);
DisableItem(myMenu[fileMenu], 1);
EnableItem(myMenu[charMenu], 1);
}
}
closeDA() /* close a desk accesory */
{
WindowPeek whichWindow;
int accNum;
whichWindow = (WindowPeek) FrontWindow();
accNum = whichWindow->windowKind;
CloseDeskAcc(accNum);
}
closewindows() /* close all windows */
{
int window;
for (window = raceWind; window <= statistWind; window++)
DisposeWindow(myWindow[window]);
curWindow = 0L;
}
closefile() /* close a file */
{
int theItem;
OSErr resultCode;
if ((curWindow != 0L) && (FrontWindow() == curWindow))
closewindows();
if (FrontWindow() != 0L)
closeDA();
resultCode = FSClose(curFile);
FOPENED = FALSE;
DisableItem(myMenu[charMenu], 1);
EnableItem(myMenu[fileMenu], 1);
DisableItem(myMenu[fileMenu], 2);
}
getchname(theName) /* get character to edit */
Str255 * theName;
{
DialogPtr charDlg;
Handle IHandle;
Rect IRect;
int itemNum, IType;
charDlg = GetNewDialog(dialogBase + charDialog, 0L, -1L);
do
ModalDialog(0L, &itemNum);
while ((itemNum != OK) && (itemNum != Cancel));
if (itemNum == Cancel) {
theName->length = 3;
strcpy(&(theName->text), "???");
}
else {
GetDItem(charDlg, 4, &IType, &IHandle, &IRect);
GetIText(IHandle, theName);
}
DisposDialog(charDlg);
}
updateStats() /* draws statistics on window */
{
static char * slabel[10] = { "strength ", "intellect ", "piety ", "vitality ", "agility ",
"luck ", "gold ", "experience", "actual HPs", "max HPs " };
static int hp[10] = { 15, 15, 15, 260, 260, 260, 15, 15, 260, 260 },
vp[10] = { 34, 59, 84, 34, 59, 84, 134, 159, 134, 159 };
int label;
SetPort(myWindow[statistWind]);
for (label = Strength; label <= MaxHits; label++) {
MoveTo(hp[label], vp[label]);
DrawText(slabel[label], 0, 10);
}
}
scale(ItoL, ip, lp) /* scales ints <-> longs */
unsigned char ItoL;
unsigned int * ip;
unsigned long * lp;
{
float tmp;
if (ItoL) {
tmp = ((float) *ip)/32000;
*lp = 2147483000*tmp;
}
else {
tmp = ((float) *lp)/2147483000;
*ip = 32000*tmp;
}
}
openwindows() /* opens all windows */
{
int wID, cID, * intPtr, tmp, ctlCount = 0, localBase = controlBase;
for (wID = raceWind; wID <= statistWind; wID++) {
myWindow[wID] = GetNewWindow(windowBase + wID, 0L, -1L);
for (cID = 0; cID < numControls[wID]; cID++)
myControl[wID][cID] = GetNewControl(localBase + cID, myWindow[wID]);
if (wID < statistWind)
SetCtlValue(myControl[wID][stat[controlLoc[wID]]], 1);
else {
for (cID = 0; cID < numControls[wID]; cID++)
if (cID < Gold)
SetCtlValue(myControl[wID][cID], stat[controlLoc[wID + cID]]);
else if (cID != Experience) {
intPtr = &(stat[controlLoc[wID + cID]]);
SetCtlValue(myControl[wID][cID], *intPtr);
}
else {
scale(0, &tmp, &(stat[experienceLoc]));
SetCtlValue(myControl[wID][cID], tmp);
}
updateStats();
}
localBase += numControls[wID];
}
curWindow = myWindow[wID - 1];
}
rdchar() /* reads character stats from file */
{
long blocklen = charBlock;
int count, chindex;
getchname(chName);
if (chName->text[0] == '?')
return;
for (chindex = 0; chindex < 20; chindex++) {
SetFPos(curFile, fsFromStart, chindex*blocklen);
FSRead(curFile, &blocklen, stat);
for (count = 1; count <= stat[0]; count++)
if (stat[count] != chName->text[count - 1])
break;
if (count > stat[0]) {
SetFPos(curFile, fsFromMark, -blocklen);
break;
}
}
if (chindex < 20) {
Dirty = FALSE;
openwindows();
DisableItem(myMenu[fileMenu], 2);
DisableItem(myMenu[charMenu], 1);
for (count = 2; count <= 4; count++)
EnableItem(myMenu[charMenu], count);
}
}
wrchar() /* write character stats */
{
long blocklen = charBlock;
long curPos;
FSWrite(curFile, &blocklen, stat);
SetFPos(curFile, fsFromMark, -blocklen);
Dirty = FALSE;
}
clchar() /* close a character */
{
int theItem;
if (Dirty) {
ParamText(chName, "\P ", "\P ", "\P ");
theItem = CautionAlert(dialogBase + saveDialog, 0L);
switch (theItem) {
case saveItem : wrchar();
break;
case discardItem : break;
case cancelItem : return;
}
}
closewindows();
EnableItem(myMenu[fileMenu], 2);
EnableItem(myMenu[charMenu], 1);
for (theItem = 2; theItem <= 4; theItem++)
DisableItem(myMenu[charMenu], theItem);
}
brag() /* do about stuff */
{
int ignore;
ignore = Alert(dialogBase + aboutDialog, 0L);
}
doCommand(eventloc) /* processes commands */
Point eventloc;
{
unsigned long mResult;
char name[30];
short theMenu, theItem;
long ticks;
mResult = MenuSelect(pass(eventloc));
theMenu = mResult >> 16;
theItem = mResult;
switch (theMenu - menuBase) {
case -399 : if (theItem == 1)
brag();
else {
GetItem(myMenu[apMenu], theItem, name);
OpenDeskAcc(name);
}
break;
case fileMenu : switch (theItem) {
case 1 : openfile();
break;
case 2 : closefile();
break;
case 3 : if (Dirty)
clchar();
if (FOPENED)
closefile();
_exit();
}
break;
case charMenu : switch (theItem) {
case 1 : rdchar();
break;
case 2 : wrchar();
break;
case 3 : clchar();
break;
case 4 : clchar();
break;
}
break;
default : break;
}
HiliteMenu(0);
}
pascal void scrollit(whichControl, whichPart) /* pascal action procedure for scrolling */
ControlHandle whichControl;
int whichPart;
{
int change = 0;
switch (whichPart) {
case inUpButton :;
case inPageUp : change--;
break;
case inDownButton :;
case inPageDown : change++;
break;
default :;
}
if (whichPart)
SetCtlValue(whichControl, GetCtlValue(whichControl) + change);
}
docontent() /* clicked in windows */
{
int controlPart, control, window, button, localBase = controlBase;
int * intPtr, tmpInt;
if (curWindow != FrontWindow()) {
SelectWindow(curWindow);
return;
}
else {
GlobalToLocal(&curEvent.where);
if (controlPart = FindControl(pass(curEvent.where), curWindow, &curControl))
if (curWindow == myWindow[statistWind]) {
Dirty = TRUE;
if (controlPart == inThumb)
controlPart = TrackControl(curControl, pass(curEvent.where), -1L);
else
controlPart = TrackControl(curContro
l, pass(curEvent.where), scrollit);
for (control = Strength; control <= MaxHits; control++)
if (curControl == myControl[statistWind][control])
if (control < Gold)
stat[controlLoc[statistWind + control]] = GetCtlValue(curControl);
else if (control != Experience) {
intPtr = &(stat[controlLoc[statistWind + control]]);
*intPtr = GetCtlValue(curControl);
}
else {
tmpInt = GetCtlValue(curControl);
scale(1, &tmpInt, &(stat[experienceLoc]));
}
}
else if (TrackControl(curControl, pass(curEvent.where), -1L) == inCheckBox) {
Dirty = TRUE;
SetCtlValue(curControl, 1);
for (window = raceWind; curWindow != myWindow[window]; window++)
;
for (button = 0; button < numControls[window]; button++)
if (myControl[window][button] == curControl)
stat[controlLoc[window]] = button;
else
SetCtlValue(myControl[window][button], 0);
}
}
}
DoActivate() /* Handle activate events */
{
WindowPeek whichWindow;
WindowPtr thisWindow;
ControlHandle whichControl;
int windnum;
thisWindow = (WindowPtr) curEvent.message;
for (windnum = 0; windnum < numWindows; windnum++)
if (thisWindow == myWindow[windnum])
break;
if (windnum < numWindows) {
whichWindow = (WindowPeek) thisWindow;
SetPort(thisWindow);
if (curEvent.modifiers & 1) {
curWindow = thisWindow;
for (whichControl = whichWindow->controlList; whichControl != 0L; whichControl = (*whichControl)->nextControl)
HiliteControl(whichControl, 0);
}
else {
for (whichControl = whichWindow->controlList; whichControl != 0L; whichControl = (*whichControl)->nextControl)
HiliteControl(whichControl, 255);
}
}
}
DoUpdate()
{
WindowPtr thisWindow;
int windnum;
thisWindow = (WindowPtr) curEvent.message;
for (windnum = 0; windnum < numWindows; windnum++)
if (thisWindow == myWindow[windnum])
break;
if (windnum < numWindows) {
curWindow = thisWindow;
BeginUpdate(curWindow);
DrawControls(curWindow);
if (windnum == statistWind)
updateStats();
EndUpdate(curWindow);
}
}
main()
{
int code;
initialize();
for (;;) {
SystemTask();
GetNextEvent(everyEvent, &curEvent);
switch (curEvent.what) {
case mouseDown :
code = FindWindow(pass(curEvent.where), &curWindow);
switch (code) {
case inDesk : break;
case inMenuBar : doCommand(pass(curEvent.where));
break;
case inSysWindow: SystemClick(&curEvent, curWindow);
break;
case inDrag : DragWindow(curWindow, pass(curEvent.where), &limitRect);
break;
case inContent : docontent();
break;
default : break;
}
break;
case activateEvt :
DoActivate();
break;
case updateEvt :
DoUpdate();
break;
default :
break;
}
}
}