home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d502 / cells.lha / CELLS / CELLSSource.lzh / cSelect.c < prev    next >
C/C++ Source or Header  |  1991-04-20  |  10KB  |  436 lines

  1. /*
  2.  *  CELLS       An Implementation of the WireWorld cellular automata
  3.  *              as described in Scientific American, Jan 1990.
  4.  *
  5.  *              Copyright 1990 by Davide P. Cervone.
  6.  *  You may use this code, provided this copyright notice is kept intact.
  7.  *  See the CELLS.HELP file for complete information on distribution conditions.
  8.  */
  9.  
  10. /*
  11.  *  File:  cSelect.c            Handles the SELECT command.
  12.  */
  13.  
  14.  
  15. #include "cGadget.h"
  16.  
  17. int SelectType;
  18.  
  19. static short BoxX,BoxY,BoxW,BoxH;          /* position ans size of select box */
  20. static short SelectX,SelectY,SelectPen;    /* last selection and pen */
  21.  
  22. extern short OffMC;                         /* offset within state array */
  23.  
  24.  
  25.  
  26. /*
  27.  *  InvertGadget()
  28.  *
  29.  *  Inverts the specified gadget on the control panel be inverting its
  30.  *  bounding rectangle.
  31.  */
  32.  
  33. void InvertGadget(theGadget)
  34. struct Gadget *theGadget;
  35. {
  36.    short x = theGadget->LeftEdge,
  37.          y = theGadget->TopEdge,
  38.          w = theGadget->Width,
  39.          h = theGadget->Height;
  40.  
  41.    SetAPen(wrp,0xFF);
  42.    SetDrMd(wrp,COMPLEMENT);
  43.    RectFill(wrp,x,y,x+w-1,y+h-1);
  44.    theGadget->MyFlags ^= BUTTON_SELECTED;
  45. }
  46.  
  47.  
  48. /*
  49.  *  BoxCell()
  50.  *
  51.  *  Draw a border around the specified cell in the specified Rast Port.
  52.  */
  53.  
  54. void BoxCell(rp,x,y,Pen)
  55. struct RastPort *rp;
  56. short x,y;
  57. int Pen;
  58. {
  59.    short X = x * CellSize + BoardX + 1;
  60.    short Y = y * CellSize + BoardY + 1;
  61.  
  62.    SetAPen(rp,Pen);
  63.    SetDrMd(rp,JAM1);
  64.    Move(rp,X,Y);
  65.    Draw(rp,X,Y+CellSize-2);
  66.    Draw(rp,X+CellSize-2,Y+CellSize-2);
  67.    Draw(rp,X+CellSize-2,Y);
  68.    Draw(rp,X+1,Y);
  69. }
  70.  
  71.  
  72. /*
  73.  *  InvertBox()
  74.  *
  75.  *  Invert the seletion box's boundary.
  76.  */
  77.  
  78. void InvertBox()
  79. {
  80.    short X = BoxX * CellSize + BoardX;
  81.    short Y = BoxY * CellSize + BoardY;
  82.    short W = BoxW * CellSize;
  83.    short H = BoxH * CellSize;
  84.    
  85.    wrp->Mask = SELECTPEN|GRID;
  86.    SetAPen(wrp,SELECTPEN|GRID);
  87.    SetDrMd(wrp,COMPLEMENT);
  88.    Move(wrp,X,Y);
  89.    Draw(wrp,X,Y+H);
  90.    Draw(wrp,X+W,Y+H);
  91.    Draw(wrp,X+W,Y);
  92.    Draw(wrp,X+1,Y);
  93.    wrp->Mask = 0xFF;
  94. }
  95.  
  96.  
  97. /*
  98.  *  SelectMouseCell()
  99.  *
  100.  *  If the mouse event is inside the grid area
  101.  *    If the selected cell is not the last selected cell,
  102.  *      Record that this cell is selected
  103.  *      Record wether we are selecting or deselecting, if necessary
  104.  *      Get the current cell's color
  105.  *      If we are adding to the selection
  106.  *        Box in the newly selected cell (in both buffers)
  107.  *        Set the cell in the selected cell array
  108.  *      Otherwise (unselecting)
  109.  *        Put the cell back to normal (in both buffers)
  110.  *        Clear the cell from the selected array
  111.  */
  112.  
  113. void SelectMouseCell(MouseX,MouseY,SetPen)
  114. short MouseX,MouseY;
  115. int SetPen;
  116. {
  117.    short x,y;
  118.    int Pen;
  119.  
  120.    if (InBoard(MouseX,MouseY,&x,&y))
  121.    {
  122.       if (x != SelectX || y != SelectY)
  123.       {
  124.          SelectX = x; SelectY = y;
  125.          x += GridX; y+= GridY;
  126.          if (SetPen) SelectPen = (CellColor(NewGen,x,y) == 0);
  127.          Pen = CellColor(CurGen,x,y);
  128.          if (SelectPen)
  129.          {
  130.             BoxCell(wrp,SelectX,SelectY,MOVEPEN);
  131.             if (DBufMode) BoxCell(rp,SelectX,SelectY,MOVEPEN);
  132.             SetCell(NewGen,x,y,Pen);
  133.          } else {
  134.             BoxCell(wrp,SelectX,SelectY,Pen);
  135.             if (DBufMode) BoxCell(rp,SelectX,SelectY,Pen);
  136.             SetCell(NewGen,x,y,0);
  137.          }
  138.       }
  139.    }
  140. }
  141.  
  142.  
  143. /*
  144.  *  CancelSelect()
  145.  *
  146.  *  If we are moving or copying, cancel the move or copy.
  147.  *  Otherwise (we are in Select mode),
  148.  *    Stop getting mouse moves, and don't buffer moves
  149.  *    Put the SELECT button back to normal
  150.  *    Put the pointer back to the drawing color
  151.  *    Refresh any selected cells to their normal colors
  152.  */
  153.  
  154. void CancelSelect()
  155. {
  156.    switch(MouseMoveType)
  157.    {
  158.       case MM_MOVE:
  159.       case MM_COPY:
  160.          CancelMoveCopy(MouseMoveType);
  161.          break;
  162.  
  163.       default:
  164.          StopMouseMoves(); MouseMoveType = MM_NONE; BufferMouse = FALSE;
  165.          InvertGadget(&cGadget[ID_SELECT]); SelectType = SEL_NONE;
  166.          SetPointerColor(PenInUse);
  167.          RefreshSelect(CurGen);
  168.          break;
  169.    }
  170. }
  171.  
  172.  
  173. /*
  174.  *  StartSelectBox()
  175.  *
  176.  *  If the mouse event is within the grid area
  177.  *    Buffer mouse moves, and start getting mouse events
  178.  *    Set the select type to BOX type
  179.  *    record the initial position and size of the box,
  180.  *    Begin inverting the box
  181.  */
  182.  
  183. static void StartSelectBox(MouseX,MouseY)
  184. short MouseX,MouseY;
  185. {
  186.    short x,y;
  187.  
  188.    if (InBoard(MouseX,MouseY,&x,&y))
  189.    {
  190.       BufferMouse = TRUE; StartMouseMoves();
  191.       SelectType = SEL_BOX;
  192.       BoxX = x; BoxY = y; BoxW = 1; BoxH = 1;
  193.       SelectX = x; SelectY = y;
  194.       InvertBox();
  195.    }
  196. }
  197.  
  198. /*
  199.  *  FinishSelectBox()
  200.  *
  201.  *  Stop getting mouse moves, and remove the box outline
  202.  *  For each cell in the box
  203.  *    If the cell is not a blank cell, or we are going with ALL cells
  204.  *      If we are clearing from the selection
  205.  *        Clear the cell frlom the selection and put back its normal colors
  206.  *      Otherwise
  207.  *        Set the select array to the selected color
  208.  *        Mark the cell as in the selection
  209.  * Update the screen once all the changes have been made
  210.  */
  211.  
  212. static void FinishSelectBox(MouseX,MouseY,theMessage)
  213. short MouseX,MouseY;
  214. struct IntuiMessage *theMessage;
  215. {
  216.    register short X,Y;
  217.    register short i;
  218.    int DoAll = (theMessage->Qualifier & SHIFTKEYS);
  219.    int ClearCells = (theMessage->Qualifier & ALTKEYS);
  220.  
  221.    StopMouseMoves(); BufferMouse = FALSE;
  222.    InvertBox();
  223.    SelectType = SEL_WAIT;
  224.  
  225.    for (Y=BoxY; Y<BoxY+BoxH; Y++)
  226.    {
  227.       for (X=BoxX, i=GridX+X+MAXGRIDW*(GridY+Y); X<BoxX+BoxW; X++,i++)
  228.       {
  229.          if (CurGen[i] != BLANK || DoAll)
  230.          {
  231.             if (ClearCells)
  232.             {
  233.                NewGen[i] = 0;
  234.                BoxCell(rp,X,Y,CurGen[i]);
  235.             } else {
  236.                NewGen[i] = CurGen[i];
  237.                BoxCell(rp,X,Y,MOVEPEN);
  238.             }
  239.          }
  240.       }
  241.    }
  242.    UpdateScreen();
  243. }
  244.  
  245.  
  246. /*
  247.  *  SizeSelectBox()
  248.  *
  249.  *  Find the closest cell to the mouse position
  250.  *  If the new position is not the same as the old one
  251.  *    Remove the old box outline
  252.  *    Update the box size
  253.  *    Draw the new box outline
  254.  */
  255.  
  256. static void SizeSelectBox(MouseX,MouseY)
  257. short MouseX,MouseY;
  258. {
  259.    short x,y;
  260.  
  261.    RestrictToBoard(MouseX,MouseY,&x,&y);
  262.    if (x != BoxX + BoxW - 1 || y != BoxY + BoxH - 1)
  263.    {
  264.       InvertBox();
  265.       if (x < BoxX) BoxX = x;
  266.       if (y < BoxY) BoxY = y;
  267.       BoxW = x - BoxX + 1;
  268.       BoxH = y - BoxY + 1;
  269.       InvertBox();
  270.    }
  271. }
  272.  
  273.  
  274. /*
  275.  *  MoveSelectBox()
  276.  *
  277.  *  Find the closes cell to the mouse position
  278.  *  If it is not the same as the old position
  279.  *    Calculate the new box position
  280.  *    If the position has changed
  281.  *      Remove the old box outline, move the box, and draw the new outline
  282.  */
  283.  
  284. static void MoveSelectBox(MouseX,MouseY)
  285. short MouseX,MouseY;
  286. {
  287.    short x,y;
  288.  
  289.    RestrictToBoard(MouseX,MouseY,&x,&y);
  290.    if (x != BoxX + BoxW - 1 || y != BoxY + BoxH - 1)
  291.    {
  292.       x = x - BoxW + 1;
  293.       y = y - BoxH + 1;
  294.       if (x < 0) x = 0;
  295.       if (y < 0) y = 0;
  296.       if (x != BoxX || y != BoxY)
  297.       {
  298.          InvertBox();
  299.          BoxX = x; BoxY = y;
  300.          InvertBox();
  301.       }
  302.    }
  303. }
  304.  
  305.  
  306. /*
  307.  *  DoSelectMove()
  308.  *
  309.  *  If we are dragging a box, size the box
  310.  *  If we are selecting cells, select them
  311.  *  If we are repositioning the box, do so
  312.  */
  313.  
  314. void DoSelectMove(MouseX,MouseY,theMessage)
  315. {
  316.    switch(SelectType)
  317.    {
  318.       case SEL_BOX:
  319.          SizeSelectBox(MouseX,MouseY);
  320.          break;
  321.  
  322.       case SEL_CELLS:
  323.          SelectMouseCell(MouseX,MouseY,FALSE);
  324.          break;
  325.  
  326.       case SEL_REPOSITION:
  327.          MoveSelectBox(MouseX,MouseY);
  328.          break;
  329.    }
  330. }
  331.  
  332.  
  333. /*
  334.  *  DoSelectButton()
  335.  *
  336.  *  For a SELECTDOWN:
  337.  *    if we aren't doing something already, start a selection box
  338.  *
  339.  *  For a SELECTUP:
  340.  *    If we have a select box in action, finish it
  341.  *
  342.  *  For a MENUDOWN:
  343.  *    If we are not doing anything else:
  344.  *      Start getting mouse moves,
  345.  *      Select the cell at the current position, and record that position
  346.  *    If we are dragging a select box, start repositioning it
  347.  *
  348.  *  For a MENUUP:
  349.  *    If we are selecting cells,
  350.  *      stop getting mouse moves and go back to waiting
  351.  *    If we are repositioning the selection box:
  352.  *      go back to resizing the box
  353.  */
  354.  
  355. void DoSelectButton(Code,MouseX,MouseY,theMessage)
  356. USHORT Code;
  357. short MouseX,MouseY;
  358. struct IntuiMessage *theMessage;
  359. {
  360.    switch(Code)
  361.    {
  362.       case SELECTDOWN:
  363.          if (SelectType == SEL_WAIT) StartSelectBox(MouseX,MouseY);
  364.          break;
  365.  
  366.       case SELECTUP:
  367.          if (SelectType == SEL_BOX || SelectType == SEL_REPOSITION)
  368.              FinishSelectBox(MouseX,MouseY,theMessage);
  369.          break;
  370.  
  371.       case MENUDOWN:
  372.          switch(SelectType)
  373.          {
  374.             case SEL_WAIT:
  375.                StartMouseMoves();
  376.                SelectMouseCell(MouseX,MouseY,TRUE);
  377.                SelectType = SEL_CELLS;
  378.                SelectX = GridW; SelectY = GridH;
  379.                break;
  380.  
  381.             case SEL_BOX:
  382.                SelectType = SEL_REPOSITION;
  383.                MoveSelectBox(MouseX,MouseY);
  384.                break;
  385.          }
  386.          break;
  387.  
  388.       case MENUUP:
  389.          switch(SelectType)
  390.          {
  391.             case SEL_CELLS:
  392.                StopMouseMoves();
  393.                SelectType = SEL_WAIT;
  394.                break;
  395.  
  396.             case SEL_REPOSITION:
  397.                SelectType = SEL_BOX;
  398.                SizeSelectBox(MouseX,MouseY);
  399.                break;
  400.          }
  401.          break;
  402.    }
  403. }
  404.  
  405.  
  406. /*
  407.  *  DoSelect()
  408.  *
  409.  *  If a selection is already in progress, cancel the selection.
  410.  *  If a move or copy is in progress cancel it, then start a new selection
  411.  *  Otherwise
  412.  *    Put the pointer color back to normal and invert the SELECT button
  413.  *    Set the flags to Select mode
  414.  *    Clear the select grid to zero, and clear the offset counter
  415.  */
  416.  
  417. void DoSelect()
  418. {
  419.    switch(MouseMoveType)
  420.    {
  421.       case MM_SELECT:
  422.          CancelSelect();
  423.          break;
  424.  
  425.       case MM_MOVE:
  426.       case MM_COPY:
  427.          CancelSelect();
  428.       default:
  429.          RestorePointerColor();
  430.          InvertGadget(&cGadget[ID_SELECT]);
  431.          SelectType = SEL_WAIT; MouseMoveType = MM_SELECT;
  432.          ZeroGrid(NewGen); OffMC = 0;
  433.          break;
  434.    }
  435. }
  436.