home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Entertainment / Concentration / Dialog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-25  |  7.1 KB  |  357 lines  |  [TEXT/KAHL]

  1. /*
  2.  * Player name and board size dialogs
  3.  */
  4.  
  5.  
  6. # include    "TransSkel.h"
  7. # include    "Message.h"
  8.  
  9. # include    "Concentration.h"
  10.  
  11.  
  12. typedef enum        /* Player dialog item numbers */
  13. {
  14.     pOK = 1,
  15.     pCancel,
  16.     pNameText,        /* first editText name item */
  17.     pNameText2,
  18.     pNameText3,
  19.     pNameText4,
  20.     pNameTitle,
  21.     pOutlineUser
  22. };
  23.  
  24.  
  25. typedef enum        /* Board Size dialog item numbers */
  26. {
  27.     bOK = 1,
  28.     bCancel,
  29.     bBoardUser,            /* board sizing item */
  30.     bTitleStatText,
  31.     bOutlineUser
  32. };
  33.  
  34.  
  35. static BlobSetHandle    board;
  36. static short            curRows, curCols;
  37.  
  38.  
  39. /*
  40.  * Run Player name dialog.  Make a copy of the scoreboard, and modify the
  41.  * copy when checking whether there are actually any names given after OK
  42.  * is clicked.  If so, copy the new scoreboard back into the real scoreboard
  43.  * to update it.
  44.  */
  45.  
  46. void
  47. PlayerDialog (void)
  48. {
  49. ModalFilterProcPtr    filter;
  50. DialogPtr    dlog;
  51. GrafPtr        savePort;
  52. ScoreBoard    newScoreBoard;
  53. ScoreBoard    *nsb = &newScoreBoard;
  54. short        item;
  55. short        i;
  56. Str255        s;
  57.  
  58.     dlog = GetNewDialog (playerDlogNum, nil, (WindowPtr) -1L);
  59.     if (dlog == (DialogPtr) nil)
  60.     {
  61.         SysBeep (1);
  62.         return;
  63.     }
  64.  
  65.     SkelPositionWindow (dlog, skelPositionOnParentDevice, horizRatio, vertRatio);
  66.  
  67.     SkelSetDlogButtonOutliner (dlog, pOutlineUser);
  68.  
  69.     *nsb = *sb;            /* make copy of current scoreboard */
  70.     
  71.     /*
  72.      * Put current names into dialog and select first one
  73.      */
  74.  
  75.     for (i = 0; i < nsb->nPlayers; i++)
  76.         SkelSetDlogStr (dlog, pNameText + i, nsb->name[i]);
  77.     for (i = nsb->nPlayers; i < maxPlayers; i++)
  78.         SkelSetDlogStr (dlog, pNameText + i, "\p");
  79.     SelIText (dlog, pNameText, 0, 32767);
  80.  
  81.     GetPort (&savePort);
  82.     SetPort (dlog);
  83.     ShowWindow (dlog);
  84.  
  85.     for (;;)
  86.     {
  87.         filter = SkelDlogFilter (nil, true);
  88.         SkelDlogCancelItem (pCancel);
  89.         ModalDialog (filter, &item);
  90.         SkelRmveDlogFilter ();
  91.         if (item == pCancel)
  92.             break;
  93.         if (item == pOK)
  94.         {
  95.             /*
  96.              * If OK is hit, determine number of names actually specified.
  97.              * There must be at least one player.
  98.              */
  99.             nsb->nPlayers = 0;
  100.             for (i = pNameText; i < pNameText + maxPlayers; ++i)
  101.             {
  102.                 SkelGetDlogStr (dlog, i, nsb->name[nsb->nPlayers]);
  103.                 if (nsb->name[nsb->nPlayers][0] > 0)
  104.                     ++nsb->nPlayers;
  105.             }
  106.             if (nsb->nPlayers > 0)
  107.                 break;
  108.             Message1 ("\pYou must have at least one player");
  109.         }
  110.     }
  111.  
  112.     DisposeDialog (dlog);
  113.     SetPort (savePort);
  114.     SkelDoUpdates ();
  115.  
  116.     /*
  117.      * If the number of players is the same, just update the scoreboard
  118.      * for the current game.  Otherwise update the scoreboard and start
  119.      * new round game.
  120.      */
  121.  
  122.     if (item == pOK)
  123.     {
  124.         if (nsb->nPlayers == sb->nPlayers)
  125.         {
  126.             *sb = *nsb;
  127.             DrawScoreBoard ();
  128.         }
  129.         else
  130.         {
  131.             *sb = *nsb;
  132.             NewGameRound ();
  133.         }
  134.     }
  135. }
  136.  
  137.  
  138. /* -------------------------------------------------------------------- */
  139. /*                Filter proc stuff for board size dialog                    */
  140. /* -------------------------------------------------------------------- */
  141.  
  142.  
  143. /*
  144.  * Draw a board blob.  If the blob has a glob, paint it, otherwise
  145.  * just a frame.  Painted blobs indicate selected parts of the board.
  146.  *
  147.  * bDst        blob to draw in
  148.  * bSrc        blob to be drawn in bDst
  149.  */
  150.  
  151. static pascal void
  152. DrawBoardBlob (BlobHandle bDst, BlobHandle bSrc, short partCode)
  153. {
  154. Rect    r;
  155.  
  156.     switch (partCode)
  157.     {
  158.  
  159.     case inStatBlob:                    /* ignore */
  160.         break;
  161.  
  162.     case inDragBlob:
  163.         r = BDragBox (bDst);
  164.         InsetRect (&r, 1, 1);
  165.         if (BGlob (bDst) != nil)        /* selected */
  166.             PaintRect (&r);
  167.         else
  168.         {
  169.             FrameRect (&r);
  170.             InsetRect (&r, 1, 1);
  171.             EraseRect (&r);
  172.         }
  173.         break;
  174.     }
  175. }
  176.  
  177.  
  178. /*
  179.  * Draw the board properly, showing as dark all the squares that are
  180.  * currently selected.  Note that globs can be glued and unglued with
  181.  * impunity, as the Blob Manager redraws only on a state *change*.
  182.  */
  183.  
  184. static void
  185. HiliteBoard (void)
  186. {
  187. BlobHandle    b;
  188. short        row, col;
  189. long        refCon;
  190.  
  191.     for (b = FirstBlob (board); b != nil; b = NextBlob (b))
  192.     {
  193.         refCon = GetBRefCon (b);
  194.         col = HiWord (refCon);
  195.         row = LoWord (refCon);
  196.         if (col < curCols && row < curRows)
  197.             GlueGlob (b, b);                /* select */
  198.         else
  199.             UnglueGlob (b);                    /* deselect */
  200.     }
  201. }
  202.  
  203.  
  204. /*
  205.  * Filter function for board dialog.  Checks for hits in the blobs
  206.  * used to represent the board and selects all blobs in the rectangle
  207.  * defined by the upper left blob to the one clicked in.  Then follow
  208.  * the mouse as long as it's held down.  This is not done especially
  209.  * intelligently - there's no check even whether the mouse has changed
  210.  * blobs before rehiliting the board.  Still, it's not unacceptably
  211.  * slow.
  212.  *
  213.  * The filter only changes the selected squares when the mouse sweeps
  214.  * to a square that results in a non-empty board with an even number
  215.  * of pieces.
  216.  */
  217.  
  218. static pascal Boolean
  219. BoardFilter (DialogPtr dlog, EventRecord *evt, short *item)
  220. {
  221. Point        pt;
  222. BlobHandle    b;
  223. long        refCon;
  224. short        rows, cols;
  225.  
  226.     if (evt->what == mouseDown)
  227.     {
  228.         pt = evt->where;
  229.         GlobalToLocal (&pt);
  230.         if (FindBlob (pt, board, &b) != 0)
  231.         {
  232.             for (;;)
  233.             {
  234.                 if (b != nil)
  235.                 {
  236.                     refCon = GetBRefCon (b);
  237.                     cols = HiWord (refCon) + 1;
  238.                     rows = LoWord (refCon) + 1;
  239.                     if ((cols * rows) % 2 == 0)            /* must have even */
  240.                     {                                    /* number of squares */
  241.                         curCols = cols;
  242.                         curRows = rows;
  243.                         HiliteBoard ();
  244.                     }                
  245.                 }
  246.                 if (!StillDown ())
  247.                     break;
  248.                 GetMouse (&pt);
  249.                 if (FindBlob (pt, board, &b) == 0)
  250.                     b = nil;
  251.             }
  252.         }
  253.     }
  254.     return (false);
  255. }
  256.  
  257.  
  258. static pascal void
  259. DoFrame (DialogPtr dlog, short item)
  260. {
  261. Rect    r;
  262.  
  263.     SkelGetDlogRect (dlog, item, &r);
  264.     if (gb->sizeType == smallPiece)
  265.     {
  266.         r.bottom -= 3;    /* account for slight differences */
  267.         r.right -= 4;    /* in size for different pieces */
  268.     }
  269.     FrameRect (&r);
  270.     DrawBlobSet (board);
  271. }
  272.  
  273.  
  274. void
  275. BoardDialog (void)
  276. {
  277. ModalFilterProcPtr    filter;
  278. DialogPtr    dlog;
  279. GrafPtr        savePort;
  280. short        item;
  281. short        i, j, rows, cols, h, v, size;
  282. Rect        boardRect, pieceRect;
  283. BlobHandle    b;
  284.  
  285.     dlog = GetNewDialog (boardDlogNum, nil, (WindowPtr) -1L);
  286.     if (dlog == (DialogPtr) nil)
  287.     {
  288.         SysBeep (1);
  289.         return;
  290.     }
  291.  
  292.     SkelPositionWindow (dlog, skelPositionOnParentDevice, horizRatio, vertRatio);
  293.  
  294.     GetPort (&savePort);
  295.     SetPort (dlog);
  296.  
  297.     SkelSetDlogButtonOutliner (dlog, bOutlineUser);
  298.     SkelSetDlogProc (dlog, bBoardUser, DoFrame);
  299.  
  300.     curRows = gb->nRows;
  301.     curCols = gb->nCols;
  302.     rows = gb->maxRows;
  303.     cols = gb->maxCols;
  304.     if (gb->sizeType == largePiece)
  305.         size = 23;
  306.     else
  307.         size = 15;
  308.  
  309.     SkelGetDlogRect (dlog, bBoardUser, &boardRect);
  310.     board = NewBlobSet ();
  311.     for (i = 0; i < rows; ++i)
  312.     {
  313.         for (j = 0; j < cols; ++j)
  314.         {
  315.             b = NewBlob (board, true, infiniteGlue, false,
  316.                             (long) (((long) j << 16) | i));
  317.             h = boardRect.left + 1 + (j * size);
  318.             v = boardRect.top + 1 + (i * size);
  319.             SetRect (&pieceRect, h, v, h + size, v + size);
  320.             SetProcRectBlob (b, DrawBoardBlob, &pieceRect, &pieceRect);
  321.         }
  322.     }
  323.     HiliteBoard ();
  324.     ShowWindow (dlog);
  325.  
  326.     for (;;)
  327.     {
  328.         filter = SkelDlogFilter (BoardFilter, true);
  329.         SkelDlogCancelItem (bCancel);
  330.         ModalDialog (filter, &item);
  331.         SkelRmveDlogFilter ();
  332.         if (item == bOK || item == bCancel)
  333.             break;
  334.     }
  335.  
  336.     DisposeBlobSet (board);
  337.     SetPort (savePort);
  338.     DisposeDialog (dlog);
  339.     SkelDoUpdates ();
  340.  
  341.     /*
  342.      * If board size changed, reinitialize board using same sizeType
  343.      * but new dimensions, then start new round of game
  344.      */
  345.     
  346.     if (item == bOK)
  347.     {
  348.         if (gb->nRows != curRows || gb->nCols != curCols)
  349.         {
  350.             gb->nRows = curRows;
  351.             gb->nCols = curCols;
  352.             InitBoard (gb->sizeType);
  353.             NewGameRound ();
  354.         }
  355.     }
  356. }
  357.