 /*  Sprite Wizard  -  By David A. Visage  */

#include <stdio.h>
#include <exec/types.h>
#include <graphics/sprite.h>
#include <intuition/intuition.h>

/*  Various defines  */
#define VERSION        0
#define GADGET_FLAGS   (GADGETDOWN | GADGETUP)
#define IDCMP_FLAGS    (CLOSEWINDOW | MOUSEBUTTONS | MENUPICK | GADGET_FLAGS)
#define ALL_BITS  0xffff

/*  Box definitions  */
#define MAX_BOXES   (16 * 16)
#define BOX_WIDTH   15
#define BOX_HEIGHT  10

/*  Grid definitions  */
#define GRID_WIDTH     (16 * BOX_WIDTH)
#define GRID_HEIGHT    (16 * BOX_HEIGHT)

/*  Define color registers  */
#define COLOR00 0
#define COLOR01 1
#define COLOR02 2
#define COLOR03 3
#define COLOR04 4
#define COLOR05 5
#define COLOR06 6
#define COLOR07 7
#define COLOR16 16
#define COLOR17 17
#define COLOR18 18
#define COLOR19 19
#define COLOR20 20
#define COLOR21 21
#define COLOR22 22
#define COLOR23 23

/*  Define screen maximums  */
#define MAX_DEPTH    3
#define MAX_WIDTH    640
#define MAX_HEIGHT   200
#define MAX_STR_LEN  256              /*  Maximum input string length  */

/*  Defines for low and high sprites  */
#define LOW_SPRITE   0
#define HIGH_SPRITE  25

/*  Sprite definitions  */
#define MAX_SPRITES  26
#define SPRITE_SIZE  36                   /*  In words  */

#define SPRITE02     2                    /*  Edit sprite  */

/*  Define return value of all functions  */
extern struct Window *OpenWindow();
extern struct Screen *OpenScreen();
extern struct Library *OpenLibrary();
extern struct View *ViewAddress();
extern struct Message *GetMsg();
extern PLANEPTR AllocRaster();
extern UWORD GetRGB4();
extern UWORD PackRGB();
extern LONG GetPropVal();
extern BOOL CheckSequence();
extern BOOL GetRowCol(),GetString();
extern BOOL LoadBinary(),SaveBinary();
extern BOOL SaveCSource(),SaveAsmSource();

/*  Global library base pointers  */
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;

/*  Various  structure declares  */
struct NewWindow MyWindow;
struct NewScreen MyScreen;
struct Preferences MyPrefs;
struct RastPort HorizRast,VertRast,GRast;
struct BitMap HorizBitMap,VertBitMap,GBitMap;
struct SimpleSprite MySprite;

/*  Lots of pointer declares  */
struct View *V;
struct RastPort *Rp;
struct ViewPort *Vp;
struct BitMap *Bm;
struct Gadget *GadPtr;
struct Window *WindowPtr;
struct Screen *ScreenPtr;
struct IntuiMessage *MessagePtr;

/*  Declares for each box image  */
struct Rectangle Boxes[MAX_BOXES];
LONG MinX,MinY,MaxX,MaxY;

/*  Used for gadget borders and DrawGrid() function  */
struct Points
 {
 SHORT X1,Y1;
 SHORT X2,Y2;
 SHORT X3,Y3;
 SHORT X4,Y4;
 SHORT X5,Y5;
 };

/*  Main Sprite structure  */
struct Sprite
 {
 UWORD SpriteData [SPRITE_SIZE];
 UWORD SprColor1,SprColor2,SprColor3;
 UWORD SpriteNumber;
 };

/*  Array to hold sprite information  */
struct Sprite SpriteArray [MAX_SPRITES];

struct Sprite TempSprite;            /*  For Get() and Put() functions  */

UWORD NullImage[SPRITE_SIZE];        /*  Disable image during request   */

UWORD AnimData[SPRITE_SIZE];         /*  For Sprite animation data      */

UBYTE AnimBuffer[MAX_STR_LEN];       /*  Holds animation sequence       */

UBYTE ObjectName[MAX_STR_LEN];       /*  Holds load/save object name    */

UBYTE SaveCName[MAX_STR_LEN];        /*  Holds save C source name       */

