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

unix.superglobalmegacorp.com

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