mirror of
https://github.com/StevenMcLeod/Freecell68k.git
synced 2024-11-27 02:49:54 +00:00
344 lines
7.8 KiB
C
344 lines
7.8 KiB
C
#include "gamewind.h"
|
|
#include "gamewindlow.h"
|
|
#include "common.h"
|
|
#include "pstring.h"
|
|
#include "strntol.h"
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#define TITLE_PREF "\pFreeCell - #"
|
|
#define DLOG_OPEN 128
|
|
#define DLOG_OPEN_INPUT 3
|
|
#define DLOG_ABOUT 129
|
|
|
|
typedef struct {
|
|
short dlgMaxIndex;
|
|
Handle itmHndl;
|
|
Rect itmRect;
|
|
short itmType;
|
|
Byte itmData[];
|
|
} DialogItemList;
|
|
|
|
static pascal Boolean DigitInputFilter(DialogPtr theDialog,
|
|
EventRecord *theEvent, short *itemHit);
|
|
static pascal Boolean AboutFilter(DialogPtr theDialog,
|
|
EventRecord *theEvent, int *itemHit);
|
|
|
|
WindowPtr WindCreateTestEnv(Rect *bounds, StringPtr title) {
|
|
WindowPtr theWind;
|
|
Rect windRect;
|
|
|
|
title = title ? title : "\pTest Area";
|
|
theWind = NewWindow(0L, bounds, title, true,
|
|
noGrowDocProc, (WindowPtr) -1L, true, 0);
|
|
|
|
return theWind;
|
|
}
|
|
|
|
WindowPtr WindCreateGame(FCState *state) {
|
|
WindowPtr theWind;
|
|
Rect boundsRect;
|
|
Rect windRect;
|
|
StringPtr titleString;
|
|
unsigned char gameNumBuf[6];
|
|
Pattern bkpat;
|
|
/*
|
|
titleString = (StringPtr) NewPtr(sizeof(Str255));
|
|
if(!titleString) return NULL;
|
|
memcpy(titleString, TITLE_PREF, sizeof(TITLE_PREF));
|
|
NumToString(state->seedno, gameNumBuf);
|
|
strcat_p(titleString, gameNumBuf);*/
|
|
|
|
SetRect(&windRect, 0, 0, WIND_XLENGTH, WIND_YLENGTH);
|
|
boundsRect = screenBits.bounds;
|
|
boundsRect.top += 20;
|
|
CentreRect(&windRect, &boundsRect);
|
|
theWind = NewWindow(0L, &windRect, "\p", true, noGrowDocProc,
|
|
(WindowPtr) -1L, true, 0);
|
|
/*DisposPtr(titleString);*/
|
|
if(theWind) {
|
|
SetPort(theWind);
|
|
GetIndPattern(&bkpat, sysPatListID, 21);
|
|
BackPat(bkpat);
|
|
SetWRefCon(theWind, (long) state);
|
|
}
|
|
return theWind;
|
|
}
|
|
|
|
void WindUpdateTitle(WindowPtr theWind) {
|
|
StringPtr titleString;
|
|
unsigned char gameNumBuf[6];
|
|
FCState *state = (FCState *) GetWRefCon(theWind);
|
|
|
|
titleString = (StringPtr) NewPtr(sizeof(Str255));
|
|
if(!titleString) return;
|
|
memcpy(titleString, TITLE_PREF, sizeof(TITLE_PREF));
|
|
NumToString(state->seedno, gameNumBuf);
|
|
strcat_p(titleString, gameNumBuf);
|
|
SetWTitle(theWind, titleString);
|
|
DisposPtr(titleString);
|
|
}
|
|
|
|
ushort DlogOpenGame(void) {
|
|
DialogPtr theDialog;
|
|
Rect dlogRect, boundsRect;
|
|
short itemNo;
|
|
Handle textboxHandle;
|
|
volatile Size textboxHndlSize;
|
|
long inputText;
|
|
|
|
theDialog = GetNewDialog(DLOG_OPEN, NULL, (WindowPtr) -1);
|
|
if(!theDialog) return -1;
|
|
dlogRect = theDialog->portRect;
|
|
boundsRect = screenBits.bounds;
|
|
boundsRect.top += 20;
|
|
CentreRect(&dlogRect, &boundsRect);
|
|
MoveWindow(theDialog, dlogRect.left, dlogRect.top, true);
|
|
ShowWindow(theDialog);
|
|
|
|
do {
|
|
do {
|
|
ModalDialog(&DigitInputFilter, &itemNo);
|
|
if(itemNo == cancel) {
|
|
inputText = -1;
|
|
goto err;
|
|
}
|
|
} while(itemNo != ok);
|
|
|
|
GetDItem(theDialog, DLOG_OPEN_INPUT, &itemNo,
|
|
&textboxHandle, &boundsRect);
|
|
textboxHndlSize = GetHandleSize(textboxHandle);
|
|
/* Ensure whitespace before / after string */
|
|
HLock(textboxHandle);
|
|
inputText = strntol(*textboxHandle, textboxHndlSize, NULL, 10);
|
|
HUnlock(textboxHandle);
|
|
if(inputText < 1 || inputText > 32000) {
|
|
SysBeep(1);
|
|
} else {
|
|
break;
|
|
}
|
|
} while(true);
|
|
|
|
err:
|
|
DisposDialog(theDialog);
|
|
return (ushort) inputText;
|
|
}
|
|
|
|
pascal Boolean DigitInputFilter(DialogPtr theDialog, EventRecord *theEvent,
|
|
short *itemHit) {
|
|
char theChar;
|
|
|
|
if(theEvent->what == keyDown || theEvent->what == autoKey) {
|
|
theChar = theEvent->message & 0xFF;
|
|
if(theChar == '\r' || theChar == '\x03') {
|
|
*itemHit = ok;
|
|
return true;
|
|
} else if(!isdigit(theChar) && theChar != '\b') {
|
|
SysBeep(1);
|
|
theEvent->what = nullEvent;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void DlogAbout(void) {
|
|
DialogPtr theDialog;
|
|
Rect dlogRect;
|
|
Rect boundsRect;
|
|
short itemNo;
|
|
|
|
theDialog = GetNewDialog(DLOG_ABOUT, NULL, (WindowPtr) -1);
|
|
if(!theDialog) return;
|
|
dlogRect = theDialog->portRect;
|
|
boundsRect = screenBits.bounds;
|
|
boundsRect.top += 20;
|
|
boundsRect.bottom /= 2;
|
|
CentreRect(&dlogRect, &boundsRect);
|
|
MoveWindow(theDialog, dlogRect.left, dlogRect.top, true);
|
|
ShowWindow(theDialog);
|
|
ModalDialog(&AboutFilter, &itemNo);
|
|
DisposDialog(theDialog);
|
|
}
|
|
|
|
pascal Boolean AboutFilter(DialogPtr theDialog, EventRecord *theEvent,
|
|
int *itemHit) {
|
|
int windowCode;
|
|
WindowPtr theWindow;
|
|
|
|
if(theEvent->what != mouseDown)
|
|
return false;
|
|
windowCode = FindWindow(theEvent->where, &theWindow);
|
|
if(windowCode != inContent || theWindow != theDialog)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
void DrawGameInit(void) {
|
|
Point drawPoint;
|
|
ushort i;
|
|
|
|
drawPoint.v = CARD_BD_Y;
|
|
drawPoint.h = CARD_BD_X;
|
|
for(i = 0; i < FC_STORES; ++i) {
|
|
DrawEmptyFrame(drawPoint);
|
|
drawPoint.h += CARD_ST_X + CARD_XLENGTH;
|
|
}
|
|
|
|
drawPoint.h = WIND_XLENGTH - CARD_BD_X - CARD_XLENGTH;
|
|
for(i = 0; i < 4; ++i) {
|
|
DrawEmptyFrame(drawPoint);
|
|
drawPoint.h -= CARD_ST_X + CARD_XLENGTH;
|
|
}
|
|
}
|
|
|
|
void ForceRedraw(void) {
|
|
GrafPtr thePort;
|
|
GetPort(&thePort);
|
|
InvalRect(&thePort->portRect);
|
|
}
|
|
|
|
void DrawAll(FCState *state) {
|
|
DrawClear();
|
|
DrawStorage(state->store);
|
|
DrawFoundation(state->foundation);
|
|
DrawPlayfield(state->cols);
|
|
}
|
|
|
|
void DrawClear(void) {
|
|
GrafPtr thePort;
|
|
Rect *clearRect;
|
|
GetPort(&thePort);
|
|
clearRect = &thePort->portRect;
|
|
EraseRect(clearRect);
|
|
}
|
|
|
|
void DrawPlayfield(FCColumn **cols) {
|
|
Point drawPoint;
|
|
ushort i;
|
|
|
|
drawPoint.v = CARD_BD_Y + CARD_YLENGTH + CARD_ST_SEP;
|
|
drawPoint.h = CARD_BD_X;
|
|
for(i = 0; i < FC_COLS; ++i) {
|
|
DrawStack(cols[i]->cards, drawPoint, cols[i]->qty);
|
|
drawPoint.h += CARD_XLENGTH + CARD_PF_X;
|
|
}
|
|
}
|
|
|
|
void DrawStorage(Card *cards) {
|
|
Point drawPoint;
|
|
ushort i;
|
|
|
|
drawPoint.v = CARD_BD_Y;
|
|
drawPoint.h = CARD_BD_X;
|
|
for(i = 0; i < FC_STORES; ++i) {
|
|
if(!CARD_EMPTY(cards[i])) {
|
|
DrawCard(cards[i], drawPoint);
|
|
} else {
|
|
DrawEmptyFrame(drawPoint);
|
|
}
|
|
drawPoint.h += CARD_ST_X + CARD_XLENGTH;
|
|
}
|
|
}
|
|
|
|
void DrawFoundation(Card *cards) {
|
|
Point drawPoint;
|
|
ushort i;
|
|
|
|
drawPoint.v = CARD_BD_Y;
|
|
drawPoint.h = WIND_XLENGTH - CARD_BD_X - CARD_XLENGTH;
|
|
for(i = 0; i < 4; ++i) {
|
|
if(!CARD_EMPTY(cards[3-i])) {
|
|
DrawCard(cards[3-i], drawPoint);
|
|
} else {
|
|
DrawEmptyFrame(drawPoint);
|
|
}
|
|
drawPoint.h -= CARD_ST_X + CARD_XLENGTH;
|
|
}
|
|
}
|
|
|
|
void DrawStorageCard(Card card, ushort pos) {
|
|
Point drawPoint;
|
|
|
|
drawPoint = GetStorePt(pos);
|
|
if(!CARD_EMPTY(card)) {
|
|
DrawCard(card, drawPoint);
|
|
} else {
|
|
DrawEmptyFrame(drawPoint);
|
|
}
|
|
}
|
|
|
|
void DrawFoundationCard(Card card, ushort pos) {
|
|
Point drawPoint;
|
|
|
|
drawPoint = GetStorePt(FC_STORES + pos);
|
|
if(!CARD_EMPTY(card)) {
|
|
DrawCard(card, drawPoint);
|
|
} else {
|
|
DrawEmptyFrame(drawPoint);
|
|
}
|
|
}
|
|
|
|
void DrawLastColumnCard(FCColumn *col, ushort colno) {
|
|
Point drawPoint;
|
|
|
|
drawPoint = GetColumnPt(colno);
|
|
DrawStackedCard(col->cards[col->qty-1], drawPoint, col->qty-1);
|
|
}
|
|
|
|
void DrawRemovedColCard(FCColumn *col, ushort colno) {
|
|
Point drawPoint;
|
|
|
|
drawPoint = GetColumnPt(colno);
|
|
DrawStackedCard(CARD_NULL, drawPoint, col->qty);
|
|
|
|
if(col->qty != 0) {
|
|
DrawStackedCard(col->cards[col->qty-1], drawPoint, col->qty-1);
|
|
} else {
|
|
DrawEmptyFrame(drawPoint);
|
|
}
|
|
}
|
|
|
|
void CentreRect(Rect *toCentre, const Rect *bounds) {
|
|
short bdx, bdy, cdx, cdy;
|
|
|
|
bdx = bounds->right - bounds->left;
|
|
bdy = bounds->bottom - bounds->top;
|
|
cdx = toCentre->right - toCentre->left;
|
|
cdy = toCentre->bottom - toCentre->top;
|
|
if(cdx > bdx || cdy > bdy) return;
|
|
|
|
toCentre->top = bounds->top + bdy/2 - cdy/2;
|
|
toCentre->left = bounds->left + bdx/2 - cdx/2;
|
|
toCentre->bottom = toCentre->top + cdy;
|
|
toCentre->right = toCentre->left + cdx;
|
|
}
|
|
|
|
/*
|
|
switch(elem.zone) {
|
|
case FCZ_LASTCARD: {
|
|
FCColumn *theColumn = state->cols[elem.num];
|
|
if(CARD_EMPTY(theColumn->cards[theColumn->qty-1]))
|
|
goto err;
|
|
|
|
GetLastStackedRect(elem.num, theColumn->qty, &drawRect);
|
|
} break;
|
|
|
|
case FCZ_STORAGE:
|
|
if(CARD_EMPTY(state->store[elem.num]))
|
|
goto err;
|
|
|
|
GetStoreRect(elem.num, &drawRect);
|
|
break;
|
|
|
|
case FCZ_FOUNDATION:
|
|
if(CARD_EMPTY(state->foundation[elem.num]))
|
|
goto err;
|
|
|
|
GetStoreRect(elem.num + FC_STORES, &drawRect);
|
|
break;
|
|
|
|
default:
|
|
goto err;
|
|
}
|
|
*/ |