UBYTE SaveAsmName[MAX_STR_LEN];      /*  Holds save ASM source name     */

/*  Currently defined repeat modes  */
char *ModeStr[] = {
 "CURRENT",
 "ALL    ",
 "FROM   ",
 "UP TO  ",
 "EXCEPT " };


#include "SW_Gadgets.h"
#include "SW_Menu.h"
#include "SW_Display.h"

main()
{
USHORT GadID,MenuCode;
UBYTE HighBit,LowBit,MenuNum;
LONG MouseX,MouseY;
LONG Row,Column,Mode;
LONG BitMask,Index;
LONG RedBits,GreenBits,BlueBits;
LONG CurrScrColor,CurrSprColor;
LONG SelectVal,ScrollVal,RotateVal;
BOOL ScrollMode,SelectMode;
BOOL RotateMode,ColorMode;
BOOL DrawMode,Test1,Test2;
UWORD *SpriteDataPtr;
UWORD *SprColorPtr;               /*  Points to current sprite color  */
struct ColorData *CurrentCD;
struct PropInfo *InfoPtr;
struct Sprite *SpritePtr;         /*  Points to current sprite  */
WORD ColorVal,SprNum;
int i;

OpenLibs();                             /*  Open all needed libraries   */
SetSeed();                              /*  Seed random number routine  */

InitDisplay();                          /*  Initial screen display      */
DrawGrid();                             /*  Put the grid on the screen  */

AllocSprite(&MySprite,SPRITE02);        /*  Allocate edit sprite        */
InitSprites(&SpriteArray[0]);           /*  Initialize edit sprites     */
InitTempSprite(&TempSprite);            /*  For Get() before Put()      */
ClearSprData(&NullImage[0]);            /*  Image during requesters     */

InitGadgets();                          /*  Add all gadgets to window   */
SetMenuStrip(WindowPtr,&Titles[0]);     /*  Menu definitions            */

/*  Allocate rasters for horizontal and vertical scrolling  */
InitTempRast(&HorizRast,&HorizBitMap,BOX_WIDTH,GRID_HEIGHT);
InitTempRast(&VertRast,&VertBitMap,GRID_WIDTH,BOX_HEIGHT);
InitTempRast(&GRast,&GBitMap,GRID_WIDTH,GRID_HEIGHT);

/*  Get pointer colors and pointer data  */
GetDefPrefs(&MyPrefs,sizeof(struct Preferences));

/*  Refresh gadget display  */
GadPtr = WindowPtr->FirstGadget;
RefreshGadgets(GadPtr,WindowPtr,NULL);

/*  Set current color and current sprite  */
SpritePtr = &SpriteArray[0];
SprColorPtr = &SpritePtr->SprColor1;
CurrentCD = &ColorData1;
CurrScrColor = CurrentCD->ScreenColor;
CurrSprColor = CurrentCD->SpriteColor;

/*  Refresh screen with current sprite, current (X,Y) and current mode  */
Mode = CURRENT;
RefreshSprNum(Rp,0);
RefreshGridXY(Rp,0,0);
RefreshMode(Rp,ModeStr[Mode]);

/*  Set first sprite image as pointer image  */
SpriteDataPtr = &SpritePtr->SpriteData[0];
CopySprData(&MyPrefs.PointerMatrix[0],SpriteDataPtr);
ChangeSprite(Vp,&MySprite,SpriteDataPtr);

/*  Set RGB gadgets and draw first sprite image  */
SetRGBGad(CurrScrColor); 
CalcSprite(Rp,SpritePtr,&Boxes[0]);

/*  Disable all repeat modes  */
ColorMode = FALSE;
SelectMode = FALSE;
ScrollMode = FALSE;
RotateMode = FALSE;
DrawMode = FALSE;

while (TRUE)                                 /*  A structured goto  */
  {
  /*  Are we in DrawMode?  */
  if ( DrawMode == TRUE )
     {
     MouseX = WindowPtr->MouseX;
     MouseY = WindowPtr->MouseY;
     if ( GetRowCol(MouseX,MouseY,&Row,&Column) == TRUE ) 
        {
        /*  Handle grid plot  */
        RefreshGridXY(Rp,Row,Column);
        Index = Column + (Row * 16);
        PlotGrid(Index,CurrScrColor);
        /*  Handle sprite plot  */
        HighBit = CurrentCD->ColorBits.HighBit;
        LowBit = CurrentCD->ColorBits.LowBit;
        BitMask = 1 << (15 - Column);
        PlotSprite(SpritePtr,Row,HighBit,LowBit,BitMask);
        }
     else
        DrawMode = FALSE;
     };

  /*  Are we in SelectMode?  */
  if ( SelectMode == TRUE )
     {
     /*  Determine current sprite  */
     SprNum = SpritePtr->SpriteNumber;    /*  Get current sprite number  */
     SprNum += SelectVal;
     if ( SprNum == - 1  )                /*  Don't change this!  */
        SpritePtr = &SpriteArray[HIGH_SPRITE];
     else if ( SprNum > HIGH_SPRITE )
        SpritePtr = &SpriteArray[LOW_SPRITE];
     else
        SpritePtr += SelectVal;       /*  Scaled by argument size  */

     /*  Change current colors to selected sprite colors  */
     ResetColors(SpritePtr->SprColor1,&ColorData1);
     ResetColors(SpritePtr->SprColor2,&ColorData2);
     ResetColors(SpritePtr->SprColor3,&ColorData3);
     
     /*  Change sprite image  */
     SpriteDataPtr = &SpritePtr->SpriteData[0];
     ChangeSprite(Vp,&MySprite,SpriteDataPtr);

     /*  Determine which color of this sprite is current  */
     if ( CurrScrColor == COLOR01 )
        SprColorPtr = &SpritePtr->SprColor1;
     else if ( CurrScrColor == COLOR02 )
        SprColorPtr = &SpritePtr->SprColor2;
     else if ( CurrScrColor == COLOR03 )
        SprColorPtr = &SpritePtr->SprColor3;

     /*  Refresh screen display  */
     SetRGBGad(CurrScrColor);
     RefreshSprNum(Rp,SpritePtr->SpriteNumber);
     CalcSprite(Rp,SpritePtr,&Boxes[0]);
     };

  /*  Are we in ColorMode?  */
  if ( ColorMode == TRUE )
     {
     /*  Read RGB gadgets  */
     RedBits = GetPropVal(&RedGad);
     GreenBits = GetPropVal(&GreenGad);
     BlueBits = GetPropVal(&BlueGad);

     /*  Set screen and sprite colors  */
     SetRGB4(Vp,CurrScrColor,RedBits,GreenBits,BlueBits);   /*  Screen  */
     SetRGB4(Vp,CurrSprColor,RedBits,GreenBits,BlueBits);   /*  Sprite  */

     /*  Should we update the sprite color pointer  */
     if ( CurrScrColor != COLOR00 )
        {
        ColorVal = PackRGB(RedBits,GreenBits,BlueBits);
        *SprColorPtr = ColorVal;
        };
     };

  /*  Are we in ScrollMode?  */
  if ( ScrollMode == TRUE )
     {
     if ( ScrollVal == SCROLL_UP )
        ScrollUp(Rp,&VertRast,SpritePtr,&Boxes[0]);
     else if ( ScrollVal == SCROLL_DOWN )
        ScrollDown(Rp,&VertRast,SpritePtr,&Boxes[0]);
     else if ( ScrollVal == SCROLL_LEFT )
        ScrollLeft(Rp,&HorizRast,SpritePtr,&Boxes[0]);
     else if ( ScrollVal = SCROLL_RIGHT )
        ScrollRight(Rp,&HorizRast,SpritePtr,&Boxes[0]);

     /*  Change actual sprite image  */
     SpriteDataPtr = &SpritePtr->SpriteData[0];
     ChangeSprite(Vp,&MySprite,SpriteDataPtr);
     };

  /*  Are we in RotateMode?  */ 
  if ( RotateMode == TRUE )
     {
     if ( RotateVal == ROTATE_RIGHT )
        RotateRight(Rp,&GRast,SpritePtr,&Boxes[0]);
     else
        RotateLeft(Rp,&GRast,SpritePtr,&Boxes[0]);

     /*  Change actual sprite image  */
     SpriteDataPtr = &SpritePtr->SpriteData[0];
     ChangeSprite(Vp,&MySprite,SpriteDataPtr);
     };

  MessagePtr = (struct IntuiMessage *) GetMsg(WindowPtr->UserPort);
  if ( MessagePtr != NULL )
     {
     ReplyMsg(MessagePtr);                  /*  Reply to message  */
     switch(MessagePtr->Class)
        {
        case CLOSEWINDOW :
             Quit();             /*  Free memory, sprite, and exit  */
        break;

        case MOUSEBUTTONS :
             if ( MessagePtr->Code == SELECTUP )
                {
                /*  Disable repeat modes -- gadgets and grid plotting    */
                DrawMode = FALSE;
                SelectMode = FALSE;
                ScrollMode = FALSE;
                RotateMode = FALSE;
                ColorMode = FALSE;
                }
             else                 /*  If SELECTDOWN, it's not a gadget!  */
                DrawMode = TRUE;
        break;

        case GADGETDOWN :
             GadPtr = (struct Gadget *) MessagePtr->IAddress;
             GadID = GadPtr->GadgetID;

             /*  Check select gadgets  */
             if ( GadID == SELECT_PLUS || GadID == SELECT_MINUS )
                {
                SelectMode = TRUE;
                SelectVal = (GadID == SELECT_PLUS ? 1 : - 1);
                };

             /*  Check color gadgets  */
             Test1 = (BOOL) (GadID == SPRCOLOR0 || GadID == SPRCOLOR1);
             Test2 = (BOOL) (GadID == SPRCOLOR2 || GadID == SPRCOLOR3);
             if ( Test1 || Test2 )
                {
                CurrentCD = (struct ColorData *) GadPtr->UserData;
                CurrScrColor = CurrentCD->ScreenColor;
                CurrSprColor = CurrentCD->SpriteColor;
                SetRGBGad(CurrScrColor);

                /*  Determine current edit color of current sprite  */
                if ( GadID == SPRCOLOR1 )
                   SprColorPtr = &SpritePtr->SprColor1;
                else if ( GadID == SPRCOLOR2 )
                   SprColorPtr = &SpritePtr->SprColor2;
                else if ( GadID == SPRCOLOR3 )
                   SprColorPtr = &SpritePtr->SprColor3;
                };

             /*  Check scroll gadgets  */
             Test1 = (BOOL) (GadID == SCROLL_UP || GadID == SCROLL_DOWN);
             Test2 = (BOOL) (GadID == SCROLL_LEFT || GadID == SCROLL_RIGHT);
             if ( Test1 | Test2 )
                {
                ScrollMode = TRUE;
                ScrollVal = GadID;
                };

             /*  Check rotate gadgets  */
             if ( GadID == ROTATE_LEFT || GadID == ROTATE_RIGHT )
                {
                RotateMode = TRUE;
                RotateVal = GadID;
                };

             /*  Check RGB gadgets  */
             Test1 = (BOOL) (GadID == RED_GAD);
             Test2 = (BOOL) (GadID == GREEN_GAD || GadID == BLUE_GAD);
             if ( Test1 | Test2 )
                ColorMode = TRUE;
        break;

        /*  This is for RELVERIFY gadgets only  */
        case GADGETUP :
             GadPtr = (struct Gadget *) MessagePtr->IAddress;
             GadID = GadPtr->GadgetID;

             /*  Check buffer gadgets  */
             Test1 = (BOOL) (GadID == GET_GAD || GadID == PUT_GAD);
             if ( Test1 )
                {
                SprNum = SpritePtr->SpriteNumber;
                if ( GadID == GET_GAD )
                   {
                   CopySprite(&TempSprite,SpritePtr);
                   SpritePtr->SpriteNumber = SprNum;
                   ResetColors(SpritePtr->SprColor1,&ColorData1);
                   ResetColors(SpritePtr->SprColor2,&ColorData2);
                   ResetColors(SpritePtr->SprColor3,&ColorData3);
                   SetRGBGad(CurrScrColor); 
                   ChangeSprite(Vp,&MySprite,&SpritePtr->SpriteData[0]);
                   CalcSprite(Rp,SpritePtr,&Boxes[0]);
                   }
                else
                   CopySprite(SpritePtr,&TempSprite);      /*  PUT_GAD  */
                };

             /*  Disable all repeat gadgets  */
             SelectMode = FALSE;
             ScrollMode = FALSE;
             RotateMode = FALSE;
             ColorMode = FALSE;
        break;
 
        case MENUPICK :
             MenuCode = MessagePtr->Code;
             if ( MenuCode != MENUNULL )
                {
                MenuNum = MENUNUM(MenuCode);
                if ( MenuNum == PROJECT )
                   HandleProject(MenuCode,SpritePtr,CurrentCD,Mode);
                else if ( MenuNum == EDIT )
                   HandleEdit(MenuCode,SpritePtr,CurrentCD,Mode);
                else if ( MenuNum == MODE )
                   {
                   Mode = ITEMNUM(MenuCode);
                   RefreshMode(Rp,ModeStr[Mode]);
                   }
                else if ( MenuNum == ANIMATE )
                   HandleAnimate(MenuCode,SpritePtr);
                };
        break;

        default :       /*  This doesn't do anything!  */  ;
        };
     };
  };
}


