home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d502 / cells.lha / CELLS / CELLSSource.lzh / cDoMouse.c < prev    next >
C/C++ Source or Header  |  1991-04-20  |  10KB  |  396 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:  cDoMouse.c       Handles Mouse Move and Button events
  12.  */
  13.  
  14.  
  15. #include "cGadget.h"
  16.  
  17. int MouseMoveType = MM_NONE;            /* type of mouse move expected */
  18. int ColorInUse    = BRDR_WIREC;         /* what color is in use */
  19. int PenInUse      = WIRE;               /* what state is to be written */
  20.  
  21. static int StartingColor;               /* variables for right-mouse effect */
  22. static int ColorCount;
  23. static short ColorX,ColorY;
  24. static int CurrentColor;
  25.  
  26. static int OldSecs,OldMics;             /* double click times */
  27.  
  28.  
  29. /*
  30.  *  StartMouseMoves()
  31.  *
  32.  *   Start reporting mouse moves.  They  will be handled according to the
  33.  *   MouseMoveType variable.
  34.  */
  35.  
  36. void StartMouseMoves()
  37. {
  38.    ModifyIDCMP(myWindow,myWindow->IDCMPFlags | MOUSEMOVE);
  39. }
  40.  
  41.  
  42. /*
  43.  *  StopMouseMoves()
  44.  *
  45.  *  Stop reporting mouse move events.
  46.  */
  47.  
  48. void StopMouseMoves()
  49. {
  50.    ModifyIDCMP(myWindow,myWindow->IDCMPFlags & ~MOUSEMOVE);   
  51. }
  52.  
  53.  
  54. /*
  55.  *  InBoard()
  56.  *
  57.  *  Returns TRUE if the mouse position is inside the active grid area, and
  58.  *  calculates the grid position (relative to GridX and GridY) of the mouse.
  59.  */
  60.  
  61. int InBoard(Mx,My,x,y)
  62. short Mx,My;
  63. short *x,*y;
  64. {
  65.    int Inside = FALSE;
  66.  
  67.    if (Mx >= BoardX && Mx <= BoardW &&
  68.        My >= BoardY && My <= BoardH)   
  69.    {
  70.       Inside = TRUE;
  71.       if (x) *x = (Mx - BoardX) / CellSize;
  72.       if (y) *y = (My - BoardY) / CellSize;
  73.    }
  74.    return(Inside);
  75. }
  76.  
  77.  
  78. /*
  79.  *  RestrictToBoard()
  80.  *
  81.  *  Calculate the nearest grid cell to the mouse position, not going
  82.  *  outside of the active screen area.
  83.  */
  84.  
  85. void RestrictToBoard(Mx,My,x,y)
  86. short Mx,My;
  87. short *x,*y;
  88. {
  89.    if (Mx < BoardX) Mx = BoardX; else if (Mx > BoardW) Mx = BoardW;
  90.    if (My < BoardY) My = BoardY; else if (My > BoardH) My = BoardH;
  91.    *x = (Mx - BoardX) / CellSize;
  92.    *y = (My - BoardY) / CellSize;
  93. }
  94.  
  95.  
  96. /*
  97.  *  SetPenColor()
  98.  *
  99.  *  If the pen color is not alread the active color,
  100.  *    Reset the current color's border pen
  101.  *    Calculate the new color and pen
  102.  *    Highlight the new color's gadget
  103.  *    Relink the color gadgets so that the selected one is drawn last
  104.  *    Redraw the gadgets (i.e., change the highlighted color)
  105.  *    Set the mouse pointer to the selected color
  106.  */
  107.  
  108. void SetPenColor(theID)
  109. int theID;
  110. {
  111.    short i,j;
  112.  
  113.    if (theID != ColorInUse)
  114.    {
  115.       cBorder[ColorInUse].FrontPen = BOXPEN;
  116.       ColorInUse = theID - ID_BLANKC + BRDR_BLANKC;
  117.       PenInUse = ((struct Image *)(cGadget[theID].GadgetRender))->PlaneOnOff;
  118.       cBorder[ColorInUse].FrontPen = HIGHPEN;
  119.       for (i=BRDR_BLANKC,j=i-1; i<=BRDR_HEADC; i++)
  120.       {
  121.          if (i != ColorInUse)
  122.          {
  123.             cBorder[j].NextBorder = &cBorder[i];
  124.             j = i;
  125.          }
  126.       }
  127.       cBorder[j].NextBorder = &cBorder[ColorInUse];
  128.       cBorder[ColorInUse].NextBorder = NULL;
  129.       DrawBorder(wrp,cBorder[BRDR_BLANKC-1].NextBorder,0,0);
  130.       SetPointerColor(PenInUse);
  131.    }
  132. }
  133.  
  134.  
  135. /*
  136.  *  ColorMouseCell()
  137.  *
  138.  *  If the mouse is within the active grid area,
  139.  *    calculate the screen position of the cell
  140.  *    if it is not the last cell colored,
  141.  *      record it as the last one colored,
  142.  *      if this is the second cell colored with an electron color,
  143.  *        change the electron color temporarily
  144.  *      set the pen color and drawing mode
  145.  *      fill the grid cell with the color
  146.  *      If double buffer mode is on, update BOTH buffers
  147.  *      Set the color of the cell in the grid array
  148.  *      record that changes have been made.
  149.  */
  150.  
  151. void ColorMouseCell(MouseX,MouseY,Pen)
  152. short MouseX,MouseY;
  153. int Pen;
  154. {
  155.    short X,Y,x,y;
  156.  
  157.    if (InBoard(MouseX,MouseY,&x,&y))
  158.    {
  159.       X = x * CellSize + BoardX + 1;
  160.       Y = y * CellSize + BoardY + 1;
  161.       if (X != ColorX || Y != ColorY || Pen != CurrentColor)
  162.       {
  163.          ColorX = X; ColorY = Y; CurrentColor = Pen;
  164.          if (ColorCount < 2)
  165.          {
  166.             ColorCount++;
  167.             if (ColorCount == 2 && (Pen == TAIL || Pen == HEAD))
  168.                Pen = (HEAD + TAIL) - Pen;
  169.          }
  170.          SetAPen(wrp,Pen);
  171.          SetDrMd(wrp,JAM1);
  172.          RectFill(wrp,X,Y,X+CellSize-2,Y+CellSize-2);
  173.          if (DBufMode)
  174.          {
  175.             SetAPen(rp,Pen); SetDrMd(rp,JAM1);
  176.             RectFill( rp,X,Y,X+CellSize-2,Y+CellSize-2);
  177.          }
  178.          SetCell(CurGen,x+GridX,y+GridY,Pen);
  179.          Changed = TRUE;
  180.       }
  181.    }
  182. }
  183.  
  184.  
  185. /*
  186.  *  ColorScreenCell()
  187.  *
  188.  *  If the specified cell is within the acrive area, calculate the screen
  189.  *  position of the cell and color it in.
  190.  */
  191.  
  192. void ColorScreenCell(X,Y,Pen)
  193. short X,Y;
  194. int Pen;
  195. {
  196.    int x,y;
  197.        
  198.    if (X >= 0 && X < GridW && Y >= 0 && Y < GridH)
  199.    {
  200.       x = BoardX + X * CellSize + 1,
  201.       y = BoardY + Y * CellSize + 1;
  202.       SetAPen(rp,Pen);
  203.       SetDrMd(rp,JAM1);
  204.       RectFill(rp,x,y,x+CellSize-2,y+CellSize-2);
  205.    }
  206. }
  207.  
  208.  
  209. /*
  210.  *  Array to determine what color to change use when the right mouse button
  211.  *  is clicked
  212.  */
  213.  
  214. static UWORD PenChange[4][4] =
  215. {
  216.    {ID_WIREC, ID_BLANKC, ID_HEADC, ID_TAILC},   /* Click w/o SelectDown */
  217.    {ID_HEADC, ID_TAILC, ID_WIREC, ID_BLANKC},   /* Double-Click w/o Select */
  218.    {ID_WIREC, ID_BLANKC, ID_WIREC, ID_WIREC},   /* Click with SelectDown */
  219.    {ID_TAILC, ID_HEADC, ID_BLANKC, ID_BLANKC}   /* Double-Click with Select */
  220. };
  221.  
  222.  
  223. /*
  224.  *  ChangePenColor()
  225.  *
  226.  *  Offset the index value if the left button is held down.
  227.  *  If the click is a double click, update the array index, and
  228.  *    clear the double click counter, otherwise record the double click values.
  229.  *  Set the pen to the proper value, according to the array.
  230.  */
  231.  
  232. static void ChangePenColor(Seconds,Micros,theMessage)
  233. int Seconds,Micros;
  234. struct IntuiMessage *theMessage;
  235. {
  236.    int i = 0;
  237.  
  238.    if (theMessage->Qualifier & IEQUALIFIER_LEFTBUTTON) i += 2;
  239.    if (DoubleClick(OldSecs,OldMics,Seconds,Micros))
  240.    {
  241.       i++;
  242.       OldSecs = OldMics = 0;
  243.    } else {
  244.       OldSecs = Seconds;
  245.       OldMics = Micros;
  246.    }
  247.    SetPenColor(PenChange[i][ColorInUse-BRDR_BLANKC]);
  248. }
  249.  
  250.  
  251. /*
  252.  *  DoMouseMove()
  253.  *
  254.  *  If a slider is active
  255.  *    do the action for the proper slider,
  256.  *  Otherwise,
  257.  *    In DRAW mode:
  258.  *      If the left button is down, fill the proper cell.
  259.  *
  260.  *    In SELECT mode:
  261.  *      Do the selection routine.
  262.  *
  263.  *    In MOVE or COPY mode:
  264.  *      Do the move or copy routine.
  265.  */
  266.  
  267. void DoMouseMove(MouseX,MouseY,theMessage)
  268. short MouseX,MouseY;
  269. struct IntuiMessage *theMessage;
  270. {
  271.    if (SliderActive)
  272.    {
  273.       if (cGadget[ID_SLIDEH].Flags & SELECTED) DoSlideH();
  274.       else if (cGadget[ID_SLIDEV].Flags & SELECTED) DoSlideV();
  275.    } else {
  276.       switch (MouseMoveType)
  277.       {
  278.          case MM_DRAW:
  279.             if (theMessage->Qualifier & IEQUALIFIER_LEFTBUTTON)
  280.                ColorMouseCell(MouseX,MouseY,PenInUse);
  281.             break;
  282.  
  283.          case MM_SELECT:
  284.             DoSelectMove(MouseX,MouseY,theMessage);
  285.             break;
  286.  
  287.          case MM_MOVE:
  288.          case MM_COPY:
  289.             DoCopyMove(MouseX,MouseY);
  290.             break;
  291.       }
  292.    }
  293. }
  294.  
  295.  
  296. /*
  297.  *  DoDrawButton()
  298.  *
  299.  *  For a SELECTDOWN:
  300.  *    if the circuit is not running and if the mouse button is within the grid,
  301.  *      record the current grid for UNDO
  302.  *      record the starting color and clear the cells-colored count.
  303.  *      get mouse move reports in DRAW mode.
  304.  *      color the selected cell
  305.  *
  306.  *  For a SELECTUP:
  307.  *    if the circuit is not running,
  308.  *      clear the last-colored variables, and stop the mouse move reports
  309.  *
  310.  *  For a MENUDOWN:
  311.  *    Choose the proper new color
  312.  *    clear the cells-colored count.
  313.  *    If we're currently drawing (i.e., the left mouse button is down)
  314.  *      change the color of the current cell.
  315.  *
  316.  *  For a MENUUP:
  317.  *    If we're in draw mode,
  318.  *      reset the pen color to it original value.
  319.  */
  320.  
  321. void DoDrawButton(Code,MouseX,MouseY,theMessage)
  322. USHORT Code;
  323. short MouseX,MouseY;
  324. struct IntuiMessage *theMessage;
  325. {
  326.    switch(Code)
  327.    {
  328.       case SELECTDOWN:
  329.          if (!Running)
  330.          {
  331.             if (InBoard(MouseX,MouseY,NULL,NULL))
  332.             {
  333.                StartingColor = ColorInUse; ColorCount = 0;
  334.                StartMouseMoves(); MouseMoveType = MM_DRAW;
  335.                CopyGrid(CurGen,UndoArray);
  336.                ColorMouseCell(MouseX,MouseY,PenInUse);
  337.             }
  338.          }
  339.          break;
  340.  
  341.       case SELECTUP:
  342.          if (!Running)
  343.          {
  344.             ColorX = GridW; ColorY = GridH; CurrentColor = 0;
  345.             StopMouseMoves(); MouseMoveType = MM_NONE;
  346.          }
  347.          break;
  348.  
  349.       case MENUDOWN:
  350.          ChangePenColor(theMessage->Seconds,theMessage->Micros,theMessage);
  351.          ColorCount = 0;
  352.          if (MouseMoveType == MM_DRAW)
  353.             ColorMouseCell(MouseX,MouseY,PenInUse);
  354.          break;
  355.  
  356.       case MENUUP:
  357.          if (MouseMoveType == MM_DRAW)
  358.          {
  359.             SetPenColor(StartingColor - BRDR_BLANKC + ID_BLANKC);
  360.             CurrentColor = PenInUse; ColorCount = 0;
  361.          }
  362.          break;
  363.    }
  364. }
  365.  
  366.  
  367. /*
  368.  *  DoMouseButton()
  369.  *
  370.  *  Call the proper mouse button routine depending on the type of mouse
  371.  *  move we are expecting.
  372.  */
  373.  
  374. void DoMouseButton(Code,MouseX,MouseY,theMessage)
  375. USHORT Code;
  376. short MouseX,MouseY;
  377. struct IntuiMessage *theMessage;
  378. {
  379.    switch (MouseMoveType)
  380.    {
  381.       case MM_NONE:
  382.       case MM_DRAW:
  383.          DoDrawButton(Code,MouseX,MouseY,theMessage);
  384.          break;
  385.  
  386.       case MM_SELECT:
  387.          DoSelectButton(Code,MouseX,MouseY,theMessage);
  388.          break;
  389.  
  390.       case MM_MOVE:
  391.       case MM_COPY:
  392.          DoCopyButton(Code,MouseX,MouseY,theMessage);
  393.          break;
  394.    }
  395. }
  396.