1213 lines
31 KiB
C
1213 lines
31 KiB
C
|
#include "sol.h"
|
||
|
VSZASSERT
|
||
|
|
||
|
|
||
|
/* Klondike init stuff */
|
||
|
LRESULT KlondGmProc(GM *pgm, INT msgg, WPARAM wp1, LPARAM wp2);
|
||
|
LRESULT DeckColProc(COL *pcol, INT msgc, WPARAM wp1, LPARAM wp2);
|
||
|
LRESULT DiscardColProc(COL *pcol, INT msgc, WPARAM wp1, LPARAM wp2);
|
||
|
LRESULT TabColProc(COL *pcol, INT msgc, WPARAM wp1, LPARAM wp2);
|
||
|
LRESULT FoundColProc(COL *pcol, INT msgc, WPARAM wp1, LPARAM wp2);
|
||
|
|
||
|
|
||
|
|
||
|
// Imported from Win3.1
|
||
|
BOOL FInitKlondGm()
|
||
|
{
|
||
|
COLCLS *pcolcls;
|
||
|
GM *pgm;
|
||
|
DX dxCrdOffUp;
|
||
|
DX dyCrdOffUp;
|
||
|
DX dyCrdOffDn;
|
||
|
int icol;
|
||
|
int icrdMax;
|
||
|
|
||
|
/* KLUDGE to get klondike going */
|
||
|
FreeGm(pgmCur);
|
||
|
|
||
|
if((pgm = pgmCur = PAlloc(sizeof(GM)+(13-1)*sizeof(COL *))) == NULL)
|
||
|
return fFalse;
|
||
|
|
||
|
pgm->lpfnGmProc = KlondGmProc;
|
||
|
SendGmMsg(pgm, msggInit, fTrue, 0);
|
||
|
pgm->icolMax = 13;
|
||
|
pgm->dqsecScore = 10*4;
|
||
|
|
||
|
if(!FInitUndo(&pgm->udr))
|
||
|
goto OOM;
|
||
|
|
||
|
/* Initialize all the column types but don't position yet */
|
||
|
for(icol = 0; icol < pgm->icolMax; icol++)
|
||
|
{
|
||
|
switch(icol)
|
||
|
{
|
||
|
case icolDeck:
|
||
|
pcolcls = PcolclsCreate(tclsDeck, (COLCLSCREATEFUNC)DeckColProc,
|
||
|
0, 0, 2, 1, 1, 10);
|
||
|
icrdMax = icrdDeckMax;
|
||
|
break;
|
||
|
|
||
|
case icolDiscard:
|
||
|
dxCrdOffUp = dxCrd / 5;
|
||
|
pcolcls = PcolclsCreate(tclsDiscard, (COLCLSCREATEFUNC)DiscardColProc,
|
||
|
dxCrdOffUp, 1, 2, 1, 1, 10);
|
||
|
icrdMax = icrdDiscardMax;
|
||
|
break;
|
||
|
|
||
|
case icolFoundFirst:
|
||
|
pcolcls = PcolclsCreate(tclsFound, (COLCLSCREATEFUNC)FoundColProc,
|
||
|
2, 1, 0, 0, 4, 1);
|
||
|
Assert(icol - 1 == icolDiscard);
|
||
|
icrdMax = icrdFoundMax;
|
||
|
break;
|
||
|
|
||
|
case icolTabFirst:
|
||
|
Assert(fHalfCards == 1 || fHalfCards == 0);
|
||
|
dyCrdOffUp = dyCrd * 4 / 25 - fHalfCards;
|
||
|
dyCrdOffDn = dyCrd / 25;
|
||
|
pgm->dyDragMax = dyCrd + 12 * dyCrdOffUp;
|
||
|
pcolcls = PcolclsCreate(tclsTab, (COLCLSCREATEFUNC)TabColProc,
|
||
|
0, dyCrdOffUp, 0, dyCrdOffDn, 1, 1);
|
||
|
icrdMax = icrdTabMax;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if(pcolcls == NULL)
|
||
|
{
|
||
|
OOM:
|
||
|
OOM();
|
||
|
FreeGm(pgmCur);
|
||
|
Assert(pgmCur == NULL);
|
||
|
return fFalse;
|
||
|
}
|
||
|
|
||
|
if((pgm->rgpcol[icol] = PcolCreate(pcolcls, 0, 0, 0, 0, icrdMax))
|
||
|
== NULL)
|
||
|
{
|
||
|
FreeP(pcolcls);
|
||
|
goto OOM;
|
||
|
}
|
||
|
pgm->icolMac++;
|
||
|
}
|
||
|
|
||
|
/* Return without positioning the cards. This will be done at
|
||
|
* WM_SIZE message time.
|
||
|
*/
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* PositionCols
|
||
|
* Positions the card columns. Note that this has been revised to
|
||
|
* allow card positioning at times other than at the start of the
|
||
|
* game.
|
||
|
*/
|
||
|
|
||
|
BOOL PositionCols(void)
|
||
|
{
|
||
|
DX dxMarg;
|
||
|
DY dyMarg;
|
||
|
DX dx;
|
||
|
X xLeft;
|
||
|
X xRight;
|
||
|
Y yTop;
|
||
|
Y yBot;
|
||
|
int icol;
|
||
|
DY dyCrdOffUp;
|
||
|
DY dyCrdOffDn;
|
||
|
COL *pcol;
|
||
|
GM *pgm;
|
||
|
WORD i;
|
||
|
|
||
|
/* The game we're using is always the current one */
|
||
|
pgm = pgmCur;
|
||
|
|
||
|
/* Before doing the column classes, replace all card X coordinates with
|
||
|
* offsets from the column class.
|
||
|
*/
|
||
|
for (icol = 0 ; icol < 13 ; ++icol)
|
||
|
{
|
||
|
/* Get a pointer to this COL structure */
|
||
|
pcol = pgm->rgpcol[icol];
|
||
|
|
||
|
/* Loop through all the cards in this column */
|
||
|
for (i = 0 ; i < pcol->icrdMax ; ++i)
|
||
|
pcol->rgcrd[i].pt.x -= pcol->rc.xLeft;
|
||
|
}
|
||
|
|
||
|
/* Set the card margins. Note that xCardMargin is computed in SOL.C
|
||
|
* at the time the original window is created and is changed on
|
||
|
* WM_SIZE messages.
|
||
|
*/
|
||
|
dxMarg = xCardMargin;
|
||
|
dyMarg = MulDiv(dyCrd, 5, 100);
|
||
|
|
||
|
/* Loop through all column types */
|
||
|
for(icol = 0 ; icol < 13 ; icol++)
|
||
|
{
|
||
|
switch(icol)
|
||
|
{
|
||
|
case icolDeck:
|
||
|
xLeft = dxMarg;
|
||
|
yTop = dyMarg;
|
||
|
xRight = xLeft + dxCrd + icrdDeckMax / 10 * 2;
|
||
|
yBot = yTop + dyCrd + icrdDeckMax / 10;
|
||
|
dx = 0;
|
||
|
break;
|
||
|
|
||
|
case icolDiscard:
|
||
|
xLeft += dxMarg + dxCrd;
|
||
|
xRight = xLeft + 7 * dxCrd / 5 + icrdDiscardMax / 10 * 2;
|
||
|
break;
|
||
|
|
||
|
case icolFoundFirst:
|
||
|
xLeft = 4 * dxMarg + 3 * dxCrd;
|
||
|
xRight = xLeft + dxCrd + icrdFoundMax / 4 * 2;
|
||
|
dx = dxMarg + dxCrd;
|
||
|
break;
|
||
|
|
||
|
case icolTabFirst:
|
||
|
dyCrdOffUp = dyCrd * 4 / 25 - fHalfCards;
|
||
|
dyCrdOffDn = dyCrd / 25;
|
||
|
xLeft = dxMarg;
|
||
|
xRight = xLeft + dxCrd;
|
||
|
yTop = yBot + 1;
|
||
|
yBot = yTop + 12 * dyCrdOffUp + dyCrd + 6 * dyCrdOffDn;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* Set this information into the structure */
|
||
|
pcol = pgm->rgpcol[icol];
|
||
|
pcol->rc.xLeft = xLeft;
|
||
|
pcol->rc.yTop = yTop;
|
||
|
pcol->rc.xRight = xRight;
|
||
|
pcol->rc.yBot = yBot;
|
||
|
|
||
|
/* Prepare for the next loop */
|
||
|
xLeft += dx;
|
||
|
xRight += dx;
|
||
|
}
|
||
|
|
||
|
/* Now that the column offsets are correct, move the cards back */
|
||
|
for (icol = 0 ; icol < 13 ; ++icol)
|
||
|
{
|
||
|
/* Get a pointer to this COL structure */
|
||
|
pcol = pgm->rgpcol[icol];
|
||
|
|
||
|
/* Loop through all the cards in this column */
|
||
|
for (i = 0 ; i < pcol->icrdMax ; ++i)
|
||
|
pcol->rgcrd[i].pt.x += pcol->rc.xLeft;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* TABLEAU col Proc stuff */
|
||
|
|
||
|
|
||
|
BOOL FTabValidMove(COL *pcolDest, COL *pcolSrc)
|
||
|
{
|
||
|
RA raSrc, raDest;
|
||
|
SU suSrc, suDest;
|
||
|
INT icrdSel;
|
||
|
CD cd;
|
||
|
|
||
|
Assert(pcolSrc->pmove != NULL);
|
||
|
icrdSel = pcolSrc->pmove->icrdSel;
|
||
|
|
||
|
Assert(icrdSel < pcolSrc->icrdMac);
|
||
|
Assert(pcolSrc->icrdMac > 0);
|
||
|
cd = pcolSrc->rgcrd[icrdSel].cd;
|
||
|
raSrc = RaFromCd(cd);
|
||
|
suSrc = SuFromCd(cd);
|
||
|
if(raSrc == raKing)
|
||
|
return (pcolDest->icrdMac == 0);
|
||
|
if(pcolDest->icrdMac == 0)
|
||
|
return fFalse;
|
||
|
if(!pcolDest->rgcrd[pcolDest->icrdMac-1].fUp)
|
||
|
return fFalse;
|
||
|
cd = pcolDest->rgcrd[pcolDest->icrdMac-1].cd;
|
||
|
raDest = RaFromCd(cd);
|
||
|
suDest = SuFromCd(cd);
|
||
|
/* invalid moves */
|
||
|
Assert((suClub ^ suSpade) == 0x03);
|
||
|
Assert((suHeart ^ suDiamond) == 0x03);
|
||
|
/* valid moves */
|
||
|
Assert((suClub ^ suDiamond) < 0x03);
|
||
|
Assert((suClub ^ suHeart) < 0x03);
|
||
|
Assert((suSpade ^ suDiamond) < 0x03);
|
||
|
Assert((suSpade ^ suHeart) < 0x03);
|
||
|
|
||
|
return (((suSrc ^ suDest) < 0x03) && suSrc != suDest && raSrc+1 == raDest);
|
||
|
}
|
||
|
|
||
|
|
||
|
INT TabHit(COL *pcol, PT *ppt, INT icrdMin)
|
||
|
{
|
||
|
CRD *pcrd;
|
||
|
|
||
|
if(pcol->icrdMac > 0 && !(pcrd=&pcol->rgcrd[pcol->icrdMac-1])->fUp && FPtInCrd(pcrd, *ppt))
|
||
|
{
|
||
|
SendGmMsg(pgmCur, msggKillUndo, 0, 0);
|
||
|
SendColMsg(pcol, msgcSel, icrdEnd, 1);
|
||
|
SendColMsg(pcol, msgcFlip, fTrue, 0);
|
||
|
SendColMsg(pcol, msgcComputeCrdPos, pcol->icrdMac-1, fFalse);
|
||
|
SendColMsg(pcol, msgcRender, pcol->icrdMac-1, icrdToEnd);
|
||
|
SendGmMsg(pgmCur, msggChangeScore, csKlondTabFlip, 0);
|
||
|
SendColMsg(pcol, msgcEndSel, fFalse, 0);
|
||
|
/* should I return this? */
|
||
|
return icrdNil;
|
||
|
}
|
||
|
return DefColProc(pcol, msgcHit, (INT_PTR) ppt, icrdMin);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL TabDiscardDblClk(COL *pcol, PT *ppt, INT icol)
|
||
|
{
|
||
|
CRD *pcrd;
|
||
|
INT icolDest;
|
||
|
COL *pcolDest;
|
||
|
BOOL fResult;
|
||
|
|
||
|
fResult = fFalse;
|
||
|
if(pcol->icrdMac > 0 && (pcrd=&pcol->rgcrd[pcol->icrdMac-1])->fUp && FPtInCrd(pcrd, *ppt))
|
||
|
{
|
||
|
if(pcol->pmove == NULL)
|
||
|
SendColMsg(pcol, msgcSel, icrdEnd, ccrdToEnd);
|
||
|
Assert(pcol->pmove != NULL);
|
||
|
for(icolDest = icolFoundFirst; icolDest < icolFoundFirst+ccolFound; icolDest++)
|
||
|
{
|
||
|
pcolDest = pgmCur->rgpcol[icolDest];
|
||
|
if(SendColMsg(pcolDest, msgcValidMove, (INT_PTR)pcol, 0))
|
||
|
{
|
||
|
SendGmMsg(pgmCur, msggSaveUndo, icolDest, icol);
|
||
|
fResult = SendColMsg(pcolDest, msgcMove, (INT_PTR) pcol, icrdToEnd) &&
|
||
|
(fOutlineDrag || SendColMsg(pcol, msgcRender, pcol->icrdMac-1, icrdToEnd)) &&
|
||
|
SendGmMsg(pgmCur, msggScore, (INT_PTR) pcolDest, (INT_PTR) pcol);
|
||
|
if(SendGmMsg(pgmCur, msggIsWinner, 0, 0))
|
||
|
SendGmMsg(pgmCur, msggWinner, 0, 0);
|
||
|
goto Return;
|
||
|
}
|
||
|
}
|
||
|
SendColMsg(pcol, msgcEndSel, fFalse, 0);
|
||
|
}
|
||
|
|
||
|
Return:
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
LRESULT TabColProc(COL *pcol, INT msgc, WPARAM wp1, LPARAM wp2)
|
||
|
{
|
||
|
|
||
|
switch(msgc)
|
||
|
{
|
||
|
case msgcHit:
|
||
|
/* should this go in DefProc? */
|
||
|
return TabHit(pcol, (PT *)wp1, (INT)wp2);
|
||
|
|
||
|
case msgcDblClk:
|
||
|
return TabDiscardDblClk(pcol, (PT *)wp1, (INT)wp2);
|
||
|
|
||
|
case msgcValidMove:
|
||
|
return FTabValidMove(pcol, (COL *) wp1);
|
||
|
}
|
||
|
return DefColProc(pcol, msgc, wp1, wp2);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL FFoundRender(COL *pcol, INT icrdFirst, INT icrdLast)
|
||
|
{
|
||
|
#define dxFoundDn 2
|
||
|
#define dyFoundDn 1
|
||
|
|
||
|
if(pcol->icrdMac == 0 || icrdLast == 0)
|
||
|
{
|
||
|
if(!FGetHdc())
|
||
|
return fFalse;
|
||
|
DrawCardExt((PT *)(&pcol->rc.xLeft), 0, GHOST);
|
||
|
DrawBackExcl(pcol, (PT *) &pcol->rc);
|
||
|
ReleaseHdc();
|
||
|
return fTrue;
|
||
|
}
|
||
|
else
|
||
|
return DefColProc(pcol, msgcRender, icrdFirst, icrdLast);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL FFoundValidMove(COL *pcolDest, COL *pcolSrc)
|
||
|
{
|
||
|
RA raSrc;
|
||
|
SU suSrc;
|
||
|
INT icrdSel;
|
||
|
|
||
|
Assert(pcolSrc->pmove != NULL);
|
||
|
icrdSel = pcolSrc->pmove->icrdSel;
|
||
|
Assert(icrdSel < pcolSrc->icrdMac);
|
||
|
Assert(pcolSrc->icrdMac > 0);
|
||
|
if(pcolSrc->pmove->ccrdSel != 1)
|
||
|
return fFalse;
|
||
|
raSrc = RaFromCd(pcolSrc->rgcrd[icrdSel].cd);
|
||
|
suSrc = SuFromCd(pcolSrc->rgcrd[icrdSel].cd);
|
||
|
if(pcolDest->icrdMac == 0)
|
||
|
return(raSrc == raAce);
|
||
|
return (raSrc == RaFromCd(pcolDest->rgcrd[pcolDest->icrdMac-1].cd)+1 &&
|
||
|
suSrc == SuFromCd(pcolDest->rgcrd[pcolDest->icrdMac-1].cd));
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* Foundation stuff */
|
||
|
LRESULT FoundColProc(COL *pcol, INT msgc, WPARAM wp1, LPARAM wp2)
|
||
|
{
|
||
|
switch(msgc)
|
||
|
{
|
||
|
case msgcValidMove:
|
||
|
return FFoundValidMove(pcol, (COL *) wp1);
|
||
|
|
||
|
case msgcRender:
|
||
|
return FFoundRender(pcol, (INT)wp1, (INT)wp2);
|
||
|
}
|
||
|
return DefColProc(pcol, msgc, wp1, wp2);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* DeckStuff */
|
||
|
|
||
|
|
||
|
BOOL DeckInit(COL *pcol)
|
||
|
{
|
||
|
CRD *pcrd;
|
||
|
INT icrd;
|
||
|
|
||
|
Assert(pcol->icrdMax == icrdDeckMax);
|
||
|
for(icrd = 0; icrd < icrdDeckMax; icrd++)
|
||
|
{
|
||
|
pcrd = &pcol->rgcrd[icrd];
|
||
|
pcrd->cd = (unsigned short)icrd;
|
||
|
pcrd->pt = *(PT *)&pcol->rc;
|
||
|
pcrd->fUp = fFalse;
|
||
|
}
|
||
|
pcol->icrdMac = icrdDeckMax;
|
||
|
SendColMsg(pcol, msgcShuffle, 0, 0);
|
||
|
SendColMsg(pcol, msgcComputeCrdPos, 0, fFalse);
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
INT DeckHit(COL *pcol, PT *ppt, INT icrdMin)
|
||
|
{
|
||
|
RC rc;
|
||
|
INT ccrd;
|
||
|
|
||
|
if(pcol->icrdMac == 0)
|
||
|
{
|
||
|
CrdRcFromPt((PT *) &pcol->rc, &rc);
|
||
|
if(PtInRect((LPRECT) &rc, *(POINT *)ppt))
|
||
|
return icrdEmpty;
|
||
|
else
|
||
|
return icrdNil;
|
||
|
}
|
||
|
else
|
||
|
if(!FPtInCrd(&pcol->rgcrd[pcol->icrdMac-1], *ppt))
|
||
|
return icrdNil;
|
||
|
|
||
|
ccrd = ((GetKeyState(VK_SHIFT) & GetKeyState(VK_CONTROL) & GetKeyState(VK_MENU)) < 0) ? 1 : pgmCur->ccrdDeal;
|
||
|
|
||
|
move.icrdSel = WMax(pcol->icrdMac-ccrd, 0);
|
||
|
move.ccrdSel = pcol->icrdMac - move.icrdSel;
|
||
|
Assert(pcol->pmove == NULL);
|
||
|
pcol->pmove = &move;
|
||
|
return move.icrdSel;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL FDeckRender(COL *pcol, INT icrdFirst, INT icrdLast)
|
||
|
{
|
||
|
INT mode;
|
||
|
BOOL f;
|
||
|
PT pt;
|
||
|
|
||
|
/* to avoid redrawing the deck multiple times during dealing */
|
||
|
if(!pgmCur->fDealt && pcol->icrdMac%10 != 9)
|
||
|
return fTrue;
|
||
|
if(!FGetHdc())
|
||
|
return fFalse;
|
||
|
if(pcol->icrdMac == 0)
|
||
|
{
|
||
|
mode = (smd == smdVegas && pgmCur->irep == ccrdDeal-1) ? DECKX : DECKO;
|
||
|
DrawCardExt((PT *) &pcol->rc, 0, mode);
|
||
|
DrawBackExcl(pcol, (PT *) &pcol->rc);
|
||
|
f = fTrue;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
f = DefColProc(pcol, msgcRender, icrdFirst, icrdLast);
|
||
|
if((icrdLast == pcol->icrdMac || icrdLast == icrdToEnd) && !fHalfCards)
|
||
|
{
|
||
|
pt.x = pcol->rgcrd[pcol->icrdMac-1].pt.x+dxCrd-1;
|
||
|
pt.y = pcol->rgcrd[pcol->icrdMac-1].pt.y+dyCrd-1;
|
||
|
SetPixel(hdcCur, pt.x-xOrgCur, pt.y-yOrgCur, rgbTable);
|
||
|
SetPixel(hdcCur, pt.x-1-xOrgCur, pt.y-yOrgCur, rgbTable);
|
||
|
SetPixel(hdcCur, pt.x-xOrgCur, pt.y-1-yOrgCur, rgbTable);
|
||
|
}
|
||
|
}
|
||
|
ReleaseHdc();
|
||
|
return f;
|
||
|
}
|
||
|
|
||
|
|
||
|
VOID DrawAnimate(INT cd, PT *ppt, INT iani)
|
||
|
{
|
||
|
|
||
|
if(!FGetHdc())
|
||
|
return;
|
||
|
cdtAnimate(hdcCur, cd, ppt->x, ppt->y, iani);
|
||
|
ReleaseHdc();
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL DeckAnimate(COL *pcol, INT iqsec)
|
||
|
{
|
||
|
INT iani;
|
||
|
PT pt;
|
||
|
|
||
|
// we removed the older card decks that required Animation. The new
|
||
|
// card deck doesn't involve any animation.
|
||
|
|
||
|
#ifdef UNUSEDCODE
|
||
|
|
||
|
if(pcol->icrdMac > 0 && !fHalfCards)
|
||
|
{
|
||
|
pt = pcol->rgcrd[pcol->icrdMac-1].pt;
|
||
|
switch(modeFaceDown)
|
||
|
{
|
||
|
case IDFACEDOWN3:
|
||
|
DrawAnimate(IDFACEDOWN3, &pt, iqsec % 4);
|
||
|
break;
|
||
|
case IDFACEDOWN10: /* krazy kastle */
|
||
|
DrawAnimate(IDFACEDOWN10, &pt, iqsec % 2);
|
||
|
break;
|
||
|
|
||
|
case IDFACEDOWN11: /* sanflipe */
|
||
|
if((iani = (iqsec+4) % (50*4)) < 4)
|
||
|
DrawAnimate(IDFACEDOWN11, &pt, iani);
|
||
|
else
|
||
|
/* if a menu overlapps an ani while it is ani'ing, leaves deck
|
||
|
bitmap in inconsistent state... */
|
||
|
if(iani % 6 == 0)
|
||
|
DrawAnimate(IDFACEDOWN11, &pt, 3);
|
||
|
break;
|
||
|
case IDFACEDOWN12: /* SLIME */
|
||
|
if((iani = (iqsec+4) % (15*4)) < 4)
|
||
|
DrawAnimate(IDFACEDOWN12, &pt, iani);
|
||
|
else
|
||
|
/* if a menu overlapps an ani while it is ani'ing, leaves deck
|
||
|
bitmap in inconsistent state... */
|
||
|
if(iani % 6 == 0)
|
||
|
DrawAnimate(IDFACEDOWN12, &pt, 3);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
LRESULT DeckColProc(COL *pcol, INT msgc, WPARAM wp1, LPARAM wp2)
|
||
|
{
|
||
|
|
||
|
switch(msgc)
|
||
|
{
|
||
|
case msgcInit:
|
||
|
return DeckInit(pcol);
|
||
|
case msgcValidMove:
|
||
|
case msgcDrawOutline:
|
||
|
return fFalse;
|
||
|
case msgcValidMovePt:
|
||
|
return icrdNil;
|
||
|
case msgcHit:
|
||
|
return DeckHit(pcol, (PT *) wp1, (INT)wp2);
|
||
|
case msgcRender:
|
||
|
return FDeckRender(pcol, (INT) wp1, (INT) wp2);
|
||
|
case msgcValidKbdColSel:
|
||
|
return !wp1;
|
||
|
case msgcValidKbdCrdSel:
|
||
|
return pcol->icrdMac == 0 || wp1 == (WPARAM) pcol->icrdMac-1;
|
||
|
case msgcAnimate:
|
||
|
return DeckAnimate(pcol, (INT)wp1);
|
||
|
}
|
||
|
return DefColProc(pcol, msgc, wp1, wp2);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL DiscardRemove(COL *pcol, COL *pcolDest, LPARAM wp2)
|
||
|
{
|
||
|
return DefColProc(pcol, msgcRemove, (INT_PTR) pcolDest, wp2);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL DiscardMove(COL *pcolDest, COL *pcolSrc, INT icrd)
|
||
|
{
|
||
|
BOOL fResult;
|
||
|
|
||
|
SendColMsg(pcolDest, msgcComputeCrdPos, WMax(0, pcolDest->icrdMac-3), fTrue);
|
||
|
|
||
|
/* YUCK: Default ComputeCrdPos doesn't quite work for discard because
|
||
|
up cards are handled specially for Discard piles. To keep
|
||
|
code size down we have this global hack variable which DefComputeCrdPos
|
||
|
uses.
|
||
|
*/
|
||
|
fMegaDiscardHack = fTrue;
|
||
|
fResult = DefColProc(pcolDest, msgcMove, (INT_PTR) pcolSrc, icrd);
|
||
|
fMegaDiscardHack = fFalse;
|
||
|
return fResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
INT DiscardHit(COL *pcol, PT *ppt, INT icrdMin)
|
||
|
{
|
||
|
return DefColProc(pcol, msgcHit, (INT_PTR) ppt, WMax(0, pcol->icrdMac-1));
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL DiscardRender(COL *pcol, INT icrdFirst, INT icrdLast)
|
||
|
{
|
||
|
PT pt;
|
||
|
INT icrd;
|
||
|
COLCLS *pcolcls;
|
||
|
|
||
|
if(DefColProc(pcol, msgcRender, icrdFirst, icrdLast))
|
||
|
{
|
||
|
if(FGetHdc())
|
||
|
{
|
||
|
pcolcls = pcol->pcolcls;
|
||
|
for(icrd = pcol->icrdMac-1; icrd >= 0 && icrd >= pcol->icrdMac-2; icrd--)
|
||
|
{
|
||
|
pt = pcol->rgcrd[icrd].pt;
|
||
|
/* 3 is a kludge value here */
|
||
|
DrawBackground(pt.x+dxCrd-pcolcls->dxUp, pt.y-pcolcls->dyUp*3,
|
||
|
pt.x+dxCrd, pt.y);
|
||
|
}
|
||
|
ReleaseHdc();
|
||
|
}
|
||
|
return fTrue;
|
||
|
}
|
||
|
return fFalse;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* Discard Stuff */
|
||
|
LRESULT DiscardColProc(COL *pcol, INT msgc, WPARAM wp1, LPARAM wp2)
|
||
|
{
|
||
|
switch(msgc)
|
||
|
{
|
||
|
case msgcDblClk:
|
||
|
return TabDiscardDblClk(pcol, (PT *)wp1, (INT)wp2);
|
||
|
case msgcHit:
|
||
|
return DiscardHit(pcol, (PT *)wp1, (INT)wp2);
|
||
|
case msgcMove:
|
||
|
return DiscardMove(pcol, (COL *) wp1, (INT)wp2);
|
||
|
case msgcRemove:
|
||
|
return DiscardRemove(pcol, (COL *) wp1, wp2);
|
||
|
case msgcValidMovePt:
|
||
|
return icrdNil;
|
||
|
case msgcValidKbdColSel:
|
||
|
return !wp1;
|
||
|
case msgcRender:
|
||
|
return DiscardRender(pcol, (INT)wp1, (INT)wp2);
|
||
|
case msgcValidKbdCrdSel:
|
||
|
return pcol->icrdMac == 0 || wp1 == (WPARAM) pcol->icrdMac-1;
|
||
|
}
|
||
|
|
||
|
return DefColProc(pcol, msgc, wp1, wp2);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/* GAME stuff */
|
||
|
|
||
|
BOOL KlondDeal(GM *pgm, BOOL fZeroScore)
|
||
|
{
|
||
|
INT icrdSel;
|
||
|
INT icol;
|
||
|
INT irw;
|
||
|
COL *pcolDeck;
|
||
|
VOID StatString();
|
||
|
|
||
|
if(!FGetHdc())
|
||
|
{
|
||
|
OOM();
|
||
|
return fFalse;
|
||
|
}
|
||
|
|
||
|
EraseScreen();
|
||
|
for(icol = 0; icol < pgm->icolMac; icol++)
|
||
|
SendColMsg(pgm->rgpcol[icol], msgcClearCol, 0, 0);
|
||
|
|
||
|
pcolDeck = pgm->rgpcol[icolDeck];
|
||
|
SendColMsg(pcolDeck, msgcInit, 0, 0);
|
||
|
|
||
|
SendGmMsg(pgm, msggKillUndo, 0, 0);
|
||
|
SendGmMsg(pgm, msggInit, !(smd == smdVegas && fKeepScore) || fZeroScore, 0);
|
||
|
|
||
|
StatString(idsNil);
|
||
|
pgm->fDealt = fTrue;
|
||
|
SendGmMsg(pgm, msggChangeScore, csKlondDeal, 0);
|
||
|
SendColMsg(pcolDeck, msgcRender, 0, icrdToEnd);
|
||
|
pgm->fDealt = fFalse;
|
||
|
for(icol = icolFoundFirst; icol < icolFoundFirst+ccolFound; icol++)
|
||
|
SendColMsg(pgm->rgpcol[icol], msgcRender, 0, icrdToEnd);
|
||
|
|
||
|
// BabakJ: What the %@!&$* is this?! irw is always less than irw + ccolTab!!!
|
||
|
// Note: ccolTab if #ifdef'ed as 7
|
||
|
// for(irw = 0; irw < irw+ccolTab; irw++)
|
||
|
|
||
|
for(irw = 0; irw < ccolTab; irw++)
|
||
|
for(icol = irw; icol < ccolTab; icol++)
|
||
|
{
|
||
|
icrdSel = SendColMsg(pcolDeck, msgcSel, icrdEnd, 0);
|
||
|
if(icol == irw)
|
||
|
SendColMsg(pcolDeck, msgcFlip, fTrue, 0);
|
||
|
SendColMsg(pgm->rgpcol[icol+icolTabFirst], msgcMove, (INT_PTR) pcolDeck, icrdToEnd);
|
||
|
SendColMsg(pcolDeck, msgcRender, icrdSel-1, icrdToEnd);
|
||
|
}
|
||
|
NewKbdColAbs(pgm, 0);
|
||
|
pgm->fDealt = fTrue;
|
||
|
ReleaseHdc();
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL KlondMouseDown(GM *pgm, PT *ppt)
|
||
|
{
|
||
|
INT icrdSel;
|
||
|
INT icrd;
|
||
|
COL *pcolDeck, *pcolDiscard;
|
||
|
|
||
|
/* Kbd sel already in effect */
|
||
|
if(FSelOfGm(pgm) || !pgm->fDealt)
|
||
|
return fFalse;
|
||
|
/* place the next cards on discard pile */
|
||
|
if((icrd = SendColMsg(pgm->rgpcol[icolDeck], msgcHit, (INT_PTR) ppt, 0)) != icrdNil)
|
||
|
{
|
||
|
pgm->fInput = fTrue;
|
||
|
pcolDeck = pgm->rgpcol[icolDeck];
|
||
|
pcolDiscard = pgm->rgpcol[icolDiscard];
|
||
|
if(icrd == icrdEmpty)
|
||
|
{
|
||
|
/* repeat */
|
||
|
if(SendColMsg(pcolDiscard, msgcNumCards, 0, 0) == 0)
|
||
|
{
|
||
|
/* both deck and discard are empty */
|
||
|
Assert(pcolDeck->pmove == NULL);
|
||
|
return fFalse;
|
||
|
}
|
||
|
if(smd == smdVegas && pgm->irep == ccrdDeal-1)
|
||
|
return fFalse;
|
||
|
|
||
|
pgm->irep++;
|
||
|
pgm->udr.fEndDeck = TRUE;
|
||
|
|
||
|
return SendGmMsg(pgm, msggSaveUndo, icolDiscard, icolDeck) &&
|
||
|
SendColMsg(pcolDiscard, msgcSel, 0, ccrdToEnd) != icrdNil &&
|
||
|
SendColMsg(pcolDiscard, msgcFlip, fFalse, 0) &&
|
||
|
SendColMsg(pcolDiscard, msgcInvert, 0, 0) &&
|
||
|
SendGmMsg(pgm, msggScore, (INT_PTR) pcolDeck, (INT_PTR) pcolDiscard) &&
|
||
|
SendColMsg(pcolDeck, msgcMove, (INT_PTR) pcolDiscard, icrdToEnd) &&
|
||
|
SendColMsg(pcolDiscard, msgcRender, 0, icrdToEnd);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
icrdSel = pcolDeck->pmove->icrdSel-1;
|
||
|
/* deal next cards to discard */
|
||
|
return SendGmMsg(pgm, msggSaveUndo, icolDiscard, icolDeck) &&
|
||
|
SendColMsg(pcolDeck, msgcFlip, fTrue, 0) &&
|
||
|
SendColMsg(pcolDeck, msgcInvert, 0, 0) &&
|
||
|
SendColMsg(pcolDiscard, msgcMove, (INT_PTR)pcolDeck, icrdToEnd) &&
|
||
|
SendColMsg(pcolDeck, msgcRender, icrdSel, icrdToEnd);
|
||
|
}
|
||
|
}
|
||
|
return DefGmProc(pgm, msggMouseDown, (INT_PTR) ppt, icolDiscard);
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL KlondIsWinner(GM *pgm)
|
||
|
{
|
||
|
INT icol;
|
||
|
|
||
|
for(icol = icolFoundFirst; icol < icolFoundFirst+ccolFound; icol++)
|
||
|
if(pgm->rgpcol[icol]->icrdMac != icrdFoundMax)
|
||
|
return fFalse;
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL FAbort()
|
||
|
{
|
||
|
MSG msg;
|
||
|
|
||
|
if (MsgWaitForMultipleObjects(0, NULL, FALSE, 5, QS_ALLINPUT) != WAIT_OBJECT_0)
|
||
|
return FALSE;
|
||
|
|
||
|
if(PeekMessage(&msg, hwndApp, 0, 0, PM_NOREMOVE))
|
||
|
{
|
||
|
switch(msg.message)
|
||
|
{
|
||
|
case WM_LBUTTONDOWN:
|
||
|
case WM_MBUTTONDOWN:
|
||
|
case WM_RBUTTONDOWN:
|
||
|
case WM_KEYDOWN:
|
||
|
case WM_SYSKEYDOWN:
|
||
|
case WM_MENUSELECT:
|
||
|
case WM_NCLBUTTONDOWN:
|
||
|
case WM_NCMBUTTONDOWN:
|
||
|
case WM_NCRBUTTONDOWN:
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
PeekMessage(&msg, hwndApp, 0, 0, PM_REMOVE);
|
||
|
TranslateMessage((LPMSG)&msg);
|
||
|
DispatchMessage((LPMSG)&msg);
|
||
|
}
|
||
|
return fFalse;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// Hack for making winning animation faster:
|
||
|
// At cascading time we have: KlondWinner -> DrawCardPt ->cdtDrawExt
|
||
|
// so we set a flag so cdtDrawExt knows it is cascading and does not need
|
||
|
// to round up corners.
|
||
|
BOOL fKlondWinner = FALSE;
|
||
|
|
||
|
BOOL KlondWinner(GM *pgm)
|
||
|
{
|
||
|
INT icol;
|
||
|
INT icrd;
|
||
|
CRD *pcrd;
|
||
|
PT pt;
|
||
|
PT ptV;
|
||
|
INT dxp;
|
||
|
INT dyp;
|
||
|
RC rcT;
|
||
|
INT dsco;
|
||
|
TCHAR *pch;
|
||
|
TCHAR szBonus[84];
|
||
|
VOID StatString();
|
||
|
UINT cchUsed, cchTmp;
|
||
|
|
||
|
fKlondWinner = TRUE;
|
||
|
|
||
|
dsco = (INT)SendGmMsg(pgmCur, msggChangeScore, csKlondWin, 0);
|
||
|
pgm->udr.fAvail = fFalse;
|
||
|
pgm->fDealt = fFalse;
|
||
|
pgm->fWon = fTrue;
|
||
|
|
||
|
if(smd == smdStandard)
|
||
|
{
|
||
|
cchUsed = CchString(szBonus, idsBonus, ARRAYSIZE(szBonus));
|
||
|
pch = &szBonus[cchUsed];
|
||
|
|
||
|
cchTmp = CchDecodeInt(pch, dsco);
|
||
|
pch += cchTmp;
|
||
|
cchUsed += cchTmp;
|
||
|
|
||
|
*pch++ = TEXT(' ');
|
||
|
cchUsed++;
|
||
|
|
||
|
*pch++ = TEXT(' ');
|
||
|
cchUsed++;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pch = szBonus;
|
||
|
cchUsed = 0;
|
||
|
}
|
||
|
if (cchUsed < ARRAYSIZE(szBonus))
|
||
|
{
|
||
|
CchString(pch, idsEndWinner, ARRAYSIZE(szBonus) - cchUsed);
|
||
|
}
|
||
|
|
||
|
StatStringSz(szBonus);
|
||
|
if(!FGetHdc())
|
||
|
goto ByeNoRel;
|
||
|
Assert(xOrgCur == 0);
|
||
|
Assert(yOrgCur == 0);
|
||
|
GetClientRect(hwndApp, (RECT *)&rcT);
|
||
|
dxp = rcT.xRight;
|
||
|
dyp = rcT.yBot - dyCrd;
|
||
|
|
||
|
for(icrd = icrdFoundMax-1; icrd >= 0; icrd--)
|
||
|
{
|
||
|
for(icol = icolFoundFirst; icol < icolFoundFirst+ccolFound; icol++)
|
||
|
{
|
||
|
ptV.x = rand() % 110 - 65; /* favor up and to left */
|
||
|
if(abs(ptV.x) < 15) /* kludge so doesn't bounce forever */
|
||
|
ptV.x = -20;
|
||
|
ptV.y = rand() % 110 - 75;
|
||
|
pt = (pcrd = &pgm->rgpcol[icol]->rgcrd[icrd])->pt;
|
||
|
|
||
|
while(pt.x > -dxCrd && pt.x < dxp)
|
||
|
{
|
||
|
DrawCardPt(pcrd, &pt);
|
||
|
pt.x += ptV.x/10;
|
||
|
pt.y += ptV.y/10;
|
||
|
ptV.y+= 3;
|
||
|
if(pt.y > dyp && ptV.y > 0)
|
||
|
ptV.y = -(ptV.y*8)/10;
|
||
|
if(FAbort())
|
||
|
goto ByeBye;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
ByeBye:
|
||
|
ReleaseHdc();
|
||
|
ByeNoRel:
|
||
|
StatString(idsNil);
|
||
|
EraseScreen();
|
||
|
|
||
|
fKlondWinner = FALSE;
|
||
|
|
||
|
return DefGmProc(pgm, msggWinner, 0, 0);
|
||
|
}
|
||
|
|
||
|
BOOL KlondForceWin(GM *pgm)
|
||
|
{
|
||
|
INT icol;
|
||
|
CRD *pcrd;
|
||
|
COL *pcol;
|
||
|
RA ra;
|
||
|
SU su;
|
||
|
|
||
|
for(icol = 0; icol < pgm->icolMac; icol++)
|
||
|
SendColMsg(pgm->rgpcol[icol], msgcClearCol, 0, 0);
|
||
|
for(su = suFirst, icol = icolFoundFirst; icol < icolFoundFirst+ccolFound; icol++, su++)
|
||
|
{
|
||
|
Assert(raFirst == 0);
|
||
|
for(ra = raFirst; ra < raMax; ra++)
|
||
|
{
|
||
|
pcol = pgm->rgpcol[icol];
|
||
|
pcrd = &pcol->rgcrd[ra];
|
||
|
pcrd->cd = Cd(ra, su);
|
||
|
pcrd->pt.x = pcol->rc.xLeft;
|
||
|
pcrd->pt.y = pcol->rc.yTop;
|
||
|
pcrd->fUp = fTrue;
|
||
|
}
|
||
|
pgm->rgpcol[icol]->icrdMac = icrdFoundMax;
|
||
|
}
|
||
|
Assert(SendGmMsg(pgm, msggIsWinner, 0, 0));
|
||
|
return (BOOL)SendGmMsg(pgm, msggWinner, 0, 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
/* Note: assumes is called once a second */
|
||
|
/* if pcolDest == pcolSrc == NULL, then is a timer msg */
|
||
|
BOOL KlondScore(GM *pgm, COL *pcolDest, COL *pcolSrc)
|
||
|
{
|
||
|
INT cs;
|
||
|
INT tclsSrc, tclsDest;
|
||
|
|
||
|
|
||
|
if(smd == smdNone)
|
||
|
return fTrue;
|
||
|
cs = csNil;
|
||
|
|
||
|
Assert(FValidCol(pcolSrc));
|
||
|
Assert(FValidCol(pcolDest));
|
||
|
|
||
|
|
||
|
tclsSrc = pcolSrc->pcolcls->tcls;
|
||
|
tclsDest = pcolDest->pcolcls->tcls;
|
||
|
|
||
|
switch(tclsDest)
|
||
|
{
|
||
|
default:
|
||
|
return fTrue;
|
||
|
case tclsDeck:
|
||
|
if(tclsSrc == tclsDiscard)
|
||
|
cs = csKlondDeckFlip;
|
||
|
break;
|
||
|
case tclsFound:
|
||
|
switch(tclsSrc)
|
||
|
{
|
||
|
default:
|
||
|
return fTrue;
|
||
|
case tclsDiscard:
|
||
|
case tclsTab:
|
||
|
cs = csKlondFound;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case tclsTab:
|
||
|
switch(tclsSrc)
|
||
|
{
|
||
|
default:
|
||
|
return fTrue;
|
||
|
case tclsDiscard:
|
||
|
cs = csKlondTab;
|
||
|
break;
|
||
|
case tclsFound:
|
||
|
cs = csKlondFoundTab;
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
SendGmMsg(pgm, msggChangeScore, cs, 0);
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
INT mpcsdscoStd[] = { -2, -20, 10, 5, 5, -15, 0, 0};
|
||
|
INT mpcsdscoVegas[] = {0, 0, 5, 0, 0, -5, -52, 0};
|
||
|
|
||
|
|
||
|
BOOL KlondChangeScore(GM *pgm, INT cs, INT sco)
|
||
|
{
|
||
|
INT dsco;
|
||
|
INT csNew;
|
||
|
INT *pmpcsdsco;
|
||
|
INT ret;
|
||
|
|
||
|
if(cs < 0)
|
||
|
return DefGmProc(pgm, msggChangeScore, cs, sco);
|
||
|
Assert(FInRange(cs, 0, csKlondMax-1));
|
||
|
switch(smd)
|
||
|
{
|
||
|
default:
|
||
|
Assert(smd == smdNone);
|
||
|
return fTrue;
|
||
|
case smdVegas:
|
||
|
pmpcsdsco = mpcsdscoVegas;
|
||
|
break;
|
||
|
|
||
|
case smdStandard:
|
||
|
pmpcsdsco = mpcsdscoStd;
|
||
|
if(cs == csKlondWin && fTimedGame)
|
||
|
{
|
||
|
#ifdef DEBUG
|
||
|
pgm->iqsecScore = WMax(120, pgm->iqsecScore);
|
||
|
#endif
|
||
|
/* check if timer set properly */
|
||
|
if(pgm->iqsecScore >= 120)
|
||
|
dsco = (20000/(pgm->iqsecScore>>2))*(350/10);
|
||
|
else
|
||
|
dsco = 0;
|
||
|
goto DoScore;
|
||
|
}
|
||
|
if(cs == csKlondDeckFlip)
|
||
|
{
|
||
|
if(ccrdDeal == 1 && pgm->irep >= 1)
|
||
|
{
|
||
|
dsco = -100;
|
||
|
goto DoScore;
|
||
|
}
|
||
|
else if(ccrdDeal == 3 && pgm->irep > 3)
|
||
|
break;
|
||
|
else
|
||
|
return fTrue;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
dsco = pmpcsdsco[cs];
|
||
|
DoScore:
|
||
|
csNew = smd == smdVegas ? csDel : csDelPos;
|
||
|
ret = DefGmProc(pgm, msggChangeScore, csNew, dsco);
|
||
|
if(cs == csKlondWin)
|
||
|
return dsco;
|
||
|
else
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL KlondTimer(GM *pgm, INT wp1, INT wp2)
|
||
|
{
|
||
|
|
||
|
if(fTimedGame && pgm->fDealt && pgm->fInput && !fIconic)
|
||
|
{
|
||
|
pgm->iqsecScore = WMin(pgm->iqsecScore+1, 0x7ffe);
|
||
|
if(pgm->icolSel == icolNil)
|
||
|
SendColMsg(pgm->rgpcol[icolDeck], msgcAnimate, pgm->iqsecScore, 0);
|
||
|
if(pgm->dqsecScore != 0 && (pgm->iqsecScore)%pgm->dqsecScore == 0)
|
||
|
{
|
||
|
SendGmMsg(pgm, msggChangeScore, csKlondTime, 0);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/* update status bar once as second */
|
||
|
if(~(pgm->iqsecScore & 0x03))
|
||
|
StatUpdate();
|
||
|
return fTrue;
|
||
|
}
|
||
|
}
|
||
|
return fFalse;
|
||
|
}
|
||
|
|
||
|
BOOL KlondDrawStatus(GM *pgm, RC *prc)
|
||
|
{
|
||
|
TCHAR *pch;
|
||
|
TCHAR sz[80];
|
||
|
RC rc;
|
||
|
LONG rgb;
|
||
|
BOOL fNegSco;
|
||
|
SIZE iSize;
|
||
|
extern INT iCurrency;
|
||
|
extern TCHAR szCurrency[];
|
||
|
HFONT hFontOld = NULL;
|
||
|
HFONT hStatusFont = NULL;
|
||
|
|
||
|
|
||
|
// store the old font and replace the status font by MS Shell Dlg
|
||
|
// as it supports FE characters as well as euro characters.
|
||
|
|
||
|
hStatusFont = CreateFont(-MulDiv(9, GetDeviceCaps(hdcCur, LOGPIXELSY), 72), 0, 0, 0, FW_BOLD, 0, 0, 0,
|
||
|
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
|
||
|
DEFAULT_PITCH, TEXT("MS Shell Dlg"));
|
||
|
|
||
|
if (hStatusFont && hdcCur);
|
||
|
hFontOld = SelectObject(hdcCur, hStatusFont);
|
||
|
|
||
|
pch = sz;
|
||
|
if(fTimedGame)
|
||
|
{
|
||
|
pch += CchString(pch, idsTime, ARRAYSIZE(sz));
|
||
|
pch += CchDecodeInt(pch, (pgm->iqsecScore>>2));
|
||
|
}
|
||
|
#ifdef DEBUG
|
||
|
if(!fScreenShots)
|
||
|
{
|
||
|
*pch++ = TEXT(' ');
|
||
|
pch = PszCopy(TEXT("Game # "), pch);
|
||
|
pch += CchDecodeInt(pch, igmCur);
|
||
|
}
|
||
|
#endif
|
||
|
if(pch != sz)
|
||
|
{
|
||
|
DrawText(hdcCur, sz, (INT)(pch-sz), (LPRECT) prc, DT_RIGHT|DT_NOCLIP|DT_SINGLELINE);
|
||
|
}
|
||
|
|
||
|
if(smd != smdNone)
|
||
|
{
|
||
|
rc = *prc;
|
||
|
GetTextExtentPoint32(hdcCur, sz, (INT)(pch-sz), &iSize);
|
||
|
rc.xRight -= iSize.cx;
|
||
|
pch = sz;
|
||
|
if(fNegSco = pgm->sco < 0)
|
||
|
*pch++ = TEXT('-');
|
||
|
if(smd == smdVegas)
|
||
|
{
|
||
|
if(!(iCurrency&1))
|
||
|
{
|
||
|
pch = PszCopy(szCurrency, pch);
|
||
|
if(iCurrency == 2)
|
||
|
*pch++ = TEXT(' ');
|
||
|
}
|
||
|
}
|
||
|
pch += CchDecodeInt(pch, fNegSco ? -pgm->sco : pgm->sco);
|
||
|
if(smd == smdVegas)
|
||
|
{
|
||
|
if(iCurrency&1)
|
||
|
{
|
||
|
if(iCurrency == 3)
|
||
|
*pch++ = TEXT(' ');
|
||
|
pch = PszCopy(szCurrency, pch);
|
||
|
}
|
||
|
}
|
||
|
*pch++ = TEXT(' ');
|
||
|
rgb = SetTextColor(hdcCur, (!fBW && fNegSco) ? RGB(0xff, 0, 0) : RGB(0, 0, 0));
|
||
|
DrawText(hdcCur, sz, (INT)(pch-sz), (LPRECT) &rc, DT_RIGHT|DT_NOCLIP|DT_SINGLELINE);
|
||
|
SetTextColor(hdcCur, rgb);
|
||
|
|
||
|
GetTextExtentPoint32(hdcCur, sz, (INT)(pch-sz), &iSize);
|
||
|
rc.xRight -= iSize.cx;
|
||
|
pch = PszCopy(szScore, sz);
|
||
|
DrawText(hdcCur, sz, (INT)(pch-sz), (LPRECT) &rc, DT_RIGHT|DT_NOCLIP|DT_SINGLELINE);
|
||
|
GetTextExtentPoint32(hdcCur, sz, (INT)(pch-sz), &iSize);
|
||
|
rc.xRight -= iSize.cx;
|
||
|
rc.xLeft = rc.xRight - 4 * dxChar;
|
||
|
PatBlt(hdcCur, rc.xLeft, rc.yTop, rc.xRight-rc.xLeft, rc.yBot-rc.yTop, PATCOPY);
|
||
|
}
|
||
|
|
||
|
|
||
|
// restore the font
|
||
|
if (hFontOld);
|
||
|
SelectObject(hdcCur, hFontOld);
|
||
|
|
||
|
// close the created font handle
|
||
|
if (hStatusFont)
|
||
|
DeleteObject(hStatusFont);
|
||
|
|
||
|
return fTrue;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
LRESULT KlondGmProc(GM *pgm, INT msgg, WPARAM wp1, LPARAM wp2)
|
||
|
{
|
||
|
switch(msgg)
|
||
|
{
|
||
|
case msggMouseDblClk:
|
||
|
if(DefGmProc(pgm, msggMouseDblClk, wp1, wp2))
|
||
|
return fTrue;
|
||
|
/* fall thru so works for deck double clicks */
|
||
|
case msggMouseDown:
|
||
|
return KlondMouseDown(pgm, (PT *)wp1);
|
||
|
|
||
|
case msggDeal:
|
||
|
return KlondDeal(pgm, (BOOL)wp1);
|
||
|
|
||
|
case msggIsWinner:
|
||
|
return KlondIsWinner(pgm);
|
||
|
|
||
|
case msggWinner:
|
||
|
return KlondWinner(pgm);
|
||
|
|
||
|
case msggForceWin:
|
||
|
return KlondForceWin(pgm);
|
||
|
|
||
|
case msggScore:
|
||
|
return KlondScore(pgm, (COL *) wp1, (COL *)wp2);
|
||
|
|
||
|
case msggChangeScore:
|
||
|
return KlondChangeScore(pgm, (INT)wp1, (INT)wp2);
|
||
|
|
||
|
case msggTimer:
|
||
|
return KlondTimer(pgm, (INT)wp1, (INT)wp2);
|
||
|
|
||
|
|
||
|
case msggDrawStatus:
|
||
|
return KlondDrawStatus(pgm, (RC *) wp1);
|
||
|
}
|
||
|
return DefGmProc(pgm, msgg, wp1, wp2);
|
||
|
}
|