/*  Set RGB gadgets based on contents of color register passed  */
SetRGBGad(ColorReg)
LONG ColorReg;
{
struct PropInfo *InfoPtr;
struct ColorMap *CMapPtr;
ULONG RedBits,GreenBits,BlueBits;
UWORD ColorVal;

CMapPtr = Vp->ColorMap;
ColorVal = GetRGB4(CMapPtr,ColorReg);
UnPackRGB(ColorVal,&RedBits,&GreenBits,&BlueBits);

/*  Set red RGB gadget  */
InfoPtr = (struct PropInfo *) RedGad.SpecialInfo;
InfoPtr->HorizPot = RedBits * 0x1111;

/*  Set green RGB gadget  */
InfoPtr = (struct PropInfo *) GreenGad.SpecialInfo;
InfoPtr->HorizPot = GreenBits * 0x1111;

/*  Set blue RGB gadget  */
InfoPtr = (struct PropInfo *) BlueGad.SpecialInfo;
InfoPtr->HorizPot = BlueBits * 0x1111;

/*  Refresh gadget display  */
GadPtr = WindowPtr->FirstGadget;
RefreshGadgets(GadPtr,WindowPtr,NULL);

/*  Refresh current color indicator  */
MinX = 540;
MinY = 37;
MaxX = 572;
MaxY = 61;
SetAPen(Rp,COLOR04);             
RectFill(Rp,MinX,MinY,MaxX,MaxY);           /*  Emulate border  */
SetAPen(Rp,ColorReg);
RectFill(Rp,MinX+1,MinY+1,MaxX-1,MaxY-1);   /*  Current color indicator  */
}


