Annotation of pmsdk/samples/petzold/chap13/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: #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.