591 lines
17 KiB
C
591 lines
17 KiB
C
/****************************************************************************
|
|
|
|
Dialog.c
|
|
|
|
June 91, JimH initial code
|
|
Oct 91, JimH port to Win32
|
|
|
|
Contains dialog box callback procedures.
|
|
|
|
****************************************************************************/
|
|
|
|
#include "freecell.h"
|
|
#include "freecons.h"
|
|
|
|
|
|
static void CentreDialog(HWND hDlg);
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
MoveColDlg
|
|
|
|
If there is ambiguity about whether the user intends to move a single card
|
|
or a column to an empty column, this dialog lets the user decide.
|
|
|
|
The return code in EndDialog tells the caller the user's choice:
|
|
-1 user chose cancel
|
|
FALSE user chose to move a single card
|
|
TRUE user chose to move a column
|
|
|
|
****************************************************************************/
|
|
|
|
INT_PTR APIENTRY MoveColDlg(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)
|
|
{
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
CentreDialog(hDlg);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, -1);
|
|
return TRUE;
|
|
break;
|
|
|
|
case IDC_SINGLE:
|
|
EndDialog(hDlg, FALSE);
|
|
return TRUE;
|
|
break;
|
|
|
|
case IDC_MOVECOL:
|
|
EndDialog(hDlg, TRUE);
|
|
return TRUE;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return FALSE; /* Didn't process a message */
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
GameNumDlg
|
|
|
|
The variable gamenumber must be set with a default value before this
|
|
dialog is invoked. That number is placed in an edit box where the user
|
|
can accept it by pressing Enter or change it. EndDialog returns TRUE
|
|
if the user chose a valid number (1 to MAXGAMENUMBER) and FALSE otherwise.
|
|
|
|
****************************************************************************/
|
|
|
|
INT_PTR APIENTRY GameNumDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
// For context sensitive help
|
|
static DWORD aIds[] = {
|
|
IDC_GAMENUM, IDH_GAMENUM,
|
|
0,0 };
|
|
|
|
switch (message) {
|
|
case WM_INITDIALOG: // set default gamenumber
|
|
CentreDialog(hDlg);
|
|
SetDlgItemInt(hDlg, IDC_GAMENUM, gamenumber, FALSE);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
|
case IDCANCEL:
|
|
gamenumber = CANCELGAME;
|
|
EndDialog(hDlg, TRUE);
|
|
return TRUE;
|
|
|
|
case IDOK:
|
|
gamenumber = (int) GetDlgItemInt(hDlg, IDC_GAMENUM, NULL, TRUE);
|
|
|
|
// negative #s are special cases -- unwinnable shuffles
|
|
|
|
if (gamenumber < -2 || gamenumber > MAXGAMENUMBER)
|
|
gamenumber = 0;
|
|
EndDialog(hDlg, gamenumber != 0);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
// context sensitive help.
|
|
case WM_HELP:
|
|
WinHelp(((LPHELPINFO) lParam)->hItemHandle, TEXT("freecell.hlp"),
|
|
HELP_WM_HELP, (ULONG_PTR) aIds);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
WinHelp((HWND) wParam, TEXT("freecell.hlp"), HELP_CONTEXTMENU,
|
|
(ULONG_PTR) aIds);
|
|
break;
|
|
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
YouWinDlg(HWND, unsigned, UINT, LONG)
|
|
|
|
****************************************************************************/
|
|
|
|
INT_PTR APIENTRY YouWinDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HWND hSelect; // handle to check box
|
|
|
|
switch (message) {
|
|
case WM_INITDIALOG: // initialize checkbox
|
|
hSelect = GetDlgItem(hDlg, IDC_YWSELECT);
|
|
SendMessage(hSelect, BM_SETCHECK, bSelecting, 0);
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
|
case IDYES:
|
|
hSelect = GetDlgItem(hDlg, IDC_YWSELECT);
|
|
bSelecting = (BOOL) SendMessage(hSelect, BM_GETCHECK, 0, 0);
|
|
EndDialog(hDlg, IDYES);
|
|
return TRUE;
|
|
|
|
case IDNO:
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, IDNO);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
return FALSE; // didn't process a message
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
YouLoseDlg
|
|
|
|
The user can choose to play a new game (same shuffle or new shuffle) or not.
|
|
|
|
****************************************************************************/
|
|
|
|
INT_PTR APIENTRY YouLoseDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HWND hSameGame; // handle to check box
|
|
BOOL bSame; // value of check box
|
|
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
CentreDialog(hDlg);
|
|
bGameInProgress = FALSE;
|
|
UpdateLossCount();
|
|
hSameGame = GetDlgItem(hDlg, IDC_YLSAME);
|
|
SendMessage(hSameGame, BM_SETCHECK, TRUE, 0); // default to same
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
|
case IDYES:
|
|
case IDOK:
|
|
hSameGame = GetDlgItem(hDlg, IDC_YLSAME);
|
|
bSame = (BOOL) SendMessage(hSameGame, BM_GETCHECK, 0, 0);
|
|
if (bSame)
|
|
PostMessage(hMainWnd,WM_COMMAND,IDM_RESTART,gamenumber);
|
|
else
|
|
{
|
|
if (bSelecting)
|
|
PostMessage(hMainWnd, WM_COMMAND, IDM_SELECT, 0);
|
|
else
|
|
PostMessage(hMainWnd, WM_COMMAND, IDM_NEWGAME, 0);
|
|
}
|
|
EndDialog(hDlg, TRUE);
|
|
return TRUE;
|
|
|
|
case IDNO:
|
|
case IDCANCEL:
|
|
gamenumber = 0;
|
|
EndDialog(hDlg, FALSE);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
#define ARRAYSIZE(a) ( sizeof(a) / sizeof(a[0]) )
|
|
|
|
/****************************************************************************
|
|
|
|
StatsDlg
|
|
|
|
This dialog box shows current wins and losses, as well as total stats
|
|
including data from .ini file.
|
|
|
|
The IDC_CLEAR message clears out the entire section from the .ini file.
|
|
|
|
****************************************************************************/
|
|
|
|
INT_PTR APIENTRY StatsDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HWND hText; // handle to text control with stats
|
|
UINT cTLost, cTWon; // total losses and wins
|
|
UINT cTLosses, cTWins; // streaks
|
|
UINT wPct; // winning % this session
|
|
UINT wTPct; // winning % including .ini data
|
|
UINT wStreak; // current streak amount
|
|
UINT wSType; // current streak type
|
|
TCHAR sbuffer[40]; // streak buffer
|
|
int nResp; // messagebox response
|
|
TCHAR buffer[256]; // extra buffer needed for loadingstrings.
|
|
LONG lRegResult; // used to store return code from registry call
|
|
|
|
// for context sensitive help
|
|
static DWORD aIds[] = {
|
|
IDC_CLEAR, IDH_CLEAR,
|
|
IDC_STEXT1, IDH_STEXT1,
|
|
IDC_STEXT2, IDH_STEXT2,
|
|
IDC_STEXT3, IDH_STEXT3,
|
|
0,0 };
|
|
|
|
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
CentreDialog(hDlg);
|
|
wPct = CalcPercentage(cWins, cLosses);
|
|
|
|
/* Get cT... data from the registry */
|
|
|
|
lRegResult = REGOPEN
|
|
|
|
if (ERROR_SUCCESS == lRegResult)
|
|
{
|
|
cTLost = GetInt(pszLost, 0);
|
|
cTWon = GetInt(pszWon, 0);
|
|
|
|
wTPct = CalcPercentage(cTWon, cTLost);
|
|
|
|
cTLosses = GetInt(pszLosses, 0);
|
|
cTWins = GetInt(pszWins, 0);
|
|
|
|
wStreak = GetInt(pszStreak, 0);
|
|
if (wStreak != 0)
|
|
{
|
|
wSType = GetInt(pszSType, 0);
|
|
|
|
if (wStreak == 1)
|
|
{
|
|
LoadString(hInst, (wSType == WON ? IDS_1WIN : IDS_1LOSS),
|
|
sbuffer, ARRAYSIZE(sbuffer));
|
|
}
|
|
else
|
|
{
|
|
LoadString(hInst, (wSType == WON ? IDS_WINS : IDS_LOSSES),
|
|
smallbuf, SMALL);
|
|
wsprintf(sbuffer, smallbuf, wStreak);
|
|
}
|
|
}
|
|
else
|
|
wsprintf(sbuffer, TEXT("%u"), 0);
|
|
|
|
// set the dialog text.
|
|
LoadString(hInst, IDS_STATS1, buffer, ARRAYSIZE(buffer));
|
|
wsprintf(bigbuf, buffer, wPct, cWins, cLosses);
|
|
hText = GetDlgItem(hDlg, IDC_STEXT1);
|
|
SetWindowText(hText, bigbuf);
|
|
|
|
LoadString(hInst, IDS_STATS2, buffer, ARRAYSIZE(buffer));
|
|
wsprintf(bigbuf, buffer, wTPct, cTWon, cTLost);
|
|
hText = GetDlgItem(hDlg, IDC_STEXT2);
|
|
SetWindowText(hText, bigbuf);
|
|
|
|
LoadString(hInst, IDS_STATS3, buffer, ARRAYSIZE(buffer));
|
|
wsprintf(bigbuf, buffer, cTWins, cTLosses, (LPTSTR) sbuffer);
|
|
hText = GetDlgItem(hDlg, IDC_STEXT3);
|
|
SetWindowText(hText, bigbuf);
|
|
|
|
|
|
REGCLOSE;
|
|
}
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
|
case IDOK:
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, TRUE);
|
|
return TRUE;
|
|
|
|
case IDC_CLEAR:
|
|
LoadString(hInst, IDS_APPNAME, smallbuf, SMALL);
|
|
LoadString(hInst, IDS_RU_SURE, bigbuf, BIG);
|
|
MessageBeep(MB_ICONQUESTION);
|
|
nResp = MessageBox(hDlg, bigbuf, smallbuf,
|
|
MB_YESNO | MB_ICONQUESTION);
|
|
if (nResp == IDNO)
|
|
break;
|
|
|
|
lRegResult = REGOPEN
|
|
|
|
if (ERROR_SUCCESS == lRegResult)
|
|
{
|
|
DeleteValue(pszWon);
|
|
DeleteValue(pszLost);
|
|
DeleteValue(pszWins);
|
|
DeleteValue(pszLosses);
|
|
DeleteValue(pszStreak);
|
|
DeleteValue(pszSType);
|
|
REGCLOSE
|
|
}
|
|
|
|
cWins = 0;
|
|
cLosses = 0;
|
|
EndDialog(hDlg, FALSE);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
// context sensitive help.
|
|
case WM_HELP:
|
|
WinHelp(((LPHELPINFO) lParam)->hItemHandle, TEXT("freecell.hlp"),
|
|
HELP_WM_HELP, (ULONG_PTR) aIds);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
WinHelp((HWND) wParam, TEXT("freecell.hlp"), HELP_CONTEXTMENU,
|
|
(ULONG_PTR) aIds);
|
|
break;
|
|
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
CalcPercentage
|
|
|
|
Percentage is rounded off, but never up to 100.
|
|
|
|
****************************************************************************/
|
|
|
|
UINT CalcPercentage(UINT cWins, UINT cLosses)
|
|
{
|
|
UINT wPct = 0;
|
|
UINT lDenom; // denominator
|
|
|
|
lDenom = cWins + cLosses;
|
|
|
|
if (lDenom != 0L)
|
|
wPct = (((cWins * 200) + lDenom) / (2 * lDenom));
|
|
|
|
if (wPct >= 100 && cLosses != 0)
|
|
wPct = 99;
|
|
|
|
return wPct;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
GetHelpFileName()
|
|
|
|
Puts the full path name of the helpfile in bigbuf
|
|
side effect: contents of bigbuf are altered
|
|
|
|
****************************************************************************/
|
|
|
|
CHAR *GetHelpFileName()
|
|
{
|
|
CHAR *psz; // used to construct pathname
|
|
|
|
psz = bighelpbuf + GetModuleFileNameA(hInst, bighelpbuf, BIG-1);
|
|
|
|
if (psz - bighelpbuf > 4)
|
|
{
|
|
while (*psz != '.')
|
|
--psz;
|
|
}
|
|
|
|
strcpy(psz, ".chm");
|
|
|
|
return bighelpbuf;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Options Dlg
|
|
|
|
****************************************************************************/
|
|
|
|
INT_PTR OptionsDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HWND hMessages; // handle to messages checkbox
|
|
HWND hQuick; // quick checkbox
|
|
HWND hDblClick; // double click checkbox
|
|
|
|
|
|
// For context sensitive help
|
|
static DWORD aIds[] = {
|
|
IDC_MESSAGES, IDH_OPTIONS_MESSAGES,
|
|
IDC_QUICK, IDH_OPTIONS_QUICK,
|
|
IDC_DBLCLICK, IDH_OPTIONS_DBLCLICK,
|
|
0,0 };
|
|
|
|
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
CentreDialog(hDlg);
|
|
hMessages = GetDlgItem(hDlg, IDC_MESSAGES);
|
|
SendMessage(hMessages, BM_SETCHECK, bMessages, 0);
|
|
|
|
hQuick = GetDlgItem(hDlg, IDC_QUICK);
|
|
SendMessage(hQuick, BM_SETCHECK, bFastMode, 0);
|
|
|
|
hDblClick = GetDlgItem(hDlg, IDC_DBLCLICK);
|
|
SendMessage(hDblClick, BM_SETCHECK, bDblClick, 0);
|
|
|
|
return TRUE;
|
|
|
|
case WM_COMMAND:
|
|
switch (wParam) {
|
|
case IDYES:
|
|
case IDOK:
|
|
hMessages = GetDlgItem(hDlg, IDC_MESSAGES);
|
|
bMessages = (BOOL)SendMessage(hMessages, BM_GETCHECK, 0, 0);
|
|
|
|
hQuick = GetDlgItem(hDlg, IDC_QUICK);
|
|
bFastMode = (BOOL)SendMessage(hQuick, BM_GETCHECK, 0, 0);
|
|
|
|
hDblClick = GetDlgItem(hDlg, IDC_DBLCLICK);
|
|
bDblClick = (BOOL)SendMessage(hDblClick, BM_GETCHECK, 0, 0);
|
|
|
|
EndDialog(hDlg, TRUE);
|
|
return TRUE;
|
|
|
|
case IDNO:
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, FALSE);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
// context sensitive help.
|
|
case WM_HELP:
|
|
WinHelp(((LPHELPINFO) lParam)->hItemHandle, TEXT("freecell.hlp"),
|
|
HELP_WM_HELP, (ULONG_PTR) aIds);
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
WinHelp((HWND) wParam, TEXT("freecell.hlp"), HELP_CONTEXTMENU,
|
|
(ULONG_PTR) aIds);
|
|
break;
|
|
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
ReadOptions and WriteOptions retrieve and update .ini file
|
|
|
|
****************************************************************************/
|
|
|
|
VOID ReadOptions()
|
|
{
|
|
LONG lRegResult = REGOPEN
|
|
|
|
if (ERROR_SUCCESS == lRegResult)
|
|
{
|
|
bMessages = GetInt(pszMessages, TRUE);
|
|
bFastMode = GetInt(pszQuick, FALSE);
|
|
bDblClick = GetInt(pszDblClick, TRUE);
|
|
REGCLOSE
|
|
}
|
|
}
|
|
|
|
|
|
VOID WriteOptions()
|
|
{
|
|
LONG lRegResult = REGOPEN
|
|
|
|
if (ERROR_SUCCESS == lRegResult)
|
|
{
|
|
if (bMessages)
|
|
DeleteValue(pszMessages);
|
|
else
|
|
SetInt(pszMessages, 0);
|
|
|
|
if (bFastMode)
|
|
SetInt(pszQuick, 1);
|
|
else
|
|
DeleteValue(pszQuick);
|
|
|
|
if (bDblClick)
|
|
DeleteValue(pszDblClick);
|
|
else
|
|
SetInt(pszDblClick, 0);
|
|
|
|
RegFlushKey(hkey);
|
|
|
|
REGCLOSE
|
|
}
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
Registry helper functions
|
|
|
|
These all assume that REGOPEN has been called first.
|
|
Remember to REGCLOSE when you're done.
|
|
DeleteValue is implemented as a macro.
|
|
|
|
****************************************************************************/
|
|
|
|
int GetInt(const TCHAR *pszValue, int nDefault)
|
|
{
|
|
DWORD dwType = REG_BINARY;
|
|
DWORD dwSize = sizeof(LONG_PTR);
|
|
LONG_PTR dwNumber, ret;
|
|
|
|
if (!hkey)
|
|
return nDefault;
|
|
|
|
ret = RegQueryValueEx(hkey, pszValue, 0, &dwType, (LPBYTE)&dwNumber,
|
|
&dwSize);
|
|
|
|
if (ret)
|
|
return nDefault;
|
|
|
|
return (int)dwNumber;
|
|
}
|
|
|
|
long SetInt(const TCHAR *pszValue, int n)
|
|
{
|
|
long dwNumber = (long)n;
|
|
if (hkey)
|
|
return RegSetValueEx(hkey, pszValue, 0, REG_BINARY,
|
|
(unsigned char *)&dwNumber, sizeof(dwNumber));
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
CentreDialog
|
|
|
|
****************************************************************************/
|
|
void CentreDialog(HWND hDlg)
|
|
{
|
|
RECT rcDlg, rcMainWnd, rcOffset;
|
|
|
|
GetClientRect(hMainWnd, &rcMainWnd);
|
|
GetClientRect(hDlg, &rcDlg);
|
|
GetWindowRect(hMainWnd, &rcOffset);
|
|
rcOffset.top += GetSystemMetrics(SM_CYCAPTION);
|
|
rcOffset.top += GetSystemMetrics(SM_CYMENU);
|
|
|
|
SetWindowPos(hDlg, 0,
|
|
((rcMainWnd.right - rcDlg.right) / 2) + rcOffset.left,
|
|
((rcMainWnd.bottom - rcDlg.bottom) / 2) + rcOffset.top,
|
|
0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
|
}
|