/*  Get setting of proportional gadget  --  Value is [0..15]  */
LONG GetPropVal(GadPtr)
struct Gadget *GadPtr;
{
struct PropInfo *InfoPtr;
USHORT HorizPot;
LONG Value;
 
InfoPtr = (struct PropInfo *) GadPtr->SpecialInfo;
HorizPot = InfoPtr->HorizPot;
Value = (LONG) (HorizPot / 0x1111);
return(Value);
}


/*  Determine if a point is within grid and return (X,Y)  */
BOOL GetRowCol(XCoord,YCoord,RowPtr,ColumnPtr)
LONG XCoord,YCoord;
LONG *RowPtr,*ColumnPtr;
{
BOOL TestX,TestY;
LONG TempRow,TempColumn;

/*  Get Mouse Coordinates in form of Row and Column  */
TempRow = (YCoord - 20) / BOX_HEIGHT;
TempColumn = (XCoord - 20) / BOX_WIDTH;

TestX =  (BOOL) ( TempColumn >= 0 && TempColumn <= 15 );
TestY =  (BOOL) ( TempRow >= 0 && TempRow <= 15 );

 /*  If point is within Grid, return TRUE  */
if ( TestX && TestY )
   {
   *RowPtr = TempRow;
   *ColumnPtr = TempColumn;
   return((BOOL) TRUE);
   }
else
   {
   *RowPtr = 9999;
   *ColumnPtr = 9999;
   return((BOOL) FALSE);
   };
}


