home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d502 / cells.lha / CELLS / CELLSSource.lzh / cMove.c < prev    next >
C/C++ Source or Header  |  1991-04-20  |  8KB  |  330 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:  cMove.c              Handles MOVE and COPY commands.
  12.  */
  13.  
  14.  
  15. #include "cGadget.h"
  16.  
  17. short OffMC;                    /* Offset in state arrays of new position */
  18. static short OffX,OffY;         /* grid offsets of new cell positions */
  19. static short BaseX,BaseY;       /* original (base) position of offsets */
  20. static short BoundX,BoundY,BoundW,BoundH;
  21.  
  22. extern ULONG Shifted;
  23.  
  24.  
  25. /*
  26.  *  CancelMoveCopy()
  27.  *
  28.  *  Cancel mouse moves, and stop buffering the mouse
  29.  *  Put the MOVE or COPY button back to normal, and cancel any selection
  30.  *  Put the gadgets to their proper shifted positions
  31.  *  Restore the pointer to the drawing color
  32.  *  Refresh the selected cells back to their original values
  33.  *  If we were moving cells,
  34.  *    replace them in their original positions
  35.  *    and redraw them on the screen
  36.  */
  37.  
  38. void CancelMoveCopy(ID)
  39. int ID;
  40. {
  41.    StopMouseMoves(); MouseMoveType = MM_NONE; BufferMouse = FALSE;
  42.    InvertGadget(&cGadget[ID_MOVE]); SelectType = SEL_NONE;
  43.    if (Shifted) ShowShiftedGadgets(); else ShowNormalGadgets();
  44.    SetPointerColor(PenInUse);
  45.    RefreshSelect(CurGen);
  46.    if (ID == MM_MOVE)
  47.    {
  48.       ReplaceGrid(NewGen,CurGen); OffMC = 0;
  49.       RefreshSelect(CurGen);
  50.    }
  51. }
  52.  
  53.  
  54. /*
  55.  *  DoMoveCopy()
  56.  *
  57.  *  If the mode is currently SELECT mode:
  58.  *    put the SELECT button back to normal and invert the MOVE or COPY button
  59.  *    set up the UNDO array
  60.  *    set the mouse move type to the specified type (MOVE or COPY)
  61.  *    clear the offset values
  62.  *    If we are movinf cells, clear the selected cells
  63.  *    refresh the selected cells (using the new mode)
  64.  *    get the bounds for the selected cells
  65.  *
  66.  *  Otherwise:
  67.  *    cancel the current MOVE or COPY
  68.  */
  69.  
  70. void DoMoveCopy(ID)
  71. int ID;
  72. {
  73.    switch (MouseMoveType)
  74.    {
  75.       case MM_SELECT:
  76.          InvertGadget(&cGadget[ID_SELECT]);
  77.          InvertGadget(&cGadget[ID_MOVE]); 
  78.          CopyGrid(CurGen,UndoArray);
  79.          MouseMoveType = ID;
  80.          OffX = OffY = OffMC = 0; BaseX = BaseY = 0;
  81.          if (ID == MM_MOVE) RemoveGrid(NewGen,CurGen);
  82.          RefreshSelect(CurGen);
  83.          GetBounds(NewGen,&BoundX,&BoundY,&BoundW,&BoundH,0);
  84.          break;
  85.  
  86.       default:
  87.          CancelSelect();
  88.          break;
  89.    }
  90. }
  91.  
  92.  
  93. /*
  94.  *  StartMoveCopy()
  95.  *
  96.  *  If the mouse is within the grid area
  97.  *    If the cell where the mouse was pressed is a selected cell
  98.  *      start buffering moves, and start getting mouse moves
  99.  *      set the select type
  100.  *      record the base postition for the move
  101.  *      refresh the cells in the new mode
  102.  */
  103.  
  104. static void StartMoveCopy(MouseX,MouseY)
  105. short MouseX,MouseY;
  106. {
  107.    short x,y;
  108.  
  109.    if (InBoard(MouseX,MouseY,&x,&y))
  110.    {
  111.       if (CellColor(NewGen,x+GridX-OffX,y+GridY-OffY))
  112.       {
  113.          BufferMouse = TRUE;
  114.          StartMouseMoves();
  115.          SelectType = (MouseMoveType == MM_MOVE)? SEL_MOVE: SEL_COPY;
  116.          BaseX = x - OffX; BaseY = y - OffY;
  117.          RefreshSelect(CurGen);
  118.       }
  119.    }
  120. }
  121.  
  122.  
  123. /*
  124.  *  FinishMoveCopy()
  125.  *
  126.  *  Stop getting mouse moves and stop buffering
  127.  *  go back to waiting for somthing to happen
  128.  *  refresh the selected cells in the new mode
  129.  */
  130.  
  131. static void FinishMoveCopy(MouseX,MouseY)
  132. short MouseX,MouseY;
  133. {
  134.    StopMouseMoves(); BufferMouse = FALSE;
  135.    SelectType = SEL_WAIT;
  136.    RefreshSelect(CurGen);
  137. }
  138.  
  139.  
  140. /*
  141.  *  CellSelected()
  142.  *
  143.  *  offset the cell index to the selected cell's current location
  144.  *  If the index is within the array, then return the cell state
  145.  *  otherwise return 0
  146.  */
  147.  
  148. int CellSelected(i)
  149. short i;
  150. {
  151.    register int Selected;
  152.  
  153.    i += OffMC;
  154.    if (i >= 0 && i < ARRAYSIZE) Selected = NewGen[i]; else Selected = FALSE;
  155.    return(Selected);
  156. }
  157.  
  158.  
  159. /*
  160.  *  CopySelect()
  161.  *
  162.  *  Record that changes have been made
  163.  *  For each cell in the selection array,
  164.  *    if the index is valid and the cell is selected (i.e., being moved or
  165.  *    copied), then copy the value of the cell into the current grid
  166.  */
  167.  
  168. static void CopySelect()
  169. {
  170.    register short i,j;
  171.    
  172.    Changed = TRUE;
  173.    for (i=0,j=OffMC; i<ARRAYSIZE && j<ARRAYSIZE; i++,j++)
  174.       if (j >= 0 && NewGen[j]) CurGen[i] = NewGen[j];
  175. }
  176.  
  177.  
  178. /*
  179.  *  CalcBounds()
  180.  *
  181.  *  Compute the destination cell positions of the bounding box of the
  182.  *  selected cells, within the screen grid area.  Clip the boundary to 
  183.  *  the active grid.
  184.  */
  185.  
  186. static void CalcBounds(NewOffX,NewOffY,x,y,w,h)
  187. short NewOffX,NewOffY;
  188. short *x,*y,*w,*h;
  189. {
  190.    if (NewOffX < OffX)
  191.    {
  192.       *x = BoundX + NewOffX;
  193.       *w = BoundX + BoundW + OffX;
  194.    } else {
  195.       *x = BoundX + OffX;
  196.       *w = BoundX + BoundW + NewOffX;
  197.    }
  198.    if (NewOffY < OffY)
  199.    {
  200.       *y = BoundY + NewOffY;
  201.       *h = BoundY + BoundH + OffY;
  202.    } else {
  203.       *y = BoundY + OffY;
  204.       *h = BoundY + BoundH + NewOffY;
  205.    }
  206.  
  207.    if (*x < GridX) *x = GridX;
  208.    if (*y < GridY) *y = GridY;
  209.    if (*w > GridX + GridW) *w = GridX + GridW;
  210.    if (*h > GridY + GridH) *h = GridY + GridH;
  211. }
  212.  
  213.  
  214. /*
  215.  *  MoveSelect()
  216.  *
  217.  *  Calculate the new bounding box positions and size
  218.  *  Calculate the new index offset into the state array
  219.  *  For each cell in the bounded part of the grid
  220.  *    Get the state of the cell that used to be at the current position
  221.  *    and the state of the cell now at the current position
  222.  *    If the cell was selected before but is not any longer,
  223.  *      replace the original cell color
  224.  *    otherwise if the cell was not selected before but is now,
  225.  *      color it the selection color
  226.  *  Update the screen (for double buffered node)
  227.  */
  228.  
  229. static void MoveSelect(NewOffX,NewOffY)
  230. short NewOffX,NewOffY;
  231. {
  232.    short x,y,w,h;
  233.    short NewOffMC;
  234.    register short X,Y;
  235.    register short i;
  236.    register int Pen1,Pen2;
  237.    int SelectPen = (SelectType == SEL_WAIT)? SELECTPEN: MOVEPEN;
  238.   
  239.    CalcBounds(NewOffX,NewOffY,&x,&y,&w,&h);
  240.    NewOffMC = -(NewOffX + MAXGRIDW * NewOffY);
  241.  
  242.    for (Y=y; Y<h; Y++)
  243.    {
  244.       for (X=x,i=X+MAXGRIDW*Y; X<w; X++,i++)
  245.       {
  246.          if (i+OffMC >= 0 && i+OffMC < ARRAYSIZE)
  247.             Pen1 = NewGen[i+OffMC]; else Pen1 = 0;
  248.          if (i+NewOffMC >= 0 && i+NewOffMC < ARRAYSIZE)
  249.             Pen2 = NewGen[i+NewOffMC]; else Pen2 = 0;
  250.          if (Pen1 && Pen2 == 0)
  251.             ColorScreenCell(X-GridX,Y-GridY,CurGen[i]);
  252.          else if (Pen1 == 0 && Pen2)
  253.             ColorScreenCell(X-GridX,Y-GridY,SelectPen);
  254.       }
  255.    }
  256.    UpdateScreen();
  257. }
  258.  
  259.  
  260. /*
  261.  *  DoCopyMove()
  262.  *
  263.  *  Find the closest board position to the current mouse position
  264.  *  Get the offsets from the base position
  265.  *  If the offsets have changed,
  266.  *    move the selection to the new location
  267.  *    change the offset values
  268.  */
  269.  
  270. void DoCopyMove(MouseX,MouseY)
  271. short MouseX,MouseY;
  272. {
  273.    short dx,dy;
  274.    
  275.    RestrictToBoard(MouseX,MouseY,&dx,&dy);
  276.    dx -= BaseX; dy -= BaseY;
  277.    if (dx != OffX || dy != OffY)
  278.    {
  279.       MoveSelect(dx,dy);
  280.       OffX = dx; OffY = dy;
  281.       OffMC = -(dx + MAXGRIDW * dy);
  282.    }
  283. }
  284.  
  285.  
  286. /*
  287.  *  DoCopyButton()
  288.  *
  289.  *  Do the right thing for each type of button event:
  290.  *
  291.  *  SELECTDOWN:
  292.  *    If we are not already moving or copying, start moving
  293.  *
  294.  *  SELECTUP:
  295.  *    Stop moving for now
  296.  *
  297.  *  MENUDOWN:
  298.  *    Place a copy of the selection at the current location
  299.  *
  300.  *  MENUUP:
  301.  *    If the left button is not down then we are done moving, so
  302.  *      cancel the move or copy (without replacing the cells)
  303.  */
  304.  
  305. void DoCopyButton(Code,MouseX,MouseY,theMessage)
  306. USHORT Code;
  307. short MouseX,MouseY;
  308. struct IntuiMessage *theMessage;
  309. {
  310.    switch(Code)
  311.    {
  312.       case SELECTDOWN:
  313.          if (SelectType == SEL_WAIT) StartMoveCopy(MouseX,MouseY);
  314.          break;
  315.  
  316.       case SELECTUP:
  317.          FinishMoveCopy(MouseX,MouseY);
  318.          break;
  319.  
  320.       case MENUDOWN:
  321.          CopySelect();
  322.          break;
  323.          
  324.       case MENUUP:
  325.          if ((theMessage->Qualifier & IEQUALIFIER_LEFTBUTTON) == 0)
  326.             CancelMoveCopy(MM_COPY);
  327.          break;
  328.    }
  329. }
  330.