home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 7 Games / 07-Games.zip / life1.zip / LIFE.C next >
C/C++ Source or Header  |  1989-10-13  |  8KB  |  352 lines

  1. #define INCL_WIN
  2. #define INCL_GPI
  3. #include <os2.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include "life.h"
  7.  
  8. #define ID_TIMER 1
  9.  
  10. MRESULT EXPENTRY ClientWndProc (HWND, USHORT, MPARAM, MPARAM);
  11.  
  12. CHAR szClientClass [] = "Life";
  13.  
  14. HAB hab;
  15.  
  16. int main(void)
  17. {
  18.     static ULONG flFrameFlags = FCF_TITLEBAR |
  19.             FCF_SYSMENU | FCF_SIZEBORDER |
  20.             FCF_MINMAX | FCF_SHELLPOSITION|
  21.             FCF_MENU | FCF_ICON;
  22.  
  23.     HMQ hmq;
  24.     HWND hwndFrame, hwndClient;
  25.     QMSG qmsg;
  26.  
  27. hab = WinInitialize(0);
  28. hmq = WinCreateMsgQueue (hab, 0);
  29.  
  30. WinRegisterClass (hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0);
  31.  
  32. hwndFrame = WinCreateStdWindow(HWND_DESKTOP, WS_VISIBLE, &flFrameFlags, szClientClass, NULL, 0L, NULL, ID_RESOURCE, &hwndClient);
  33.  
  34. while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
  35.     WinDispatchMsg(hab, &qmsg);
  36.  
  37. WinDestroyWindow (hwndFrame);
  38. WinDestroyMsgQueue (hmq);
  39. WinTerminate (hab);
  40. return 0;
  41. }
  42.  
  43. VOID EnableMenuItem (HWND hwndMenu, SHORT idMenuItem, BOOL fEnable)
  44. {
  45. WinSendMsg (hwndMenu, MM_SETITEMATTR, MPFROM2SHORT (idMenuItem, TRUE), MPFROM2SHORT (MIA_DISABLED, fEnable ? 0 : MIA_DISABLED));
  46. }
  47.  
  48. VOID ErrorMsg (HWND hwnd, CHAR *szMessage)
  49. {
  50. WinMessageBox (HWND_DESKTOP, hwnd, szMessage, szClientClass, 0, MB_OK | MB_ICONEXCLAMATION);
  51. }
  52.  
  53. VOID DrawCell (HPS hps, SHORT x, SHORT y, SHORT cxCell, SHORT cyCell, BYTE bCell)
  54. {
  55. RECTL rcl;
  56.  
  57. rcl.xLeft = x * cxCell;
  58. rcl.yBottom = y * cyCell;
  59. rcl.xRight = rcl.xLeft + cxCell - 1;
  60. rcl.yTop = rcl.yBottom + cyCell - 1;
  61.  
  62. WinFillRect (hps, &rcl, bCell & 1 ? CLR_NEUTRAL : CLR_BACKGROUND);
  63. }
  64.  
  65. VOID DoGeneration (HPS hps, PBYTE pbGrid, SHORT xNumCells, SHORT yNumCells, SHORT cxCell, SHORT cyCell)
  66. {
  67. SHORT x, y, sSum;
  68.  
  69. for (y = 0; y< yNumCells - 1; y++)
  70.     for (x = 0; x < xNumCells; x++)
  71.     {
  72.     if (x == 0 || x == xNumCells - 1 || y == 0)
  73.         *pbGrid |= *pbGrid << 4;
  74.     else
  75.         {
  76.         sSum = (*(pbGrid - 1) +
  77.             *(pbGrid - xNumCells - 1) +
  78.             *(pbGrid - xNumCells) +
  79.             *(pbGrid - xNumCells + 1))
  80.                 >> 4;
  81.  
  82.         sSum += *(pbGrid + 1) +
  83.             *(pbGrid + xNumCells + 1) +
  84.             *(pbGrid + xNumCells) +
  85.             *(pbGrid + xNumCells - 1);
  86.  
  87.         sSum = (sSum | *pbGrid) & 0x0F;
  88.  
  89.         *pbGrid <<= 4;
  90.  
  91.         if (sSum == 3)
  92.             *pbGrid |= 1;
  93.  
  94.         if ((*pbGrid & 1) != *pbGrid >> 4)
  95.             DrawCell (hps, x, y, cxCell, cyCell, *pbGrid);
  96.         }
  97.     pbGrid++;
  98.     }
  99. }
  100.  
  101. VOID DisplayGenerationNum (HPS hps, SHORT xGen, SHORT yGen, LONG lGeneration)
  102. {
  103. static CHAR szBuffer[24] = "Generation ";
  104. POINTL ptl;
  105. ptl.x=xGen;
  106. ptl.y=yGen;
  107. ltoa (lGeneration, szBuffer + 11, 10);
  108.  
  109. GpiSavePS (hps);
  110.  
  111. GpiSetBackMix (hps, BM_OVERPAINT);
  112. GpiCharStringAt(hps, &ptl, (LONG) strlen (szBuffer), szBuffer);
  113.  
  114. GpiRestorePS (hps, -1L);
  115. }
  116.  
  117. MRESULT EXPENTRY ClientWndProc(HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
  118. {
  119. static BOOL fTimerGoing;
  120. static HWND hwndMenu;
  121. static LONG lGeneration;
  122. static SEL selGrid;
  123. static SHORT cxChar, cyChar, cyDesc, cxClient, cyClient, xGenNum, yGenNum, cxCell, cyCell, xNumCells, yNumCells, sCellScale = 1;
  124. FONTMETRICS fm;
  125. HPS hps;
  126. PBYTE pbGrid;
  127. POINTL ptl;
  128. SHORT x, y;
  129.  
  130. switch (msg)
  131. {
  132. case WM_CREATE:
  133.     hps=WinGetPS(hwnd);
  134.     GpiQueryFontMetrics(hps, (LONG) sizeof fm, &fm);
  135.     cxChar = (SHORT) fm.lAveCharWidth;
  136.     cyChar = (SHORT) fm.lMaxBaselineExt;
  137.     cyDesc = (SHORT) fm.lMaxDescender;
  138.     WinReleasePS (hps);
  139.  
  140.     hwndMenu = WinWindowFromID (
  141.         WinQueryWindow (hwnd, QW_PARENT, FALSE),
  142.         FID_MENU);
  143.     return 0;
  144.  
  145. case WM_SIZE:
  146.     if (selGrid)
  147.     {
  148.         DosFreeSeg (selGrid);
  149.         selGrid = 0;
  150.     }
  151.     if (fTimerGoing)
  152.     {
  153.         WinStopTimer(hab, hwnd, ID_TIMER);
  154.         fTimerGoing = FALSE;
  155.     }
  156.  
  157. cxClient = SHORT1FROMMP (mp2);
  158. cyClient = SHORT2FROMMP (mp2);
  159.  
  160. xGenNum = cxChar;
  161. yGenNum = cyClient - cyChar + cyDesc;
  162.  
  163. cxCell = cxChar * 2 / sCellScale;
  164. cyCell = cyChar /sCellScale;
  165.  
  166. xNumCells = cxClient / cxCell;
  167. yNumCells = (cyClient - cyChar) / cyCell;
  168.  
  169. if (xNumCells <= 0 || yNumCells <= 0)
  170. {
  171.     ErrorMsg (hwnd, "Not enough room for even one cell.");
  172. }
  173.  
  174. else if ((LONG) xNumCells * yNumCells > 65536L)
  175. {
  176.     ErrorMsg (hwnd, "More than 64K cells not supported.");
  177. }
  178.  
  179. else if (DosAllocSeg (xNumCells * yNumCells, &selGrid, 0))
  180. {
  181. ErrorMsg(hwnd, "Not enough memory for this many cells.");
  182. selGrid = 0;
  183. }
  184.  
  185. else
  186. {
  187.     pbGrid = MAKEP (selGrid, 0);
  188.  
  189.     for (y = 0; y < yNumCells; y++)
  190.         for (x = 0; x < xNumCells; x++)
  191.             *pbGrid++ = 0;
  192. }
  193.  
  194. EnableMenuItem (hwndMenu, IDM_SIZE, TRUE);
  195. EnableMenuItem (hwndMenu, IDM_START, selGrid != 0);
  196. EnableMenuItem (hwndMenu, IDM_STOP, FALSE);
  197. EnableMenuItem (hwndMenu, IDM_STEP, selGrid != 0);
  198. EnableMenuItem (hwndMenu, IDM_CLEAR, selGrid != 0);
  199.  
  200. lGeneration = 0;
  201. return 0;
  202.  
  203. case WM_BUTTON1DOWN:
  204. x = MOUSEMSG(&msg)->x / cxCell;
  205. y = MOUSEMSG(&msg)->y / cyCell;
  206.  
  207. if (selGrid && !fTimerGoing && x < xNumCells && y < yNumCells)
  208. {
  209. pbGrid = MAKEP (selGrid, 0);
  210.  
  211. hps = WinGetPS (hwnd);
  212.  
  213. DrawCell (hps, x, y, cxCell, cyCell,
  214.     *(pbGrid+y * xNumCells + x) ^= 1);
  215.  
  216. WinReleasePS(hps);
  217. }
  218. else
  219.     WinAlarm(HWND_DESKTOP, WA_WARNING);
  220. break;
  221.  
  222. case WM_COMMAND:
  223. switch (COMMANDMSG(&msg)->cmd)
  224. {
  225. case IDM_LARGE:
  226. case IDM_SMALL:
  227. case IDM_TINY:
  228. WinSendMsg (hwndMenu, MM_SETITEMATTR,
  229.     MPFROM2SHORT(sCellScale, TRUE),
  230.     MPFROM2SHORT(MIA_CHECKED, 0));
  231.  
  232. sCellScale = COMMANDMSG(&msg)->cmd;
  233.  
  234. WinSendMsg (hwndMenu, MM_SETITEMATTR,
  235.     MPFROM2SHORT (sCellScale, TRUE),
  236.     MPFROM2SHORT (MIA_CHECKED, MIA_CHECKED));
  237.  
  238. WinSendMsg (hwnd, WM_SIZE, NULL,
  239.     MPFROM2SHORT(cxClient, cyClient));
  240.  
  241. WinInvalidateRect (hwnd, NULL, FALSE);
  242. return 0;
  243.  
  244. case IDM_START:
  245. if (!WinStartTimer (hab, hwnd, ID_TIMER, 1))
  246. {
  247.     ErrorMsg(hwnd, "Too many clocks or timers.");
  248. }
  249.  
  250. else
  251. {
  252.     fTimerGoing=TRUE;
  253.  
  254. EnableMenuItem(hwndMenu, IDM_SIZE, FALSE);
  255. EnableMenuItem(hwndMenu, IDM_START, FALSE);
  256. EnableMenuItem(hwndMenu, IDM_STOP, TRUE);
  257. EnableMenuItem(hwndMenu, IDM_STEP, FALSE);
  258. EnableMenuItem(hwndMenu, IDM_CLEAR, FALSE);
  259. }
  260. return 0;
  261.  
  262. case IDM_STOP:
  263. WinStopTimer(hab,hwnd, ID_TIMER);
  264. fTimerGoing = FALSE;
  265.  
  266. EnableMenuItem(hwndMenu, IDM_SIZE, TRUE);
  267. EnableMenuItem(hwndMenu, IDM_START, TRUE);
  268. EnableMenuItem(hwndMenu, IDM_STOP, FALSE);
  269. EnableMenuItem(hwndMenu, IDM_STEP, TRUE);
  270. EnableMenuItem(hwndMenu, IDM_CLEAR, TRUE);
  271. return 0;
  272.  
  273. case IDM_STEP:
  274.     WinSendMsg(hwnd, WM_TIMER, NULL, NULL);
  275.     return 0;
  276.  
  277. case IDM_CLEAR:
  278.     lGeneration=0L;
  279.  
  280.     pbGrid = MAKEP(selGrid, 0);
  281.  
  282. for (y = 0; y < yNumCells; y++)
  283.     for (x = 0; x < xNumCells; x++)
  284.         *pbGrid++ = 0;
  285.  
  286. WinInvalidateRect(hwnd, NULL, FALSE);
  287. return 0;
  288. }
  289. break;
  290.  
  291. case WM_TIMER:
  292.     hps = WinGetPS(hwnd);
  293.  
  294.     DisplayGenerationNum(hps, xGenNum, yGenNum, ++lGeneration);
  295.  
  296. pbGrid = MAKEP(selGrid, 0);
  297.  
  298. DoGeneration (hps, pbGrid, xNumCells, yNumCells, cxCell, cyCell);
  299.  
  300. WinReleasePS (hps);
  301. return 0;
  302.  
  303. case WM_PAINT:
  304.     hps = WinBeginPaint (hwnd, NULL, NULL);
  305.     GpiErase (hps);
  306.  
  307. if (selGrid)
  308. {
  309. for (x = 1; x <= xNumCells; x++)
  310. {
  311. ptl.x = cxCell * x - 1;
  312. ptl.y = 0;
  313. GpiMove (hps, &ptl);
  314.  
  315. ptl.y = cyCell * yNumCells -1;
  316. GpiLine (hps, &ptl);
  317. }
  318.  
  319. for (y = 1; y<=yNumCells; y++)
  320. {
  321. ptl.x = 0;
  322. ptl.y = cyCell * y - 1;
  323. GpiMove (hps, &ptl);
  324.  
  325. ptl.x = cxCell * xNumCells - 1;
  326. GpiLine (hps, &ptl);
  327. }
  328.  
  329. pbGrid = MAKEP (selGrid, 0);
  330.  
  331. for (y = 0; y < yNumCells; y++)
  332. for (x = 0; x < xNumCells; x++)
  333. if (*pbGrid++)
  334. DrawCell (hps, x, y, cxCell, cyCell, *(pbGrid-1));
  335.  
  336. DisplayGenerationNum (hps, xGenNum, yGenNum, lGeneration);
  337. }
  338. WinEndPaint(hps);
  339. return 0;
  340.  
  341. case WM_DESTROY:
  342. if (fTimerGoing)
  343. WinStopTimer (hab, hwnd, ID_TIMER);
  344.  
  345. if (selGrid)
  346.     DosFreeSeg(selGrid);
  347.  
  348. return 0;
  349. }
  350. return WinDefWindowProc(hwnd, msg, mp1, mp2);
  351. }
  352.