/*  Plot point on grid based on index passed  */
PlotGrid(Index,ColorReg)
LONG Index,ColorReg;
{
MinX = (LONG) Boxes[Index].MinX;
MinY = (LONG) Boxes[Index].MinY;
MaxX = (LONG) Boxes[Index].MaxX;
MaxY = (LONG) Boxes[Index].MaxY;
SetAPen(Rp,ColorReg);
RectFill(Rp,MinX + 1,MinY + 1,MaxX - 1,MaxY - 1);
}


/*  Plot point in sprite  */
PlotSprite(SpritePtr,Row,HighBit,LowBit,BitMask)
struct Sprite *SpritePtr;
LONG Row;
UBYTE LowBit,HighBit;
LONG BitMask;
{
LONG WordIndex;
UWORD HighWord,LowWord;
UWORD *SpriteDataPtr;

SpriteDataPtr = &SpritePtr->SpriteData[0];

/*  Calculate address of actual sprite data  */
WordIndex = 2 + (Row * 2);                       /*  Skip posctldata  */
HighWord = *(SpriteDataPtr + WordIndex);
LowWord = *(SpriteDataPtr + WordIndex + 1);

if ( HighBit == 1 )
   HighWord |= BitMask;                        /*  Set if HighBit = 1  */
else
   HighWord &= (ALL_BITS - BitMask);

if ( LowBit == 1 )
   LowWord |= BitMask;                         /*  Set if HighBit = 1  */
else
   LowWord &= (ALL_BITS - BitMask);

/*  Assign data back to sprite  */
*(SpriteDataPtr + WordIndex) = HighWord;
*(SpriteDataPtr + WordIndex + 1) = LowWord;
ChangeSprite(Vp,&MySprite,SpriteDataPtr);
}


