Annotation of pmsdk/samples/petzold/chap13/life.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.