Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

590 lines
17 KiB

  1. /****************************************************************************
  2. Dialog.c
  3. June 91, JimH initial code
  4. Oct 91, JimH port to Win32
  5. Contains dialog box callback procedures.
  6. ****************************************************************************/
  7. #include "freecell.h"
  8. #include "freecons.h"
  9. static void CentreDialog(HWND hDlg);
  10. /****************************************************************************
  11. MoveColDlg
  12. If there is ambiguity about whether the user intends to move a single card
  13. or a column to an empty column, this dialog lets the user decide.
  14. The return code in EndDialog tells the caller the user's choice:
  15. -1 user chose cancel
  16. FALSE user chose to move a single card
  17. TRUE user chose to move a column
  18. ****************************************************************************/
  19. INT_PTR APIENTRY MoveColDlg(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam)
  20. {
  21. switch (message) {
  22. case WM_INITDIALOG:
  23. CentreDialog(hDlg);
  24. return TRUE;
  25. case WM_COMMAND:
  26. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  27. case IDCANCEL:
  28. EndDialog(hDlg, -1);
  29. return TRUE;
  30. break;
  31. case IDC_SINGLE:
  32. EndDialog(hDlg, FALSE);
  33. return TRUE;
  34. break;
  35. case IDC_MOVECOL:
  36. EndDialog(hDlg, TRUE);
  37. return TRUE;
  38. break;
  39. }
  40. break;
  41. }
  42. return FALSE; /* Didn't process a message */
  43. }
  44. /****************************************************************************
  45. GameNumDlg
  46. The variable gamenumber must be set with a default value before this
  47. dialog is invoked. That number is placed in an edit box where the user
  48. can accept it by pressing Enter or change it. EndDialog returns TRUE
  49. if the user chose a valid number (1 to MAXGAMENUMBER) and FALSE otherwise.
  50. ****************************************************************************/
  51. INT_PTR APIENTRY GameNumDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  52. {
  53. // For context sensitive help
  54. static DWORD aIds[] = {
  55. IDC_GAMENUM, IDH_GAMENUM,
  56. 0,0 };
  57. switch (message) {
  58. case WM_INITDIALOG: // set default gamenumber
  59. CentreDialog(hDlg);
  60. SetDlgItemInt(hDlg, IDC_GAMENUM, gamenumber, FALSE);
  61. return TRUE;
  62. case WM_COMMAND:
  63. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  64. case IDCANCEL:
  65. gamenumber = CANCELGAME;
  66. EndDialog(hDlg, TRUE);
  67. return TRUE;
  68. case IDOK:
  69. gamenumber = (int) GetDlgItemInt(hDlg, IDC_GAMENUM, NULL, TRUE);
  70. // negative #s are special cases -- unwinnable shuffles
  71. if (gamenumber < -2 || gamenumber > MAXGAMENUMBER)
  72. gamenumber = 0;
  73. EndDialog(hDlg, gamenumber != 0);
  74. return TRUE;
  75. }
  76. break;
  77. // context sensitive help.
  78. case WM_HELP:
  79. WinHelp(((LPHELPINFO) lParam)->hItemHandle, TEXT("freecell.hlp"),
  80. HELP_WM_HELP, (ULONG_PTR) aIds);
  81. break;
  82. case WM_CONTEXTMENU:
  83. WinHelp((HWND) wParam, TEXT("freecell.hlp"), HELP_CONTEXTMENU,
  84. (ULONG_PTR) aIds);
  85. break;
  86. }
  87. return FALSE;
  88. }
  89. /****************************************************************************
  90. YouWinDlg(HWND, unsigned, UINT, LONG)
  91. ****************************************************************************/
  92. INT_PTR APIENTRY YouWinDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  93. {
  94. HWND hSelect; // handle to check box
  95. switch (message) {
  96. case WM_INITDIALOG: // initialize checkbox
  97. hSelect = GetDlgItem(hDlg, IDC_YWSELECT);
  98. SendMessage(hSelect, BM_SETCHECK, bSelecting, 0);
  99. return TRUE;
  100. case WM_COMMAND:
  101. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  102. case IDYES:
  103. hSelect = GetDlgItem(hDlg, IDC_YWSELECT);
  104. bSelecting = (BOOL) SendMessage(hSelect, BM_GETCHECK, 0, 0);
  105. EndDialog(hDlg, IDYES);
  106. return TRUE;
  107. case IDNO:
  108. case IDCANCEL:
  109. EndDialog(hDlg, IDNO);
  110. return TRUE;
  111. }
  112. break;
  113. }
  114. return FALSE; // didn't process a message
  115. }
  116. /****************************************************************************
  117. YouLoseDlg
  118. The user can choose to play a new game (same shuffle or new shuffle) or not.
  119. ****************************************************************************/
  120. INT_PTR APIENTRY YouLoseDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  121. {
  122. HWND hSameGame; // handle to check box
  123. BOOL bSame; // value of check box
  124. switch (message) {
  125. case WM_INITDIALOG:
  126. CentreDialog(hDlg);
  127. bGameInProgress = FALSE;
  128. UpdateLossCount();
  129. hSameGame = GetDlgItem(hDlg, IDC_YLSAME);
  130. SendMessage(hSameGame, BM_SETCHECK, TRUE, 0); // default to same
  131. return TRUE;
  132. case WM_COMMAND:
  133. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  134. case IDYES:
  135. case IDOK:
  136. hSameGame = GetDlgItem(hDlg, IDC_YLSAME);
  137. bSame = (BOOL) SendMessage(hSameGame, BM_GETCHECK, 0, 0);
  138. if (bSame)
  139. PostMessage(hMainWnd,WM_COMMAND,IDM_RESTART,gamenumber);
  140. else
  141. {
  142. if (bSelecting)
  143. PostMessage(hMainWnd, WM_COMMAND, IDM_SELECT, 0);
  144. else
  145. PostMessage(hMainWnd, WM_COMMAND, IDM_NEWGAME, 0);
  146. }
  147. EndDialog(hDlg, TRUE);
  148. return TRUE;
  149. case IDNO:
  150. case IDCANCEL:
  151. gamenumber = 0;
  152. EndDialog(hDlg, FALSE);
  153. return TRUE;
  154. }
  155. break;
  156. }
  157. return FALSE;
  158. }
  159. #define ARRAYSIZE(a) ( sizeof(a) / sizeof(a[0]) )
  160. /****************************************************************************
  161. StatsDlg
  162. This dialog box shows current wins and losses, as well as total stats
  163. including data from .ini file.
  164. The IDC_CLEAR message clears out the entire section from the .ini file.
  165. ****************************************************************************/
  166. INT_PTR APIENTRY StatsDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  167. {
  168. HWND hText; // handle to text control with stats
  169. UINT cTLost, cTWon; // total losses and wins
  170. UINT cTLosses, cTWins; // streaks
  171. UINT wPct; // winning % this session
  172. UINT wTPct; // winning % including .ini data
  173. UINT wStreak; // current streak amount
  174. UINT wSType; // current streak type
  175. TCHAR sbuffer[40]; // streak buffer
  176. int nResp; // messagebox response
  177. TCHAR buffer[256]; // extra buffer needed for loadingstrings.
  178. LONG lRegResult; // used to store return code from registry call
  179. // for context sensitive help
  180. static DWORD aIds[] = {
  181. IDC_CLEAR, IDH_CLEAR,
  182. IDC_STEXT1, IDH_STEXT1,
  183. IDC_STEXT2, IDH_STEXT2,
  184. IDC_STEXT3, IDH_STEXT3,
  185. 0,0 };
  186. switch (message) {
  187. case WM_INITDIALOG:
  188. CentreDialog(hDlg);
  189. wPct = CalcPercentage(cWins, cLosses);
  190. /* Get cT... data from the registry */
  191. lRegResult = REGOPEN
  192. if (ERROR_SUCCESS == lRegResult)
  193. {
  194. cTLost = GetInt(pszLost, 0);
  195. cTWon = GetInt(pszWon, 0);
  196. wTPct = CalcPercentage(cTWon, cTLost);
  197. cTLosses = GetInt(pszLosses, 0);
  198. cTWins = GetInt(pszWins, 0);
  199. wStreak = GetInt(pszStreak, 0);
  200. if (wStreak != 0)
  201. {
  202. wSType = GetInt(pszSType, 0);
  203. if (wStreak == 1)
  204. {
  205. LoadString(hInst, (wSType == WON ? IDS_1WIN : IDS_1LOSS),
  206. sbuffer, ARRAYSIZE(sbuffer));
  207. }
  208. else
  209. {
  210. LoadString(hInst, (wSType == WON ? IDS_WINS : IDS_LOSSES),
  211. smallbuf, SMALL);
  212. wsprintf(sbuffer, smallbuf, wStreak);
  213. }
  214. }
  215. else
  216. wsprintf(sbuffer, TEXT("%u"), 0);
  217. // set the dialog text.
  218. LoadString(hInst, IDS_STATS1, buffer, ARRAYSIZE(buffer));
  219. wsprintf(bigbuf, buffer, wPct, cWins, cLosses);
  220. hText = GetDlgItem(hDlg, IDC_STEXT1);
  221. SetWindowText(hText, bigbuf);
  222. LoadString(hInst, IDS_STATS2, buffer, ARRAYSIZE(buffer));
  223. wsprintf(bigbuf, buffer, wTPct, cTWon, cTLost);
  224. hText = GetDlgItem(hDlg, IDC_STEXT2);
  225. SetWindowText(hText, bigbuf);
  226. LoadString(hInst, IDS_STATS3, buffer, ARRAYSIZE(buffer));
  227. wsprintf(bigbuf, buffer, cTWins, cTLosses, (LPTSTR) sbuffer);
  228. hText = GetDlgItem(hDlg, IDC_STEXT3);
  229. SetWindowText(hText, bigbuf);
  230. REGCLOSE;
  231. }
  232. return TRUE;
  233. case WM_COMMAND:
  234. switch (GET_WM_COMMAND_ID(wParam, lParam)) {
  235. case IDOK:
  236. case IDCANCEL:
  237. EndDialog(hDlg, TRUE);
  238. return TRUE;
  239. case IDC_CLEAR:
  240. LoadString(hInst, IDS_APPNAME, smallbuf, SMALL);
  241. LoadString(hInst, IDS_RU_SURE, bigbuf, BIG);
  242. MessageBeep(MB_ICONQUESTION);
  243. nResp = MessageBox(hDlg, bigbuf, smallbuf,
  244. MB_YESNO | MB_ICONQUESTION);
  245. if (nResp == IDNO)
  246. break;
  247. lRegResult = REGOPEN
  248. if (ERROR_SUCCESS == lRegResult)
  249. {
  250. DeleteValue(pszWon);
  251. DeleteValue(pszLost);
  252. DeleteValue(pszWins);
  253. DeleteValue(pszLosses);
  254. DeleteValue(pszStreak);
  255. DeleteValue(pszSType);
  256. REGCLOSE
  257. }
  258. cWins = 0;
  259. cLosses = 0;
  260. EndDialog(hDlg, FALSE);
  261. return TRUE;
  262. }
  263. break;
  264. // context sensitive help.
  265. case WM_HELP:
  266. WinHelp(((LPHELPINFO) lParam)->hItemHandle, TEXT("freecell.hlp"),
  267. HELP_WM_HELP, (ULONG_PTR) aIds);
  268. break;
  269. case WM_CONTEXTMENU:
  270. WinHelp((HWND) wParam, TEXT("freecell.hlp"), HELP_CONTEXTMENU,
  271. (ULONG_PTR) aIds);
  272. break;
  273. }
  274. return FALSE;
  275. }
  276. /****************************************************************************
  277. CalcPercentage
  278. Percentage is rounded off, but never up to 100.
  279. ****************************************************************************/
  280. UINT CalcPercentage(UINT cWins, UINT cLosses)
  281. {
  282. UINT wPct = 0;
  283. UINT lDenom; // denominator
  284. lDenom = cWins + cLosses;
  285. if (lDenom != 0L)
  286. wPct = (((cWins * 200) + lDenom) / (2 * lDenom));
  287. if (wPct >= 100 && cLosses != 0)
  288. wPct = 99;
  289. return wPct;
  290. }
  291. /****************************************************************************
  292. GetHelpFileName()
  293. Puts the full path name of the helpfile in bigbuf
  294. side effect: contents of bigbuf are altered
  295. ****************************************************************************/
  296. CHAR *GetHelpFileName()
  297. {
  298. CHAR *psz; // used to construct pathname
  299. psz = bighelpbuf + GetModuleFileNameA(hInst, bighelpbuf, BIG-1);
  300. if (psz - bighelpbuf > 4)
  301. {
  302. while (*psz != '.')
  303. --psz;
  304. }
  305. strcpy(psz, ".chm");
  306. return bighelpbuf;
  307. }
  308. /****************************************************************************
  309. Options Dlg
  310. ****************************************************************************/
  311. INT_PTR OptionsDlg(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  312. {
  313. HWND hMessages; // handle to messages checkbox
  314. HWND hQuick; // quick checkbox
  315. HWND hDblClick; // double click checkbox
  316. // For context sensitive help
  317. static DWORD aIds[] = {
  318. IDC_MESSAGES, IDH_OPTIONS_MESSAGES,
  319. IDC_QUICK, IDH_OPTIONS_QUICK,
  320. IDC_DBLCLICK, IDH_OPTIONS_DBLCLICK,
  321. 0,0 };
  322. switch (message) {
  323. case WM_INITDIALOG:
  324. CentreDialog(hDlg);
  325. hMessages = GetDlgItem(hDlg, IDC_MESSAGES);
  326. SendMessage(hMessages, BM_SETCHECK, bMessages, 0);
  327. hQuick = GetDlgItem(hDlg, IDC_QUICK);
  328. SendMessage(hQuick, BM_SETCHECK, bFastMode, 0);
  329. hDblClick = GetDlgItem(hDlg, IDC_DBLCLICK);
  330. SendMessage(hDblClick, BM_SETCHECK, bDblClick, 0);
  331. return TRUE;
  332. case WM_COMMAND:
  333. switch (wParam) {
  334. case IDYES:
  335. case IDOK:
  336. hMessages = GetDlgItem(hDlg, IDC_MESSAGES);
  337. bMessages = (BOOL)SendMessage(hMessages, BM_GETCHECK, 0, 0);
  338. hQuick = GetDlgItem(hDlg, IDC_QUICK);
  339. bFastMode = (BOOL)SendMessage(hQuick, BM_GETCHECK, 0, 0);
  340. hDblClick = GetDlgItem(hDlg, IDC_DBLCLICK);
  341. bDblClick = (BOOL)SendMessage(hDblClick, BM_GETCHECK, 0, 0);
  342. EndDialog(hDlg, TRUE);
  343. return TRUE;
  344. case IDNO:
  345. case IDCANCEL:
  346. EndDialog(hDlg, FALSE);
  347. return TRUE;
  348. }
  349. break;
  350. // context sensitive help.
  351. case WM_HELP:
  352. WinHelp(((LPHELPINFO) lParam)->hItemHandle, TEXT("freecell.hlp"),
  353. HELP_WM_HELP, (ULONG_PTR) aIds);
  354. break;
  355. case WM_CONTEXTMENU:
  356. WinHelp((HWND) wParam, TEXT("freecell.hlp"), HELP_CONTEXTMENU,
  357. (ULONG_PTR) aIds);
  358. break;
  359. }
  360. return FALSE;
  361. }
  362. /****************************************************************************
  363. ReadOptions and WriteOptions retrieve and update .ini file
  364. ****************************************************************************/
  365. VOID ReadOptions()
  366. {
  367. LONG lRegResult = REGOPEN
  368. if (ERROR_SUCCESS == lRegResult)
  369. {
  370. bMessages = GetInt(pszMessages, TRUE);
  371. bFastMode = GetInt(pszQuick, FALSE);
  372. bDblClick = GetInt(pszDblClick, TRUE);
  373. REGCLOSE
  374. }
  375. }
  376. VOID WriteOptions()
  377. {
  378. LONG lRegResult = REGOPEN
  379. if (ERROR_SUCCESS == lRegResult)
  380. {
  381. if (bMessages)
  382. DeleteValue(pszMessages);
  383. else
  384. SetInt(pszMessages, 0);
  385. if (bFastMode)
  386. SetInt(pszQuick, 1);
  387. else
  388. DeleteValue(pszQuick);
  389. if (bDblClick)
  390. DeleteValue(pszDblClick);
  391. else
  392. SetInt(pszDblClick, 0);
  393. RegFlushKey(hkey);
  394. REGCLOSE
  395. }
  396. }
  397. /****************************************************************************
  398. Registry helper functions
  399. These all assume that REGOPEN has been called first.
  400. Remember to REGCLOSE when you're done.
  401. DeleteValue is implemented as a macro.
  402. ****************************************************************************/
  403. int GetInt(const TCHAR *pszValue, int nDefault)
  404. {
  405. DWORD dwType = REG_BINARY;
  406. DWORD dwSize = sizeof(LONG_PTR);
  407. LONG_PTR dwNumber, ret;
  408. if (!hkey)
  409. return nDefault;
  410. ret = RegQueryValueEx(hkey, pszValue, 0, &dwType, (LPBYTE)&dwNumber,
  411. &dwSize);
  412. if (ret)
  413. return nDefault;
  414. return (int)dwNumber;
  415. }
  416. long SetInt(const TCHAR *pszValue, int n)
  417. {
  418. long dwNumber = (long)n;
  419. if (hkey)
  420. return RegSetValueEx(hkey, pszValue, 0, REG_BINARY,
  421. (unsigned char *)&dwNumber, sizeof(dwNumber));
  422. else
  423. return 1;
  424. }
  425. /****************************************************************************
  426. CentreDialog
  427. ****************************************************************************/
  428. void CentreDialog(HWND hDlg)
  429. {
  430. RECT rcDlg, rcMainWnd, rcOffset;
  431. GetClientRect(hMainWnd, &rcMainWnd);
  432. GetClientRect(hDlg, &rcDlg);
  433. GetWindowRect(hMainWnd, &rcOffset);
  434. rcOffset.top += GetSystemMetrics(SM_CYCAPTION);
  435. rcOffset.top += GetSystemMetrics(SM_CYMENU);
  436. SetWindowPos(hDlg, 0,
  437. ((rcMainWnd.right - rcDlg.right) / 2) + rcOffset.left,
  438. ((rcMainWnd.bottom - rcDlg.bottom) / 2) + rcOffset.top,
  439. 0, 0, SWP_NOSIZE | SWP_NOZORDER);
  440. }