/*  Reset screen, gadget, and sprite colors  */
ResetColors(ColorVal,ColorDataPtr)
UWORD ColorVal;
struct ColorData *ColorDataPtr;
{
ULONG ScreenColor,SpriteColor;
ULONG RedBits,GreenBits,BlueBits;

/*  Get current screen and sprite color registers  */
ScreenColor = ColorDataPtr->ScreenColor;
SpriteColor = ColorDataPtr->SpriteColor;

/*  Set screen and gadget colors based on colors of current sprite  */
UnPackRGB(ColorVal,&RedBits,&GreenBits,&BlueBits);
SetRGB4(Vp,ScreenColor,RedBits,GreenBits,BlueBits);
SetRGB4(Vp,SpriteColor,RedBits,GreenBits,BlueBits);
}


/*  Handle project choice from menu  */
HandleProject(MenuCode,SpritePtr,ColorDataPtr,Mode)
USHORT MenuCode;
struct Sprite *SpritePtr;
struct ColorData *ColorDataPtr;
ULONG Mode;
{
UBYTE ItemNum,SubNum;
char *StrPtr,*FileName;
char ErrMsg[80];
BOOL ReturnVal;

ItemNum = ITEMNUM(MenuCode);
SubNum = SUBNUM(MenuCode);
switch(ItemNum)
  {
  case ABOUT :
       if ( SubNum == AUTHOR )
          Author(WindowPtr);
       else if ( SubNum == PROGRAM )
          {
          ChangeSprite(Vp,&MySprite,&NullImage[0]);
          Program(WindowPtr);
          ChangeSprite(Vp,&MySprite,&SpritePtr->SpriteData[0]);
          };
  break;

  case LOAD :
       StrPtr = "Load binary data from which file :      ";
       ReturnVal = GetString(WindowPtr,StrPtr,&ObjectName[0]);
       if ( ReturnVal == TRUE )
          {
          FileName = (char *) &ObjectName[0];
          ReturnVal = LoadBinary(&SpriteArray[0],FileName,&ErrMsg[0]);
          if ( ReturnVal == FALSE )
             ErrRequest(WindowPtr,&ErrMsg[0]);
          else
             {
             /*  Change current colors to selected sprite colors  */
             ResetColors(SpritePtr->SprColor1,&ColorData1);
             ResetColors(SpritePtr->SprColor2,&ColorData2);
             ResetColors(SpritePtr->SprColor3,&ColorData3);

             /*  Reset current pen indicator and RGB gadgets  */
             SetRGBGad(ColorDataPtr->ScreenColor);

             CalcSprite(Rp,SpritePtr,&Boxes[0]);     /*  Redraw image  */
             };
          }; 
  break;

  case SAVE_SRC :
#ifdef DEMO
       /*  Disable imagry, do request, re-enable imagry  */
       ChangeSprite(Vp,&MySprite,&NullImage[0]);
       Money(WindowPtr);
       ChangeSprite(Vp,&MySprite,&SpritePtr->SpriteData[0]);
#else
       if ( SubNum == SAVE_C_SRC )
          {
          StrPtr = "Save C source data to which file :      ";
          ReturnVal = GetString(WindowPtr,StrPtr,&SaveCName[0]);
          FileName = (char *) &SaveCName[0];
          }
       else if ( SubNum == SAVE_ASM_SRC )
          {
          StrPtr = "Save 68000 source data to which file :  ";
          ReturnVal = GetString(WindowPtr,StrPtr,&SaveAsmName[0]);
          FileName = (char *) &SaveAsmName[0];
          }
       else
          ReturnVal = FALSE;

       if ( ReturnVal == TRUE )
          {
          if ( SubNum == SAVE_C_SRC )
             ReturnVal = SaveCSource(SpritePtr,FileName,Mode,&ErrMsg[0]);
          else if ( SubNum == SAVE_ASM_SRC )
             ReturnVal = SaveAsmSource(SpritePtr,FileName,Mode,&ErrMsg[0]);
          if ( ReturnVal == FALSE )
             ErrRequest(WindowPtr,&ErrMsg[0]);
          };
#endif
  break;

  case SAVE_BIN :                                    
       StrPtr = "Save binary data to which file :        ";
       ReturnVal = GetString(WindowPtr,StrPtr,&ObjectName[0]);
       if ( ReturnVal == TRUE )
          {
          FileName = (char *) &ObjectName[0];
          ReturnVal = SaveBinary(SpritePtr,FileName,Mode,&ErrMsg[0]);
          if ( ReturnVal == FALSE )
             ErrRequest(WindowPtr,&ErrMsg[0]);
          }; 
  break;


  case QUIT :
       Quit();             /*  Free memory, sprite, and exit  */
  break;

  default :    /*  Just a stub!  */  ;
  };
}


