home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format 115 / af115sub.adf / yahzee.lzx / yahzee / layout.c < prev    next >
C/C++ Source or Header  |  1998-06-03  |  14KB  |  397 lines

  1. /*
  2.  * layout.c
  3.  * ========
  4.  * Handles layout of display.
  5.  *
  6.  * Copyright (C) 1994-1998 Håkan L. Younes (lorens@hem.passagen.se)
  7.  */
  8.  
  9. #include <exec/types.h>
  10. #include <graphics/gfxbase.h>
  11. #include "requesters.h"
  12. #include "rules.h"
  13. #include "draw.h"
  14. #include "layout_const.h"
  15. #include "layout.h"
  16.  
  17. #include <clib/exec_protos.h>
  18. #include <clib/gadtools_protos.h>
  19. #include <clib/graphics_protos.h>
  20. #include <clib/intuition_protos.h>
  21.  
  22.  
  23. #define MAX(a, b)   (((a) > (b)) ? (a) : (b))
  24.  
  25.  
  26. struct TextAttr   topaz8 = {
  27.    "topaz.font", 8, 0, FPF_ROMFONT
  28. };
  29.  
  30. extern struct GfxBase  *GfxBase;
  31. extern struct TextFont  *romfont;
  32. extern char   scr_title[];
  33. extern char   win_title[];
  34. extern struct Gadget   die_gads[];
  35. extern struct Gadget  *roll_gad, *disp_gad, *gt_gads;
  36. extern struct NewGadget   new_roll_gad, new_disp_gad;
  37.  
  38.  
  39. static void
  40. upper_board_extent (
  41.    struct rules  *rules,
  42.    UBYTE          num_players,
  43.    BOOL           split_board,
  44.    UWORD          font_w,
  45.    UWORD          font_h,
  46.    UWORD         *width,
  47.    UWORD         *height)
  48. {
  49.    *width = (upper_label_len (rules) + 3 * num_players) * font_w +
  50.             (num_players + 1) * (INTERWIDTH / 2 + LINEWIDTH) + LINEWIDTH;
  51.    *height = (num_upper_labels (rules) + 1) *
  52.              (font_h + INTERHEIGHT / 2 + LINEHEIGHT) + LINEHEIGHT;
  53. }
  54.  
  55. static void
  56. lower_board_extent (
  57.    struct rules  *rules,
  58.    UBYTE          num_players,
  59.    BOOL           split_board,
  60.    UWORD          font_w,
  61.    UWORD          font_h,
  62.    UWORD         *width,
  63.    UWORD         *height)
  64. {
  65.    *width = (lower_label_len (rules) + 3 * num_players) * font_w +
  66.             (num_players + 1) * (INTERWIDTH / 2 + LINEWIDTH) + LINEWIDTH;
  67.    *height = num_lower_labels (rules) *
  68.              (font_h + INTERHEIGHT / 2 + LINEHEIGHT) + LINEHEIGHT;
  69.    if (split_board)
  70.       *height += font_h + INTERHEIGHT / 2 + LINEHEIGHT;
  71. }
  72.  
  73. static void
  74. gadget_extent (
  75.    struct Screen  *scr,
  76.    struct rules   *rules,
  77.    UWORD          *width,
  78.    UWORD          *height,
  79.    BOOL            vert_gads)
  80. {
  81.    if (vert_gads)
  82.    {
  83.       *width = MAX (new_roll_gad.ng_Width, die_gads[0].Width);
  84.       *height = rules->num_dice * (die_gads[0].Height + INTERHEIGHT) +
  85.                 new_roll_gad.ng_Height + new_disp_gad.ng_Height + INTERHEIGHT;
  86.    }
  87.    else
  88.    {
  89.       *width = rules->num_dice * (die_gads[0].Width + INTERWIDTH) +
  90.                new_roll_gad.ng_Width + new_disp_gad.ng_Width + INTERWIDTH;
  91.       *height = MAX (new_roll_gad.ng_Height, die_gads[0].Height);
  92.    }
  93. }
  94.  
  95. BOOL
  96. layout_display (
  97.    struct Screen  *scr,
  98.    struct Window **win,
  99.    struct rules   *rules,
  100.    UBYTE           num_players)
  101. {
  102.    register UBYTE   n;
  103.    BOOL    done, split_board, board_romfont, vert_gads;
  104.    UWORD   used_w, used_h;
  105.    UWORD   board_w[2], board_h[2];
  106.    UWORD   gadget_w = 0, gadget_h = 0;
  107.    
  108.    done = FALSE;
  109.    for (n = 1; n <= 8 && !done; ++n)
  110.    {
  111.       split_board = !(n & 1);
  112.       board_romfont = (n > 4);
  113.       vert_gads = (n + 1) / 2 & 1;
  114.       
  115.       upper_board_extent (rules, num_players, split_board,
  116.                           (board_romfont) ? ROMFONT_WIDTH :
  117.                                             GfxBase->DefaultFont->tf_XSize,
  118.                           (board_romfont) ? ROMFONT_HEIGHT :
  119.                                             GfxBase->DefaultFont->tf_YSize,
  120.                           &board_w[0], &board_h[0]);
  121.       lower_board_extent (rules, num_players, split_board,
  122.                           (board_romfont) ? ROMFONT_WIDTH :
  123.                                             GfxBase->DefaultFont->tf_XSize,
  124.                           (board_romfont) ? ROMFONT_HEIGHT :
  125.                                             GfxBase->DefaultFont->tf_YSize,
  126.                           &board_w[1], &board_h[1]);
  127.       if (split_board)
  128.       {
  129.          used_w = board_w[0] + board_w[1] - LINEWIDTH;
  130.          used_h = MAX (board_h[0], board_h[1]);
  131.       }
  132.       else
  133.       {
  134.          used_w = MAX (board_w[0], board_w[1]);
  135.          used_h = board_h[0] + board_h[1] - LINEHEIGHT;
  136.       }
  137.       gadget_extent (scr, rules, &gadget_w, &gadget_h, vert_gads);
  138.       if (vert_gads)
  139.       {
  140.          used_w += gadget_w + 3 * INTERWIDTH + scr->WBorLeft + scr->WBorRight;
  141.          used_h = MAX (used_h, gadget_h) + 2 * INTERHEIGHT + scr->WBorTop +
  142.                   scr->WBorBottom + scr->Font->ta_YSize + 1;
  143.       }
  144.       else
  145.       {
  146.          used_w = MAX (used_w, gadget_w) + 2 * INTERWIDTH +
  147.                   scr->WBorLeft + scr->WBorRight;
  148.          used_h += gadget_h + 3 * INTERHEIGHT + scr->WBorTop +
  149.                    scr->WBorBottom + scr->Font->ta_YSize + 1;
  150.       }
  151.       
  152.       if (used_w <= scr->Width && used_h <= scr->Height)
  153.          done = TRUE;
  154.    }
  155.    if (!done)
  156.    {
  157.       msg_requester (NULL, "Error Message", "OK", "Screen is too small!");
  158.       
  159.       return FALSE;
  160.    }
  161.    
  162.    if (board_romfont && romfont == NULL)
  163.    {
  164.       if (!(romfont = OpenFont (&topaz8)))
  165.       {
  166.          msg_requester (NULL, "Error Message", "OK",
  167.                         "Couldn't open topaz.font!");
  168.          
  169.          return FALSE;
  170.       }
  171.    }
  172.    
  173.    if (*win == NULL)
  174.    {
  175.       *win = OpenWindowTags (NULL,
  176.                              WA_Left, (scr->Width - used_w) / 2,
  177.                              WA_Top, (scr->Height - used_h) / 2,
  178.                              WA_Width, used_w,
  179.                              WA_Height, used_h,
  180.                              WA_AutoAdjust, FALSE,
  181.                              WA_Activate, TRUE,
  182.                              WA_CloseGadget, TRUE,
  183.                              WA_DepthGadget, TRUE,
  184.                              WA_DragBar, TRUE,
  185.                              WA_Title, win_title,
  186.                              WA_ScreenTitle, scr_title,
  187.                              WA_PubScreen, scr,
  188.                              WA_NewLookMenus, TRUE,
  189.                              WA_IDCMP, BUTTONIDCMP | IDCMP_MOUSEBUTTONS |
  190.                                        IDCMP_MENUPICK | IDCMP_CLOSEWINDOW |
  191.                                        IDCMP_REFRESHWINDOW |
  192.                                        IDCMP_CHANGEWINDOW,
  193.                              TAG_DONE);
  194.    }
  195.    else
  196.    {
  197.       struct IntuiMessage  *msg;
  198.       BOOL   done = FALSE;
  199.       
  200.       delete_scoreboard ((*win)->RPort);
  201.       delete_gadgets ((*win)->RPort, die_gads);
  202.       RemoveGList (*win, die_gads, -1);
  203.       FreeGadgets (gt_gads);
  204.       ChangeWindowBox (*win,
  205.                        (used_w > scr->Width - (*win)->LeftEdge) ?
  206.                        scr->Width - used_w : (*win)->LeftEdge,
  207.                        (used_h > scr->Height - (*win)->TopEdge) ?
  208.                        scr->Height - used_h : (*win)->TopEdge,
  209.                        used_w, used_h);
  210.       WaitPort ((*win)->UserPort);
  211.       while (!done && (msg = (struct IntuiMessage *)GetMsg ((*win)->UserPort)))
  212.       {
  213.          done = (msg->Class == IDCMP_CHANGEWINDOW);
  214.          ReplyMsg ((struct Message *)msg);
  215.       }
  216.    }
  217.    if (*win == NULL)
  218.    {
  219.       msg_requester (NULL, "Error Message", "OK", "Couldn't open window!");
  220.       
  221.       return FALSE;
  222.    }
  223.    
  224.    for (n = 0; n < rules->num_dice; ++n)
  225.    {
  226.       die_gads[n].NextGadget = (n == rules->num_dice - 1) ? NULL :
  227.                                                             &die_gads[n + 1];
  228.       if (vert_gads)
  229.       {
  230.          die_gads[n].LeftEdge = used_w - (*win)->BorderRight - INTERWIDTH -
  231.                                 gadget_w + (gadget_w - die_gads[n].Width) / 2;
  232.          die_gads[n].TopEdge = ((n > 0) ?
  233.                              die_gads[n - 1].TopEdge + die_gads[n - 1].Height :
  234.                              (*win)->BorderTop) + INTERHEIGHT;
  235.       }
  236.       else
  237.       {
  238.          die_gads[n].LeftEdge = ((n > 0) ?
  239.                              die_gads[n - 1].LeftEdge + die_gads[n - 1].Width :
  240.                              (*win)->BorderLeft) + INTERWIDTH;
  241.          die_gads[n].TopEdge = used_h - (*win)->BorderBottom - INTERHEIGHT -
  242.                                gadget_h + (gadget_h - die_gads[n].Height) / 2;
  243.       }
  244.       die_gads[n].Flags |= GFLG_DISABLED;
  245.    }
  246.    AddGList (*win, die_gads, -1, -1, NULL);
  247.    if (vert_gads)
  248.    {
  249.       new_roll_gad.ng_LeftEdge = used_w - (*win)->BorderRight - INTERWIDTH -
  250.                                  gadget_w +
  251.                                  (gadget_w - new_roll_gad.ng_Width) / 2;
  252.       new_roll_gad.ng_TopEdge = die_gads[n - 1].TopEdge +
  253.                                 die_gads[n - 1].Height + INTERHEIGHT;
  254.       new_disp_gad.ng_LeftEdge = new_roll_gad.ng_LeftEdge;
  255.       new_disp_gad.ng_TopEdge = new_roll_gad.ng_TopEdge +
  256.                                 new_roll_gad.ng_Height + INTERHEIGHT;
  257.    }
  258.    else
  259.    {
  260.       new_roll_gad.ng_LeftEdge = die_gads[n - 1].LeftEdge +
  261.                                  die_gads[n - 1].Width + INTERWIDTH;
  262.       new_roll_gad.ng_TopEdge = used_h - (*win)->BorderBottom - INTERHEIGHT -
  263.                                 gadget_h +
  264.                                 (gadget_h - new_roll_gad.ng_Height) / 2;
  265.       new_disp_gad.ng_LeftEdge = new_roll_gad.ng_LeftEdge +
  266.                                  new_roll_gad.ng_Width + INTERWIDTH;
  267.       new_disp_gad.ng_TopEdge = new_roll_gad.ng_TopEdge;
  268.    }
  269.    roll_gad = CreateContext (>_gads);
  270.    roll_gad = CreateGadget (BUTTON_KIND, roll_gad, &new_roll_gad, TAG_DONE);
  271.    disp_gad = CreateGadget (NUMBER_KIND, roll_gad, &new_disp_gad,
  272.                             GTNM_Number, 3, GTNM_Border, TRUE, TAG_DONE);
  273.    if (disp_gad == NULL)
  274.    {
  275.       msg_requester (NULL, "Error Message", "OK",
  276.                      "Couldn't create gadgets!");
  277.       
  278.       return FALSE;
  279.    }
  280.    AddGList (*win, gt_gads, -1, -1, NULL);
  281.    RefreshGadgets (die_gads, *win, NULL);
  282.    GT_RefreshWindow (*win, NULL);
  283.    
  284.    SetFont ((*win)->RPort, (board_romfont) ? romfont : GfxBase->DefaultFont);
  285.    init_board_grid (*win, rules, num_players, split_board);
  286.    draw_scoreboard ((*win)->RPort, rules, num_players);
  287.    
  288.    return TRUE;
  289. }
  290.  
  291. void
  292. init_board_grid (
  293.    struct Window  *win,
  294.    struct rules   *rules,
  295.    UBYTE           num_players,
  296.    BOOL            split_board)
  297. {
  298.    register UBYTE   i, j, prev;
  299.    UBYTE   limit;
  300.    
  301.    limit = num_upper_labels (rules);
  302.    upper_board.left = win->BorderLeft + INTERWIDTH;
  303.    upper_board.top = win->BorderTop + INTERHEIGHT;
  304.    upper_board_extent (rules, num_players, split_board,
  305.                        win->RPort->TxWidth, win->RPort->TxHeight,
  306.                        &upper_board.width, &upper_board.height);
  307.    lower_board.left = upper_board.left +
  308.                       ((split_board) ? upper_board.width - LINEWIDTH : 0);
  309.    lower_board.top = upper_board.top +
  310.                      ((split_board) ? 0 : upper_board.height - LINEHEIGHT);
  311.    lower_board_extent (rules, num_players, split_board,
  312.                       win->RPort->TxWidth, win->RPort->TxHeight,
  313.                       &lower_board.width, &lower_board.height);
  314.    if (!split_board)
  315.    {
  316.       upper_board.width = MAX (upper_board.width, lower_board.width);
  317.       lower_board.width = upper_board.width;
  318.    }
  319.    
  320.    board_grid[0][0].left = upper_board.left + LINEWIDTH;
  321.    board_grid[0][0].top = upper_board.top + win->RPort->TxHeight +
  322.                           INTERHEIGHT / 2 + 2 * LINEHEIGHT;
  323.    board_grid[0][0].width = INTERWIDTH / 2 +
  324.                             upper_label_len (rules) * win->RPort->TxWidth;
  325.    if (!split_board)
  326.    {
  327.       board_grid[0][limit].width = INTERWIDTH / 2 +
  328.                                  lower_label_len (rules) * win->RPort->TxWidth;
  329.       board_grid[0][0].width = MAX (board_grid[0][0].width,
  330.                                     board_grid[0][limit].width);
  331.    }
  332.    board_grid[0][0].height = win->RPort->TxHeight + INTERHEIGHT / 2;
  333.    for (i = 1; i <= num_players; ++i)
  334.    {
  335.       board_grid[i][0].left = board_grid[i - 1][0].left +
  336.                               board_grid[i - 1][0].width + LINEWIDTH;
  337.       board_grid[i][0].top = board_grid[0][0].top;
  338.       board_grid[i][0].width = 3 * win->RPort->TxWidth + INTERWIDTH / 2;
  339.       board_grid[i][0].height = board_grid[0][0].height;
  340.    }
  341.    prev = 0;
  342.    for (j = 1; j < limit; ++j)
  343.    {
  344.       if (!rules->labels[j])
  345.          ++limit;
  346.       else
  347.       {
  348.          for (i = 0; i <= num_players; ++i)
  349.          {
  350.             board_grid[i][j].left = board_grid[i][prev].left;
  351.             board_grid[i][j].top = board_grid[i][prev].top +
  352.                                    board_grid[i][prev].height + LINEHEIGHT;
  353.             board_grid[i][j].width = board_grid[i][prev].width;
  354.             board_grid[i][j].height = board_grid[i][prev].height;
  355.          }
  356.          prev = j;
  357.       }
  358.    }
  359.    if (split_board)
  360.    {
  361.       while (!rules->labels[j])
  362.          ++j;
  363.       
  364.       board_grid[0][j].left = lower_board.left + LINEWIDTH;
  365.       board_grid[0][j].top = board_grid[0][0].top;
  366.       board_grid[0][j].width = INTERWIDTH / 2 +
  367.                                lower_label_len (rules) * win->RPort->TxWidth;
  368.       board_grid[0][j].height = board_grid[0][0].height;
  369.       for (i = 1; i <= num_players; ++i)
  370.       {
  371.          board_grid[i][j].left = board_grid[i - 1][j].left +
  372.                                  board_grid[i - 1][j].width + LINEWIDTH;
  373.          board_grid[i][j].top = board_grid[0][j].top;
  374.          board_grid[i][j].width = 3 * win->RPort->TxWidth + INTERWIDTH / 2;
  375.          board_grid[i][j].height = board_grid[0][j].height;
  376.       }
  377.       prev = j;
  378.       ++j;
  379.    }
  380.    for (; j < MAX_LABELS; ++j)
  381.    {
  382.       if (rules->labels[j])
  383.       {
  384.          for (i = 0; i <= num_players; ++i)
  385.          {
  386.             board_grid[i][j].left = board_grid[i][prev].left;
  387.             board_grid[i][j].top = board_grid[i][prev].top +
  388.                                    board_grid[i][prev].height + LINEHEIGHT;
  389.             board_grid[i][j].width = board_grid[i][prev].width;
  390.             board_grid[i][j].height = board_grid[i][prev].height;
  391.          }
  392.          prev = j;
  393.       }
  394.    }
  395. }
  396.  
  397.