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.

1432 lines
40 KiB

  1. #include <windows.h>
  2. #include <port1632.h>
  3. #include "cards.h"
  4. #include "cruel.h"
  5. #include "cdt.h"
  6. #include "stdlib.h"
  7. typedef INT X;
  8. typedef INT Y;
  9. typedef INT DX;
  10. typedef INT DY;
  11. // ReCt structure
  12. typedef struct _rc
  13. {
  14. X xLeft;
  15. Y yTop;
  16. X xRight;
  17. Y yBot;
  18. } RC;
  19. #define IDCARDBACK 65
  20. #define ININAME "entpack.ini"
  21. #define APPTITLE "Cruel"
  22. #define HI 0
  23. #define LOW 1
  24. #define SUM 2
  25. #define TOTAL 3
  26. #define WINS 4
  27. #define abs(x) (((x) < 0) ? (-(x)) : (x))
  28. #define NEXT_ROUND 4000
  29. #define INVALID_POS 255
  30. #define MAXUNDOSIZE 100
  31. extern VOID APIENTRY AboutWEP(HWND hwnd, HICON hicon, LPSTR lpTitle, LPSTR lpCredit);
  32. LRESULT APIENTRY WndProc (HWND, UINT, WPARAM, LPARAM) ;
  33. VOID Deal(VOID);
  34. VOID InitBoard(VOID);
  35. VOID DrawLayout(HDC hDC);
  36. VOID DrawFoundation(HDC hDC);
  37. VOID UpdateDeck(HDC hDC);
  38. VOID UpdateLayout(HDC hDC, INT column);
  39. VOID DoWinEffects(HDC hDC);
  40. BOOL MoveCard(HDC hDC, INT startRow, INT startColumn,
  41. INT endRow, INT endColumn,
  42. BOOL bValidate);
  43. VOID RestoreLayout(HDC hDC);
  44. VOID APIENTRY Help(HWND hWnd, UINT wCommand, ULONG_PTR lParam);
  45. VOID UndoMove(HDC hDC);
  46. INT Message(HWND hWnd, WORD wId, WORD wFlags);
  47. VOID MyDrawText(HDC hDC, LPSTR lpBuf, INT w, LPRECT lpRect, WORD wFlags);
  48. BOOL CheckGameOver(VOID);
  49. INT_PTR CALLBACK BackDlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam);
  50. BOOL FDrawFocus(HDC hdc, RC *prc, BOOL fFocus);
  51. VOID ChangeBack(WORD wNewDeckBack);
  52. VOID DoBacks(VOID);
  53. VOID DrawGameOver(VOID);
  54. BOOL fDialog(INT id,HWND hwnd,DLGPROC fpfn);
  55. BOOL APIENTRY cdtDrawExt(HDC hdc, INT x, INT y, INT dx, INT dy, INT cd, INT mode, DWORD rgbBgnd);
  56. BOOL APIENTRY cdtAnimate(HDC hdc, INT cd, INT x, INT y, INT ispr);
  57. VOID DrawAnimate(INT cd, MPOINT *ppt, INT iani);
  58. BOOL DeckAnimate(INT iqsec);
  59. VOID APIENTRY TimerProc(HWND hwnd, UINT wm, UINT_PTR id, DWORD dwTime);
  60. INT_PTR APIENTRY RecordDlgProc(HANDLE hdlg, UINT wm, WPARAM wParam, LPARAM lParam);
  61. LRESULT APIENTRY ReadOnlyProc(HWND hwnd, UINT wMessage, WPARAM wParam, LPARAM lParam);
  62. VOID MarkControlReadOnly(HWND hwndCtrl, BOOL bReadOnly);
  63. VOID ShowStacks(VOID);
  64. VOID SaveState(VOID);
  65. VOID RestoreState(VOID);
  66. LPSTR lstrtok(LPSTR lpStr, LPSTR lpDelim);
  67. static BOOL IsInString(CHAR c, LPSTR s);
  68. VOID DisplayStats(VOID);
  69. INT sprintf();
  70. #if 0
  71. INT init[2][6] = { { 49, 33, 13, 46, 10, 47 },
  72. { 39, 31, 19, 44, 28, 8 }};
  73. #endif
  74. typedef struct tagCardRec {
  75. INT card;
  76. struct tagCardRec *next;
  77. } CardRec;
  78. CardRec *FreeList[52];
  79. INT freePos;
  80. CardRec deck[52];
  81. CardRec *layout[2][6];
  82. RECT layoutRect[2][6];
  83. INT foundation[4];
  84. RECT foundationRect[4];
  85. INT nCards;
  86. LONG nStats[5];
  87. CHAR szAppName[80], szGameOver[80], szGameOverS[80];
  88. CHAR szOOM[256], szRecordTitle[80];
  89. WORD wDeckBack;
  90. BOOL bGameInProgress = FALSE;
  91. typedef struct tagUndoRec {
  92. INT startRow, startColumn, endRow, endColumn;
  93. } UndoRec;
  94. UndoRec undo[MAXUNDOSIZE];
  95. INT undoPos;
  96. INT xClient, yClient, xCard, yCard;
  97. INT xInc, yInc;
  98. DWORD dwBkgnd;
  99. WORD wErrorMessages;
  100. HWND hWnd;
  101. HANDLE hMyInstance;
  102. MMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow) /* { */
  103. MSG msg ;
  104. WNDCLASS wndclass ;
  105. HANDLE hAccel;
  106. if (!LoadString(hInstance, IDSOOM, szOOM, 256)
  107. || !LoadString(hInstance, IDSAppName, szAppName, 80)
  108. || !LoadString(hInstance, IDSGameOver, szGameOver, 80)
  109. || !LoadString(hInstance, IDSGameOverS, szGameOverS, 80)
  110. || !LoadString(hInstance, IDSRecordTitle, szRecordTitle, 80)
  111. )
  112. return FALSE;
  113. if (hPrevInstance) {
  114. hWnd = FindWindow(szAppName, NULL);
  115. if (hWnd)
  116. {
  117. hWnd = GetLastActivePopup(hWnd);
  118. BringWindowToTop(hWnd);
  119. if (IsIconic(hWnd))
  120. ShowWindow(hWnd, SW_RESTORE);
  121. }
  122. return FALSE;
  123. }
  124. wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS ;
  125. wndclass.lpfnWndProc = WndProc ;
  126. wndclass.cbClsExtra = 0 ;
  127. wndclass.cbWndExtra = 0 ;
  128. wndclass.hInstance = hInstance ;
  129. wndclass.hIcon = LoadIcon (hInstance, szAppName) ;
  130. wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
  131. wndclass.hbrBackground = CreateSolidBrush(dwBkgnd = RGB(0,130,0));
  132. wndclass.lpszMenuName = szAppName ;
  133. wndclass.lpszClassName = szAppName ;
  134. if (!RegisterClass (&wndclass))
  135. return FALSE ;
  136. RestoreState();
  137. hWnd = CreateWindow (szAppName, APPTITLE,
  138. WS_OVERLAPPEDWINDOW | WS_MAXIMIZE,
  139. CW_USEDEFAULT, CW_USEDEFAULT,
  140. CW_USEDEFAULT, CW_USEDEFAULT,
  141. NULL, NULL, hInstance, NULL) ;
  142. if (!hWnd)
  143. return FALSE;
  144. hAccel = LoadAccelerators(hInstance, szAppName);
  145. if (!hAccel)
  146. return FALSE;
  147. if(SetTimer(hWnd, 666, 250, TimerProc) == 0) {
  148. return FALSE;
  149. }
  150. ShowWindow (hWnd, SW_SHOWMAXIMIZED) ;
  151. UpdateWindow (hWnd) ;
  152. hMyInstance = hInstance;
  153. while (GetMessage (&msg, NULL, 0, 0))
  154. {
  155. if (!TranslateAccelerator(hWnd, hAccel, &msg)) {
  156. TranslateMessage (&msg) ;
  157. DispatchMessage (&msg) ;
  158. }
  159. }
  160. return (INT) msg.wParam ;
  161. }
  162. VOID MyDrawText(HDC hDC, LPSTR lpBuf, INT w, LPRECT lpRect, WORD wFlags)
  163. {
  164. DWORD dwOldBk, dwOldTextColor;
  165. HBRUSH hBrush, hOldBrush;
  166. dwOldBk = SetBkColor(hDC, dwBkgnd);
  167. dwOldTextColor = SetTextColor(hDC, RGB(255,255,255));
  168. if (hBrush = CreateSolidBrush(dwBkgnd)) {
  169. if (hOldBrush = SelectObject(hDC, hBrush)) {
  170. PatBlt(hDC, lpRect->left, lpRect->top, lpRect->right - lpRect->left,
  171. lpRect->bottom - lpRect->top, PATCOPY);
  172. SelectObject(hDC, hOldBrush);
  173. }
  174. DeleteObject(hBrush);
  175. }
  176. DrawText(hDC, lpBuf, w, lpRect, wFlags);
  177. SetBkColor(hDC, dwOldBk);
  178. SetTextColor(hDC, dwOldTextColor);
  179. }
  180. VOID APIENTRY Help(HWND hWnd, UINT wCommand, ULONG_PTR lParam)
  181. {
  182. CHAR szHelpPath[100], *pPath;
  183. pPath = szHelpPath
  184. + GetModuleFileName(hMyInstance, szHelpPath, 99);
  185. if (pPath != szHelpPath) // if GetModuleFileName succeeded
  186. {
  187. while (*pPath-- != '.')
  188. ;
  189. ++pPath;
  190. *++pPath = 'H';
  191. *++pPath = 'L';
  192. *++pPath = 'P';
  193. *++pPath = '\0';
  194. WinHelp(hWnd, szHelpPath, wCommand, lParam);
  195. }
  196. }
  197. BOOL CheckGameOver(VOID)
  198. {
  199. CardRec *pCard;
  200. INT colStart, colEnd, rowStart, rowEnd;
  201. BOOL bMoveFound;
  202. HDC hDC;
  203. RECT rect;
  204. /* check to see if there is a card to play */
  205. bMoveFound = FALSE;
  206. for (rowStart = 0; rowStart < 2; ++rowStart)
  207. for (colStart = 0; colStart < 6; ++colStart) {
  208. if (!layout[rowStart][colStart])
  209. continue;
  210. for (rowEnd = -1; rowEnd < 2; ++rowEnd)
  211. for (colEnd = 0; colEnd < ((rowEnd < 0) ? 4 : 6); ++colEnd) {
  212. if (rowEnd == -1 && foundation[colEnd] == wDeckBack)
  213. continue;
  214. if (MoveCard(NULL, rowStart, colStart, rowEnd, colEnd, TRUE)) {
  215. bMoveFound = TRUE;
  216. goto endMoveSearch;
  217. }
  218. }
  219. }
  220. endMoveSearch:
  221. /* if a move was found game ain't over! */
  222. if (bMoveFound)
  223. return FALSE;
  224. /* count # of cards left */
  225. nCards = 0;
  226. for (rowStart = 0; rowStart < 2; ++rowStart)
  227. for (colStart = 0; colStart < 6; ++colStart)
  228. for (pCard = layout[rowStart][colStart]; pCard; pCard = pCard->next)
  229. ++nCards;
  230. /* if no cards then we have a winner! */
  231. if (!nCards) {
  232. Message(hWnd, IDSWinner, MB_OK | MB_ICONEXCLAMATION);
  233. undoPos = 0;
  234. }
  235. else
  236. DrawGameOver();
  237. if (!nCards)
  238. ++nStats[WINS];
  239. if (nCards < nStats[LOW])
  240. nStats[LOW] = nCards;
  241. if (nCards > nStats[HI])
  242. nStats[HI] = nCards;
  243. ++nStats[TOTAL];
  244. nStats[SUM] += nCards;
  245. bGameInProgress = FALSE;
  246. return TRUE;
  247. }
  248. VOID DrawGameOver(VOID)
  249. {
  250. HDC hDC;
  251. CHAR buffer[80];
  252. RECT rect;
  253. wsprintf(buffer, (nCards == 1) ? szGameOverS : szGameOver, nCards);
  254. rect.bottom = yClient - 15;
  255. rect.top = rect.bottom - 10;
  256. rect.left = 0;
  257. rect.right = xClient;
  258. if (hDC = GetDC(hWnd)) {
  259. MyDrawText(hDC, buffer, -1, &rect, DT_CENTER | DT_NOCLIP);
  260. ReleaseDC(hWnd, hDC);
  261. }
  262. }
  263. LRESULT APIENTRY WndProc (
  264. HWND hWnd,
  265. UINT iMessage,
  266. WPARAM wParam,
  267. LPARAM lParam)
  268. {
  269. HDC hDC ;
  270. HMENU hMenu;
  271. PAINTSTRUCT ps ;
  272. INT i, j ;
  273. POINT mpt;
  274. MPOINT pt;
  275. RECT tmpRect;
  276. LONG Area, maxArea;
  277. static BOOL fBoard = FALSE;
  278. static HWND hWndButton = NULL;
  279. INT row, column;
  280. static BOOL fTracking = FALSE;
  281. static INT startRow, startColumn, endRow, endColumn;
  282. static RECT trackRect;
  283. static HDC hDCTrack;
  284. static HBRUSH hBrush, hOldBrush;
  285. static HPEN hOldPen;
  286. static MPOINT ptOldPos;
  287. FARPROC lpAbout;
  288. HANDLE hLib;
  289. switch (iMessage)
  290. {
  291. case WM_CREATE:
  292. cdtInit(&xCard, &yCard);
  293. Deal();
  294. startRow = startColumn = endRow = endColumn = INVALID_POS;
  295. hBrush = CreateSolidBrush(dwBkgnd);
  296. if (!hBrush)
  297. return -1L;
  298. CheckGameOver();
  299. break;
  300. case WM_SIZE:
  301. xClient = LOWORD(lParam);
  302. yClient = HIWORD(lParam);
  303. break;
  304. case WM_PAINT:
  305. hDC = BeginPaint (hWnd, &ps) ;
  306. SetBkColor(hDC, dwBkgnd);
  307. if (!fBoard)
  308. {
  309. InitBoard();
  310. if (!hWndButton)
  311. hWndButton = CreateWindow("button", "Deal",
  312. WS_CHILD |
  313. WS_VISIBLE |
  314. BS_DEFPUSHBUTTON,
  315. 20 + 5 * xInc,
  316. 10 + yCard / 4,
  317. xCard,
  318. yCard / 2,
  319. hWnd, (HMENU)NEXT_ROUND,
  320. hMyInstance, NULL);
  321. fBoard = TRUE;
  322. }
  323. DrawLayout(hDC);
  324. DrawFoundation(hDC);
  325. if (!bGameInProgress)
  326. DrawGameOver();
  327. EndPaint(hWnd, &ps);
  328. break;
  329. case WM_LBUTTONDBLCLK:
  330. pt = MAKEMPOINT(lParam);
  331. for (row = 0; row < 2; ++row)
  332. for (column = 0; column < 6; ++column)
  333. {
  334. MPOINT2POINT(pt, mpt);
  335. if (!layout[row][column] ||
  336. !PtInRect(&layoutRect[row][column], mpt))
  337. continue;
  338. i = CardSuit(layout[row][column]->card);
  339. j = CardRank(layout[row][column]->card);
  340. if (CardRank(foundation[i]) == j - 1) {
  341. hDC = GetDC(hWnd);
  342. if (hDC) {
  343. MoveCard(hDC, row, column, -1, i, FALSE);
  344. ReleaseDC(hWnd, hDC);
  345. }
  346. } else {
  347. if (wErrorMessages)
  348. Message(hWnd, IDSNotNextCard, MB_OK);
  349. }
  350. return 0L;
  351. }
  352. break;
  353. case WM_LBUTTONDOWN:
  354. pt = MAKEMPOINT(lParam);
  355. for (row = 0; row < 2; ++row)
  356. for (column = 0; column < 6; ++column)
  357. {
  358. MPOINT2POINT(pt, mpt);
  359. if (!layout[row][column] ||
  360. !PtInRect(&layoutRect[row][column], mpt))
  361. continue;
  362. fTracking = TRUE;
  363. startRow = row;
  364. startColumn = column;
  365. trackRect = layoutRect[row][column];
  366. hDCTrack = GetDC(hWnd);
  367. hOldBrush = SelectObject(hDCTrack,
  368. GetStockObject(NULL_BRUSH));
  369. hOldPen = SelectObject(hDCTrack,
  370. GetStockObject(WHITE_PEN));
  371. SetROP2(hDCTrack, R2_XORPEN);
  372. Rectangle(hDCTrack, trackRect.left, trackRect.top,
  373. trackRect.right, trackRect.bottom);
  374. ptOldPos = pt;
  375. SetCapture(hWnd);
  376. goto foundSource;
  377. }
  378. foundSource:
  379. break;
  380. case WM_MOUSEMOVE:
  381. pt = MAKEMPOINT(lParam);
  382. if (fTracking && !(wParam & MK_LBUTTON))
  383. PostMessage(hWnd, WM_LBUTTONUP, wParam, lParam);
  384. else if (!fTracking ||
  385. ((pt.x == ptOldPos.x) && (pt.y == ptOldPos.y)))
  386. break;
  387. Rectangle(hDCTrack, trackRect.left, trackRect.top,
  388. trackRect.right, trackRect.bottom);
  389. OffsetRect(&trackRect, pt.x - ptOldPos.x,
  390. pt.y - ptOldPos.y);
  391. ptOldPos = pt;
  392. Rectangle(hDCTrack, trackRect.left, trackRect.top,
  393. trackRect.right, trackRect.bottom);
  394. break;
  395. case WM_LBUTTONUP:
  396. if (!fTracking)
  397. break;
  398. ReleaseCapture();
  399. endRow = endColumn = INVALID_POS;
  400. maxArea = 0;
  401. for (row = 0; row < 2; ++row)
  402. for (column = 0; column < 6; ++column)
  403. {
  404. if (!layout[row][column] ||
  405. !IntersectRect(&tmpRect, &trackRect,
  406. &layoutRect[row][column]))
  407. continue;
  408. Area = abs((tmpRect.right - tmpRect.left)
  409. * (tmpRect.bottom - tmpRect.top));
  410. if (Area > maxArea) {
  411. endRow = row;
  412. endColumn = column;
  413. maxArea = Area;
  414. }
  415. }
  416. if (maxArea)
  417. goto foundTarget;
  418. endRow = -1;
  419. for (column = 0; column < 4; ++column)
  420. if (IntersectRect(&tmpRect, &trackRect, &foundationRect[column]))
  421. {
  422. Area = abs((tmpRect.right - tmpRect.left)
  423. * (tmpRect.bottom - tmpRect.top));
  424. if (Area > maxArea) {
  425. endColumn = column;
  426. maxArea = Area;
  427. }
  428. }
  429. foundTarget:
  430. fTracking = FALSE;
  431. Rectangle(hDCTrack, trackRect.left, trackRect.top,
  432. trackRect.right, trackRect.bottom);
  433. if (startRow != endRow || startColumn != endColumn) {
  434. if ((endRow != INVALID_POS) && (endColumn != INVALID_POS))
  435. MoveCard(hDCTrack, startRow, startColumn, endRow, endColumn, FALSE);
  436. startRow = startColumn = endRow = endColumn = INVALID_POS;
  437. }
  438. SelectObject(hDCTrack, hOldBrush);
  439. SelectObject(hDCTrack, hOldPen);
  440. ReleaseDC(hWnd, hDCTrack);
  441. break;
  442. case WM_INITMENU:
  443. hMenu = GetMenu(hWnd);
  444. EnableMenuItem(hMenu, IDM_OPTIONSUNDO, MF_BYCOMMAND |
  445. undoPos ? MF_ENABLED : MF_GRAYED);
  446. CheckMenuItem(hMenu, IDM_OPTIONSERROR,
  447. wErrorMessages ? MF_CHECKED : MF_UNCHECKED);
  448. break;
  449. case WM_COMMAND:
  450. switch(GET_WM_COMMAND_ID(wParam, lParam))
  451. {
  452. case IDM_NEWGAME:
  453. Deal();
  454. fBoard = FALSE;
  455. InvalidateRect(hWnd, NULL, TRUE);
  456. CheckGameOver();
  457. break;
  458. case IDM_EXIT:
  459. DestroyWindow(hWnd);
  460. break;
  461. case IDM_OPTIONSDECK:
  462. DoBacks();
  463. break;
  464. case IDM_ABOUT:
  465. hLib = MLoadLibrary("shell32.dll");
  466. if (hLib < (HANDLE)32)
  467. break;
  468. lpAbout = GetProcAddress(hLib, (LPSTR)"ShellAboutA");
  469. if (lpAbout) {
  470. (*lpAbout)(hWnd,
  471. (LPSTR) szAppName, (LPSTR)"by Ken Sykes",
  472. LoadIcon(hMyInstance, szAppName));
  473. }
  474. FreeLibrary(hLib);
  475. break;
  476. case MENU_INDEX:
  477. Help(hWnd, HELP_INDEX, 0L);
  478. break;
  479. case MENU_HOWTOPLAY:
  480. Help(hWnd, HELP_CONTEXT, 1L);
  481. break;
  482. case MENU_COMMANDS:
  483. Help(hWnd, HELP_CONTEXT, 2L);
  484. break;
  485. case MENU_USINGHELP:
  486. Help(hWnd, HELP_HELPONHELP, 0L);
  487. break;
  488. case IDM_OPTIONSERROR:
  489. wErrorMessages = (WORD) ~wErrorMessages;
  490. break;
  491. case IDM_OPTIONSUNDO:
  492. hDC = GetDC(hWnd);
  493. UndoMove(hDC);
  494. ReleaseDC(hWnd, hDC);
  495. break;
  496. case IDM_GAMERECORD:
  497. DisplayStats();
  498. break;
  499. case IDM_DOMINIMIZE:
  500. ShowWindow(hWnd, SW_MINIMIZE);
  501. break;
  502. case NEXT_ROUND:
  503. if (!bGameInProgress)
  504. break;
  505. if (!undoPos) {
  506. if (wErrorMessages)
  507. Message(hWnd, IDSNoCardsMoved, MB_OK);
  508. break;
  509. }
  510. UnionRect(&tmpRect, &layoutRect[0][0],
  511. &layoutRect[1][5]);
  512. hDC = GetDC(hWnd);
  513. FillRect(hDC, &tmpRect, hBrush);
  514. RestoreLayout(hDC);
  515. DrawLayout(hDC);
  516. ReleaseDC(hWnd, hDC);
  517. undoPos = 0;
  518. CheckGameOver();
  519. break;
  520. }
  521. break;
  522. case WM_DESTROY:
  523. KillTimer(hWnd, 666);
  524. cdtTerm();
  525. Help(hWnd, HELP_QUIT, 0L);
  526. DeleteObject(hBrush);
  527. SaveState();
  528. PostQuitMessage (0) ;
  529. break ;
  530. default:
  531. return DefWindowProc (hWnd, iMessage, wParam, lParam) ;
  532. }
  533. return 0L ;
  534. }
  535. VOID Deal(VOID)
  536. {
  537. INT i, p1, p2;
  538. INT row, column;
  539. CardRec tmp, *pDeck;
  540. cardSuit suit;
  541. cardRank rank;
  542. /* stuff cards into deck */
  543. pDeck = deck;
  544. for (i = 4; i < 52; ++i)
  545. (pDeck++)->card = i;
  546. /* shuffle them around */
  547. srand(LOWORD(GetTickCount()));
  548. for (p2 = 0; p2 < 7; ++p2) {
  549. for (i = 47; i > 0; --i) {
  550. p1 = rand() % i;
  551. tmp = deck[p1];
  552. deck[p1] = deck[i];
  553. deck[i] = tmp;
  554. }
  555. }
  556. /* establish layout links */
  557. pDeck = deck;
  558. for (row = 0; row < 2; ++row)
  559. for (column = 0; column < 6; ++column)
  560. {
  561. layout[row][column] = pDeck;
  562. for (i = 0; i < 3; ++i, ++pDeck)
  563. pDeck->next = pDeck + 1;
  564. (pDeck++)->next = NULL;
  565. }
  566. /* put aces in foundation */
  567. for (i = 0; i < 4; ++i)
  568. foundation[i] = i;
  569. #if 0
  570. {
  571. INT i,j, *p;
  572. for (i = 0; i < 2; ++i)
  573. for (j = 0; j < 6; ++j)
  574. layout[i][j]->card = init[i][j];
  575. p = (INT *) &init[0][0];
  576. j = *p;
  577. for (i = 1; i < 12; ++i)
  578. p[i-1] = p[i];
  579. p[11] = j;
  580. }
  581. #endif
  582. bGameInProgress = TRUE;
  583. }
  584. VOID InitBoard(VOID)
  585. {
  586. INT xPos, yPos;
  587. INT row, column, i;
  588. RECT *pRect;
  589. /* compute x and y increments */
  590. xInc = (xClient - 40) / 6;
  591. yInc = (yClient - 20) / 3;
  592. /* compute foundation rectangles */
  593. yPos = 10;
  594. pRect = foundationRect;
  595. for (xPos = 20 + xInc, i = 0; i < 4; ++i, xPos += xInc, ++pRect)
  596. {
  597. pRect->left = xPos;
  598. pRect->top = yPos;
  599. pRect->right = xPos + xCard;
  600. pRect->bottom = yPos + yCard;
  601. }
  602. /* compute layout rectangles */
  603. pRect = &layoutRect[0][0];
  604. for (row = 0, yPos = 10 + yInc; row < 2; ++row, yPos += yInc)
  605. for (column = 0, xPos = 20; column < 6; ++column, xPos += xInc)
  606. {
  607. pRect->left = xPos;
  608. pRect->top = yPos;
  609. pRect->right = xPos + xCard;
  610. (pRect++)->bottom = yPos + yCard;
  611. }
  612. undoPos = 0;
  613. freePos = 0;
  614. }
  615. VOID DrawLayout(HDC hDC)
  616. {
  617. INT row, column;
  618. for (row = 0; row < 2; ++row)
  619. for (column = 0; column < 6; ++column)
  620. {
  621. if (!layout[row][column])
  622. continue;
  623. cdtDraw(hDC, layoutRect[row][column].left,
  624. layoutRect[row][column].top,
  625. layout[row][column]->card,
  626. faceup, dwBkgnd);
  627. }
  628. }
  629. VOID DrawFoundation(HDC hDC)
  630. {
  631. INT i;
  632. for (i = 0; i < 4; ++i)
  633. cdtDraw(hDC, foundationRect[i].left, foundationRect[i].top,
  634. foundation[i],
  635. (foundation[i] == wDeckBack) ? facedown : faceup, dwBkgnd);
  636. }
  637. BOOL MoveCard(HDC hDC, INT startRow, INT startColumn,
  638. INT endRow, INT endColumn,
  639. BOOL bValidate)
  640. {
  641. CardRec *pStart = layout[startRow][startColumn];
  642. CardRec *pEnd = layout[endRow][endColumn];
  643. INT startCard = pStart->card;
  644. INT endCard;
  645. cardMode drawmode;
  646. BOOL bDone;
  647. if (pEnd == (CardRec*)NULL) /* on NT, this causes exception */
  648. endCard = (endRow < 0) ? foundation[endColumn] : 0;
  649. else
  650. endCard = (endRow < 0) ? foundation[endColumn] : pEnd->card;
  651. /* make sure suits match */
  652. if (CardSuit(startCard) != CardSuit(endCard))
  653. {
  654. if (!bValidate && wErrorMessages)
  655. Message(hWnd, IDSWrongSuit, MB_OK);
  656. return FALSE;
  657. }
  658. /* take action based on where card is moved ... */
  659. if (endRow < 0)
  660. { /* card to foundation */
  661. /* card must be one higher than top of foundation */
  662. if (IndexValue(startCard, ACELOW) != IndexValue(endCard, ACELOW) + 1)
  663. {
  664. if (!bValidate && wErrorMessages)
  665. Message(hWnd, IDSNotNextCard, MB_OK);
  666. return FALSE;
  667. }
  668. if (bValidate)
  669. return TRUE;
  670. /* move card to foundation and draw it */
  671. if (CardRank(startCard) == king) {
  672. startCard = wDeckBack;
  673. drawmode = facedown;
  674. } else
  675. drawmode = faceup;
  676. foundation[endColumn] = startCard;
  677. cdtDraw(hDC, foundationRect[endColumn].left,
  678. foundationRect[endColumn].top,
  679. startCard, drawmode, dwBkgnd);
  680. layout[startRow][startColumn] = pStart->next;
  681. FreeList[freePos++] = pStart;
  682. }
  683. else
  684. { /* card to another pile */
  685. /* card must be one lower in rank */
  686. if (IndexValue(startCard, ACELOW) != IndexValue(endCard, ACELOW) - 1)
  687. {
  688. if (!bValidate && wErrorMessages)
  689. Message(hWnd, IDSWrongRank, MB_OK);
  690. return FALSE;
  691. }
  692. if (bValidate)
  693. return TRUE;
  694. /* move card to new pile and display it */
  695. layout[endRow][endColumn] = pStart;
  696. layout[startRow][startColumn] = pStart->next;
  697. pStart->next = pEnd;
  698. cdtDraw(hDC, layoutRect[endRow][endColumn].left,
  699. layoutRect[endRow][endColumn].top,
  700. startCard, faceup, dwBkgnd);
  701. }
  702. /* erase old card and expose new card */
  703. if (layout[startRow][startColumn])
  704. cdtDraw(hDC, layoutRect[startRow][startColumn].left,
  705. layoutRect[startRow][startColumn].top,
  706. layout[startRow][startColumn]->card, faceup, dwBkgnd);
  707. else
  708. cdtDraw(hDC, layoutRect[startRow][startColumn].left,
  709. layoutRect[startRow][startColumn].top,
  710. 0, remove, dwBkgnd);
  711. if (undoPos == MAXUNDOSIZE) {
  712. Message(hWnd, IDSUndoFull, MB_OK);
  713. undoPos = 0;
  714. }
  715. undo[undoPos].startRow = startRow;
  716. undo[undoPos].endRow = endRow;
  717. undo[undoPos].startColumn = startColumn;
  718. undo[undoPos].endColumn = endColumn;
  719. ++undoPos;
  720. bDone = TRUE;
  721. for (startCard = 0; startCard < 4; ++startCard)
  722. if (foundation[startCard] != wDeckBack) {
  723. bDone = FALSE;
  724. break;
  725. }
  726. if (bDone)
  727. CheckGameOver();
  728. return TRUE;
  729. }
  730. VOID RestoreLayout(HDC hDC)
  731. {
  732. INT i, j;
  733. CardRec *pCurPos, *pList;
  734. /* stage 1: Chain cards together ... */
  735. /* find last non-empty stack */
  736. for (i = 0; i < 12; ++i)
  737. if (layout[i / 6][i % 6])
  738. break;
  739. /* start the list here */
  740. pList = pCurPos = layout[i / 6][i % 6];
  741. /* work towards last stack */
  742. for (; i < 11; ++i)
  743. {
  744. while (pCurPos->next)
  745. pCurPos = pCurPos->next;
  746. pCurPos->next = layout[(i+1) / 6][(i+1) % 6];
  747. }
  748. /* stage 2: deal them back to layout again ... */
  749. for (i = 0; i < 12; ++i)
  750. {
  751. layout[i / 6][i % 6] = pList;
  752. for (j = 0; j < 3; ++j)
  753. if (pList && pList->next)
  754. pList = pList->next;
  755. else
  756. break;
  757. if (j != 3)
  758. break;
  759. else
  760. {
  761. pCurPos = pList->next;
  762. pList->next = NULL;
  763. pList = pCurPos;
  764. }
  765. }
  766. /* rest of stacks are empty */
  767. for (++i; i < 12; ++i)
  768. layout[i / 6][i % 6] = NULL;
  769. }
  770. VOID UndoMove(HDC hDC)
  771. {
  772. CHAR buffer[10];
  773. RECT *pRect, rect;
  774. INT column, card;
  775. HBRUSH hBrush;
  776. CardRec *pCard;
  777. INT endRow, endColumn, startRow, startColumn;
  778. --undoPos;
  779. endRow = undo[undoPos].endRow;
  780. startRow = undo[undoPos].startRow;
  781. endColumn = undo[undoPos].endColumn;
  782. startColumn = undo[undoPos].startColumn;
  783. if (endRow < 0) {
  784. /* move card from foundation back to pile */
  785. if (!freePos) {
  786. Message(hWnd, IDSIntFreePos, MB_OK | MB_ICONHAND);
  787. return;
  788. }
  789. pCard = FreeList[--freePos];
  790. /* move card to pile */
  791. if (foundation[endColumn] == wDeckBack)
  792. foundation[endColumn] = 48 + endColumn;
  793. // foundation[endColumn] = CardIndex(endColumn, king);
  794. pCard->card = card = foundation[endColumn];
  795. pCard->next = layout[startRow][startColumn];
  796. layout[startRow][startColumn] = pCard;
  797. /* decrement card on foundation */
  798. foundation[endColumn] -= 4;
  799. // foundation[endColumn] = CardIndex(CardSuit(card), CardRank(card)-1);
  800. /* update the foundation */
  801. cdtDraw(hDC, foundationRect[endColumn].left,
  802. foundationRect[endColumn].top,
  803. foundation[endColumn], faceup, dwBkgnd);
  804. /* update the pile */
  805. cdtDraw(hDC, layoutRect[startRow][startColumn].left,
  806. layoutRect[startRow][startColumn].top,
  807. pCard->card, faceup, dwBkgnd);
  808. } else {
  809. /* move card from one pile to the other */
  810. pCard = layout[endRow][endColumn];
  811. layout[endRow][endColumn] = pCard->next;
  812. pCard->next = layout[startRow][startColumn];
  813. layout[startRow][startColumn] = pCard;
  814. /* update pile we moved card back to (start) */
  815. cdtDraw(hDC, layoutRect[startRow][startColumn].left,
  816. layoutRect[startRow][startColumn].top,
  817. pCard->card, faceup, dwBkgnd);
  818. /* update pile we moved card back from (end), which could be empty
  819. ** now.
  820. */
  821. if (layout[endRow][endColumn])
  822. cdtDraw(hDC, layoutRect[endRow][endColumn].left,
  823. layoutRect[endRow][endColumn].top,
  824. layout[endRow][endColumn]->card, faceup, dwBkgnd);
  825. else
  826. cdtDraw(hDC, layoutRect[endRow][endColumn].left,
  827. layoutRect[endRow][endColumn].top,
  828. 0, remove, dwBkgnd);
  829. }
  830. }
  831. INT Message(HWND hWnd, WORD wId, WORD wFlags)
  832. {
  833. static CHAR szBuf[256];
  834. if (!LoadString(hMyInstance, wId, szBuf, 256) ||
  835. wId == IDSOOM) {
  836. lstrcpy(szBuf, szOOM);
  837. wFlags = MB_ICONHAND | MB_SYSTEMMODAL;
  838. }
  839. if (!(wFlags & MB_SYSTEMMODAL))
  840. wFlags |= MB_TASKMODAL;
  841. if (!(wFlags & (MB_ICONHAND | MB_ICONEXCLAMATION | MB_ICONINFORMATION)))
  842. wFlags |= MB_ICONEXCLAMATION;
  843. return MessageBox(hWnd, szBuf, szAppName, wFlags);
  844. }
  845. VOID DoBacks()
  846. {
  847. DialogBox(hMyInstance, MAKEINTRESOURCE(1), hWnd, BackDlgProc);
  848. }
  849. INT_PTR CALLBACK BackDlgProc(HWND hdlg, UINT wm, WPARAM wParam, LPARAM lParam)
  850. {
  851. WORD cmd;
  852. static INT modeNew;
  853. INT iback;
  854. MEASUREITEMSTRUCT FAR *lpmi;
  855. DRAWITEMSTRUCT FAR *lpdi;
  856. HBRUSH hbr;
  857. RC rc, rcCrd;
  858. HDC hdc;
  859. INT i;
  860. switch(wm)
  861. {
  862. case WM_INITDIALOG:
  863. modeNew = wDeckBack;
  864. SetFocus(GetDlgItem(hdlg, modeNew));
  865. return FALSE;
  866. case WM_COMMAND:
  867. cmd = GET_WM_COMMAND_ID(wParam, lParam);
  868. if(cmd >= IDFACEDOWNFIRST && cmd <= IDFACEDOWN12) {
  869. modeNew = cmd;
  870. if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_DOUBLECLICKED) {
  871. ChangeBack((WORD)modeNew);
  872. EndDialog(hdlg, 0);
  873. }
  874. } else
  875. switch(cmd)
  876. {
  877. case IDOK:
  878. ChangeBack((WORD)modeNew);
  879. /* fall thru */
  880. case IDCANCEL:
  881. EndDialog(hdlg, 0);
  882. break;
  883. }
  884. break;
  885. case WM_MEASUREITEM:
  886. lpmi = (MEASUREITEMSTRUCT FAR *)lParam;
  887. lpmi->CtlType = ODT_BUTTON;
  888. lpmi->itemWidth = xCard /* 32 */;
  889. lpmi->itemHeight = yCard /* 54 */;
  890. break;
  891. case WM_DRAWITEM:
  892. lpdi = (DRAWITEMSTRUCT FAR *)lParam;
  893. CopyRect((LPRECT) &rc, &lpdi->rcItem);
  894. rcCrd = rc;
  895. InflateRect((LPRECT) &rcCrd, -3, -3);
  896. hdc = lpdi->hDC;
  897. if (lpdi->itemAction == ODA_DRAWENTIRE)
  898. {
  899. cdtDrawExt(hdc, rcCrd.xLeft, rcCrd.yTop,
  900. rcCrd.xRight-rcCrd.xLeft, rcCrd.yBot-rcCrd.yTop,
  901. lpdi->CtlID, FACEDOWN, 0L);
  902. FDrawFocus(hdc, &rc, lpdi->itemState & ODS_FOCUS);
  903. break;
  904. }
  905. if (lpdi->itemAction == ODA_SELECT)
  906. InvertRect(hdc, (LPRECT)&rcCrd);
  907. if (lpdi->itemAction == ODA_FOCUS)
  908. FDrawFocus(hdc, &rc, lpdi->itemState & ODS_FOCUS);
  909. break;
  910. default:
  911. return FALSE;
  912. }
  913. return TRUE;
  914. }
  915. BOOL FDrawFocus(HDC hdc, RC *prc, BOOL fFocus)
  916. {
  917. HBRUSH hbr;
  918. RC rc;
  919. hbr = CreateSolidBrush(GetSysColor(fFocus ? COLOR_HIGHLIGHT : COLOR_WINDOW));
  920. if(hbr == NULL)
  921. return FALSE;
  922. rc = *prc;
  923. FrameRect(hdc, (LPRECT) &rc, hbr);
  924. InflateRect((LPRECT) &rc, -1, -1);
  925. FrameRect(hdc, (LPRECT) &rc, hbr);
  926. DeleteObject(hbr);
  927. return TRUE;
  928. }
  929. VOID ChangeBack(WORD wNewDeckBack)
  930. {
  931. HDC hDC;
  932. INT i;
  933. hDC = GetDC(hWnd);
  934. for (i = 0; i < 4; ++i) {
  935. if (foundation[i] == wDeckBack) {
  936. if (hDC)
  937. cdtDraw(hDC, foundationRect[i].left, foundationRect[i].top, wNewDeckBack, facedown, dwBkgnd);
  938. foundation[i] = wNewDeckBack;
  939. }
  940. }
  941. if (hDC)
  942. ReleaseDC(hWnd, hDC);
  943. wDeckBack = wNewDeckBack;
  944. return;
  945. }
  946. VOID DrawAnimate(INT cd, MPOINT *ppt, INT iani)
  947. {
  948. HDC hDC;
  949. INT i;
  950. if(!(hDC = GetDC(hWnd)))
  951. return;
  952. for (i = 0; i < 4; ++i)
  953. if (foundation[i] == wDeckBack)
  954. cdtAnimate(hDC, cd, foundationRect[i].left, foundationRect[i].top, iani);
  955. ReleaseDC(hWnd, hDC);
  956. }
  957. BOOL DeckAnimate(INT iqsec)
  958. {
  959. INT iani;
  960. MPOINT pt;
  961. pt.x = pt.y = 0; /* not used! */
  962. switch(wDeckBack) {
  963. case IDFACEDOWN3:
  964. DrawAnimate(IDFACEDOWN3, &pt, iqsec % 4);
  965. break;
  966. case IDFACEDOWN10: // krazy kastle
  967. DrawAnimate(IDFACEDOWN10, &pt, iqsec % 2);
  968. break;
  969. case IDFACEDOWN11: // sanflipe
  970. if((iani = (iqsec+4) % (50*4)) < 4)
  971. DrawAnimate(IDFACEDOWN11, &pt, iani);
  972. else
  973. // if a menu overlapps an ani while it is ani'ing, leaves deck
  974. // bitmap in inconsistent state...
  975. if(iani % 6 == 0)
  976. DrawAnimate(IDFACEDOWN11, &pt, 3);
  977. break;
  978. case IDFACEDOWN12: // SLIME
  979. if((iani = (iqsec+4) % (15*4)) < 4)
  980. DrawAnimate(IDFACEDOWN12, &pt, iani);
  981. else
  982. // if a menu overlapps an ani while it is ani'ing, leaves deck
  983. // bitmap in inconsistent state...
  984. if(iani % 6 == 0)
  985. DrawAnimate(IDFACEDOWN12, &pt, 3);
  986. break;
  987. }
  988. return TRUE;
  989. }
  990. VOID APIENTRY TimerProc(HWND hwnd, UINT wm, UINT_PTR id, DWORD dwTime)
  991. {
  992. static INT x = 0;
  993. if (bGameInProgress)
  994. DeckAnimate(x++);
  995. return;
  996. }
  997. VOID SaveState(VOID)
  998. {
  999. CHAR sz[80];
  1000. wsprintf(sz, "%ld %ld %ld %ld %ld", nStats[0], nStats[1],
  1001. nStats[2], nStats[3], nStats[4]);
  1002. WritePrivateProfileString(szAppName, "Stats", sz, ININAME);
  1003. wsprintf(sz, "%d %d", wErrorMessages, wDeckBack);
  1004. WritePrivateProfileString(szAppName, "MenuState", sz, ININAME);
  1005. }
  1006. VOID DisplayStats(VOID)
  1007. {
  1008. CHAR sz[80];
  1009. fDialog(2, hWnd, RecordDlgProc);
  1010. }
  1011. VOID RestoreState(VOID)
  1012. {
  1013. CHAR sz[80], *psz;
  1014. INT col;
  1015. DWORD cchRead;
  1016. cchRead = GetPrivateProfileString(szAppName, "Stats", "0 52 0 0 0", sz,
  1017. sizeof(sz), ININAME);
  1018. psz = (cchRead > 0) ? lstrtok(sz, " ") : NULL;
  1019. col = 0;
  1020. if (psz) {
  1021. nStats[0] = atol(psz);
  1022. for (col = 1; col < 5 && psz; ++col)
  1023. nStats[col] = atol(psz = lstrtok(NULL, " "));
  1024. }
  1025. for (; col < 5; ++col)
  1026. nStats[col] = 0;
  1027. cchRead = GetPrivateProfileString(szAppName, "MenuState", "0 65 4", sz,
  1028. sizeof(sz), ININAME);
  1029. psz = (cchRead > 0) ? lstrtok(sz, " ") : NULL;
  1030. if (psz) {
  1031. wErrorMessages = (WORD) atoi(psz);
  1032. psz = lstrtok(NULL, " ");
  1033. wDeckBack = IDCARDBACK;
  1034. if (psz)
  1035. wDeckBack = (WORD) atoi(psz);
  1036. } else {
  1037. wErrorMessages = 0;
  1038. wDeckBack = IDCARDBACK;
  1039. }
  1040. }
  1041. static BOOL IsInString(CHAR c, LPSTR s)
  1042. {
  1043. while (*s && *s != c)
  1044. s = AnsiNext(s);
  1045. return *s;
  1046. }
  1047. /* write our own strtok to avoid pulling in entire string library ... */
  1048. LPSTR lstrtok(LPSTR lpStr, LPSTR lpDelim)
  1049. {
  1050. static LPSTR lpString;
  1051. LPSTR lpRetVal, lpTemp;
  1052. /* if we are passed new string skip leading delimiters */
  1053. if(lpStr) {
  1054. lpString = lpStr;
  1055. while (*lpString && IsInString(*lpString, lpDelim))
  1056. lpString = AnsiNext(lpString);
  1057. }
  1058. /* if there are no more tokens return NULL */
  1059. if(!*lpString)
  1060. return NULL;
  1061. /* save head of token */
  1062. lpRetVal = lpString;
  1063. /* find delimiter or end of string */
  1064. while(*lpString && !IsInString(*lpString, lpDelim))
  1065. lpString = AnsiNext(lpString);
  1066. /* if we found a delimiter insert string terminator and skip */
  1067. if(*lpString) {
  1068. lpTemp = AnsiNext(lpString);
  1069. *lpString = '\0';
  1070. lpString = lpTemp;
  1071. }
  1072. /* return token */
  1073. return(lpRetVal);
  1074. }
  1075. /*----------------------------------------------------------------------------*\
  1076. | fDialog(id,hwnd,fpfn) |
  1077. | |
  1078. | Description: |
  1079. | This function displays a dialog box and returns the exit code. |
  1080. | the function passed will have a proc instance made for it. |
  1081. | |
  1082. | Arguments: |
  1083. | id resource id of dialog to display |
  1084. | hwnd parent window of dialog |
  1085. | fpfn dialog message function |
  1086. | |
  1087. | Returns: |
  1088. | exit code of dialog (what was passed to EndDialog) |
  1089. | |
  1090. \*----------------------------------------------------------------------------*/
  1091. BOOL fDialog(INT id,HWND hwnd,DLGPROC fpfn)
  1092. {
  1093. BOOL f;
  1094. HANDLE hInst;
  1095. hInst = (HANDLE)GetWindowLongPtr(hwnd,GWLP_HINSTANCE);
  1096. fpfn = MakeProcInstance(fpfn,hInst);
  1097. f = (BOOL) DialogBox(hInst,MAKEINTRESOURCE(id),hwnd,fpfn);
  1098. FreeProcInstance ((FARPROC)fpfn);
  1099. return f;
  1100. }
  1101. INT_PTR APIENTRY RecordDlgProc(HANDLE hdlg, UINT wm, WPARAM wParam, LPARAM lParam)
  1102. {
  1103. CHAR sz[80];
  1104. HWND hwndEdit;
  1105. INT i;
  1106. switch(wm) {
  1107. case WM_INITDIALOG:
  1108. hwndEdit = GetDlgItem(hdlg, IDD_RECORD);
  1109. SendMessage(hwndEdit, LB_ADDSTRING, 0, (LPARAM) (szRecordTitle));
  1110. wsprintf(sz, "%ld\t%ld\t%ld\t%ld\t%ld", nStats[TOTAL], nStats[WINS],
  1111. nStats[HI], nStats[LOW], nStats[TOTAL] ? (nStats[SUM] / nStats[TOTAL]) : 0);
  1112. SendMessage(hwndEdit, LB_ADDSTRING, 0, (LPARAM) (sz));
  1113. MarkControlReadOnly(hwndEdit, TRUE);
  1114. return TRUE;
  1115. case WM_COMMAND:
  1116. switch(GET_WM_COMMAND_ID(wParam, lParam)) {
  1117. case IDOK:
  1118. /* fall thru */
  1119. case IDCANCEL:
  1120. hwndEdit = GetDlgItem(hdlg, IDD_RECORD);
  1121. MarkControlReadOnly(hwndEdit, FALSE);
  1122. EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
  1123. break;
  1124. case IDD_CLEARSCORES:
  1125. for (i = 0; i < 5; ++i)
  1126. nStats[i] = 0;
  1127. nStats[LOW] = 52;
  1128. lstrcpy(sz, "0\t0\t0\t52\t0");
  1129. hwndEdit = GetDlgItem(hdlg, IDD_RECORD);
  1130. SendMessage(hwndEdit, LB_DELETESTRING, 1, 0L);
  1131. SendMessage(hwndEdit, LB_ADDSTRING, 0, (LPARAM) (sz));
  1132. break;
  1133. }
  1134. break;
  1135. }
  1136. return FALSE;
  1137. }
  1138. static WNDPROC lpOldWP;
  1139. VOID MarkControlReadOnly(HWND hwndCtrl, BOOL bReadOnly)
  1140. {
  1141. if (bReadOnly)
  1142. lpOldWP = (WNDPROC) SetWindowLongPtr(hwndCtrl, GWLP_WNDPROC,
  1143. (LONG_PTR) ReadOnlyProc);
  1144. else
  1145. SetWindowLongPtr(hwndCtrl, GWLP_WNDPROC, (LONG_PTR) lpOldWP);
  1146. }
  1147. LRESULT APIENTRY ReadOnlyProc(HWND hwnd, UINT wMessage, WPARAM wParam, LPARAM lParam)
  1148. {
  1149. switch (wMessage) {
  1150. case WM_LBUTTONDOWN:
  1151. case WM_RBUTTONDOWN:
  1152. case WM_LBUTTONDBLCLK:
  1153. case WM_RBUTTONDBLCLK:
  1154. return 0L;
  1155. }
  1156. return CallWindowProc(lpOldWP, hwnd, wMessage, wParam, lParam);
  1157. }
  1158. #if 0
  1159. VOID ShowStacks(VOID)
  1160. {
  1161. CHAR szBuf[80];
  1162. wsprintf(szBuf,
  1163. "%02d %02d %02d %02d %02d %02d\n%02d %02d %02d %02d %02d %02d",
  1164. layout[0][0] ? layout[0][0]->card : -1,
  1165. layout[0][1] ? layout[0][1]->card : -1,
  1166. layout[0][2] ? layout[0][2]->card : -1,
  1167. layout[0][3] ? layout[0][3]->card : -1,
  1168. layout[0][4] ? layout[0][4]->card : -1,
  1169. layout[0][5] ? layout[0][5]->card : -1,
  1170. layout[1][0] ? layout[1][0]->card : -1,
  1171. layout[1][1] ? layout[1][1]->card : -1,
  1172. layout[1][2] ? layout[1][2]->card : -1,
  1173. layout[1][3] ? layout[1][3]->card : -1,
  1174. layout[1][4] ? layout[1][4]->card : -1,
  1175. layout[1][5] ? layout[1][5]->card : -1);
  1176. MessageBox(hWnd, szBuf, "Card Stacks", MB_OK);
  1177. wsprintf(szBuf,
  1178. "%02d %02d %02d %02d %02d %02d\n%02d %02d %02d %02d %02d %02d",
  1179. layout[0][0] ? IndexValue(layout[0][0]->card, ACELOW) : -1,
  1180. layout[0][1] ? IndexValue(layout[0][1]->card, ACELOW) : -1,
  1181. layout[0][2] ? IndexValue(layout[0][2]->card, ACELOW) : -1,
  1182. layout[0][3] ? IndexValue(layout[0][3]->card, ACELOW) : -1,
  1183. layout[0][4] ? IndexValue(layout[0][4]->card, ACELOW) : -1,
  1184. layout[0][5] ? IndexValue(layout[0][5]->card, ACELOW) : -1,
  1185. layout[1][0] ? IndexValue(layout[1][0]->card, ACELOW) : -1,
  1186. layout[1][1] ? IndexValue(layout[1][1]->card, ACELOW) : -1,
  1187. layout[1][2] ? IndexValue(layout[1][2]->card, ACELOW) : -1,
  1188. layout[1][3] ? IndexValue(layout[1][3]->card, ACELOW) : -1,
  1189. layout[1][4] ? IndexValue(layout[1][4]->card, ACELOW) : -1,
  1190. layout[1][5] ? IndexValue(layout[1][5]->card, ACELOW) : -1);
  1191. MessageBox(hWnd, szBuf, "IndexValue", MB_OK);
  1192. }
  1193. #endif