/*  Handle edit choice from menu  */
HandleEdit(MenuCode,SpritePtr,ColorDataPtr,Mode)
USHORT MenuCode;
struct Sprite *SpritePtr;
struct ColorData *ColorDataPtr;
ULONG Mode;
{
UWORD *SpriteDataPtr;
UBYTE ItemNum,SubNum;

/*  Retrieve item number and subnumber chosen  */
ItemNum = ITEMNUM(MenuCode);
SubNum = SUBNUM(MenuCode);

switch(ItemNum)
  {
  case FLIP :
       SpriteDataPtr = &SpritePtr->SpriteData[0];
       if ( SubNum == FLIP_XAXIS )
          {
          FlipX(SpritePtr);
          ChangeSprite(Vp,&MySprite,SpriteDataPtr);
          CalcSprite(Rp,SpritePtr,&Boxes[0]);
          }
       else
          {
          FlipY(SpritePtr);
          ChangeSprite(Vp,&MySprite,SpriteDataPtr);
          CalcSprite(Rp,SpritePtr,&Boxes[0]);
          };
  break;                      /*  case FLIP  */

  case CLR_DATA :
       ClearSprite(SpritePtr,Mode);      /*  Clear specified range  */
       if ( Mode != EXCEPT )
          CalcSprite(Rp,SpritePtr,&Boxes[0]);
  break;
 
  case CLR_COLOR :
       ClearColor(SpritePtr,Mode);       /*  Clear specified range  */
       if ( Mode != EXCEPT )
          {
          /*  Reset ColorData structures to default colors  */
          ResetColors(SpritePtr->SprColor1,&ColorData1);
          ResetColors(SpritePtr->SprColor2,&ColorData2);
          ResetColors(SpritePtr->SprColor3,&ColorData3);

          /*  Reset current pen indicator and RGB gadgets  */
          SetRGBGad(ColorDataPtr->ScreenColor);
          };
  break;                      /*  case CLR_COLOR   */

  case NEGATE :
       SpriteDataPtr = &SpritePtr->SpriteData[0];
       Negate(SpritePtr);
       ChangeSprite(Vp,&MySprite,SpriteDataPtr);
       CalcSprite(Rp,SpritePtr,&Boxes[0]);
  break;

  default :                   /*  Just a stub!  */;
  };
}                            


/*  Handle animate choice from menu  */
HandleAnimate(MenuCode,SpritePtr)
USHORT MenuCode;
struct Sprite *SpritePtr;
{
UBYTE ItemNum,SubNum;
int cntr,BufferLen;
char *StrPtr;
BOOL Finished;
ULONG ColorReg,DelayVal;
ULONG RedBits,GreenBits,BlueBits;
UWORD *SpriteDataPtr,SprNum;

ItemNum = ITEMNUM(MenuCode);
SubNum = SUBNUM(MenuCode);

switch(ItemNum)
  {
  case DEFINE :
       StrPtr = "Please enter your animation sequence :  ";
       GetString(WindowPtr,StrPtr,&AnimBuffer[0]);
       /*  Check if animation sequence is valid  */
       if ( CheckSequence(&AnimBuffer[0]) == FALSE )
          {
          ErrRequest(WindowPtr,"Illegal animation sequence entered!");
          *AnimBuffer = '\0';
          };
  break;

  case START :
       /*  Intialize variables for mouse animation  */
       BufferLen = strlen(AnimBuffer);
       DelayVal = GetPropVal(&SpeedGad) + 3;
       Finished = FALSE;
       cntr = 0;
     
       if ( BufferLen == 0 )     /*  Was animation sequence entered?  */
          {
          ErrRequest(WindowPtr,"An animation sequence must be entered!");
          break;
          };

       /*  Main animation loop  */
       while ( ! Finished )
         {
         /*  Determine sprite number to animate  */
         SprNum = AnimBuffer[cntr] - 'A';
         SpriteDataPtr = &SpriteArray[SprNum].SpriteData[0];
         CopySprData(SpriteDataPtr,&AnimData[0]);
         ClearPosCtl(&AnimData[0]);

         /*  Set pointer color registers from sprite colors  */
         SetPackedRGB(Vp,SpriteArray[SprNum].SprColor1,COLOR17);
         SetPackedRGB(Vp,SpriteArray[SprNum].SprColor2,COLOR18);
         SetPackedRGB(Vp,SpriteArray[SprNum].SprColor3,COLOR19);

         /*  Show next sequence and pause for delay  */
         SetPointer(WindowPtr,&AnimData[0],16,16,0,0);
         Delay(DelayVal);

         /*  Get next frame  */
         cntr++;
         if ( cntr == BufferLen )  cntr = 0;

         /*  Check if it's time to exit  */
         MessagePtr = (struct IntuiMessage *) GetMsg(WindowPtr->UserPort);
         if ( MessagePtr->Class == MOUSEBUTTONS )
            {
            ReplyMsg(MessagePtr);
            Finished = TRUE;
            ClearPointer(WindowPtr);

            /*  Restore default pointer colors  */
            SetPackedRGB(Vp,MyPrefs.color17,COLOR17);
            SetPackedRGB(Vp,MyPrefs.color18,COLOR18);
            SetPackedRGB(Vp,MyPrefs.color19,COLOR19);
            };
         };
  break;

  default :    /*  Just a stub!  */  ;
  };
}


/*  SpriteWiz cleanup routine  */
Quit()
{
FreeTempRast(&VertRast,&VertBitMap,GRID_WIDTH,BOX_HEIGHT);
FreeTempRast(&HorizRast,&HorizBitMap,BOX_WIDTH,GRID_HEIGHT);
FreeTempRast(&GRast,&GBitMap,GRID_WIDTH,GRID_HEIGHT);
FreeSprite(SPRITE02);
CloseWindow(WindowPtr);
CloseScreen(ScreenPtr);
exit(0);
}

