/* The routines in this file are copyright (c) 1987 by Helene (Lee) Taran.
 * Permission is granted for use and free distribution as long as the
 * original author's name is included with the code.
 */

#include "spline.h"

struct IntuitionBase *IntuitionBase; 
struct GfxBase *GfxBase;
struct LayersBase *LayersBase;

void *OpenLibrary();
void *OpenWindow();
void *OpenScreen();

USHORT pointimage[] =  /* what a control point will look like */
   {0x0000, 0x0000, 0x1c00, 0x3e00, 0x3e00, 0x3e00, 0x1c00 };

struct Image control_image = 
 { -4,-4,7,7, 1, &pointimage[0], 0x1, 0x0, NULL};

USHORT ColorTable[COLORCOUNT] =   /* Here are the actual colors used      */
    {  
     0x0000,  /* black */
     0x0063,  /* greenish */
     0x0f24,  /* redish  */
     0x000f,  /* blue */
    };

struct NewWindow WindowInfo =
{ WINDOW_LEFT,              /* Left Edge                               */
  WINDOW_TOP,               /* Top Edge                                */
  WINDOW_WIDTH,             /* Initial Width       (640 =Hires)        */
  WINDOW_HEIGHT,            /* Initial Height      (400 = interlaced)  */
  -1,                       /* DetailPen   (-1 = use screen's)         */
  -1,                       /* BlockPen    (-1 = use screen's)         */
  MOUSEBUTTONS | CLOSEWINDOW , /* <-- IDCMP flags; \/ window flags     */    
  SMART_REFRESH | WINDOWCLOSE| ACTIVATE | REPORTMOUSE,
  NULL,                             /* First Gadget                    */
  NULL,                             /* CheckMark    (used with menus)  */
  (UBYTE *)"Splines",               /* Title                           */
  NULL,                             /* Screen       (null = default)   */
  NULL,                             /* BitMap                          */
  1,	                            /* MinWidth   (0 = initial value)  */
  1,                                /* MinHeight  (0 = initial value)  */
  0,                                /* MaxWidth   (0 = initial value)  */
  0,                                /* MaxHeight  (0 = initial value)  */
  CUSTOMSCREEN,                     /* Type                            */
};


/* The following structure gives all the information that Intuition
 * needs to maintain a customized screen.
 */
struct NewScreen ScreenInfo =
{ 
  0,0,                               /* Left Edge, Top Edge   */
  SCREEN_WIDTH,SCREEN_HEIGHT,        /* Screen Width & Height */
  DEPTH,                             /* Number of bit-planes  */
  DETAILPEN,                         /* Detail Pen color register */
  BLOCKPEN,                          /* Background color register */
  VIEWMODE,                          /* ViewMode */
  CUSTOMSCREEN,                      /* Type */
  NULL,                              /* Font : null = use default */
  (UBYTE *)"Splines and PopUp Menus:   by Lee Taran",  /* Screen Title */
  NULL,                              /* Gadgets */
  NULL                               /* CustomBitMap */
};

/* Bits to keep track of anything that must eventually be deallocated */
int OpenBits = 0x0000;

/* Intuition structures that will be used to setup the background
 * environment. 
 */
struct Window *Window;
struct Screen *Screen;
struct Layer_Info *Layer_Info;

struct PopUp_Menu PointMenu, CurveMenu;
struct PopUp_Item PointItem[] = {
  { "Add Point After",  ADD_AFTER,   1,1,0,0,DETAILPEN,NULL},
  { "Add Point Before", ADD_BEFORE,  1,2,0,0,DETAILPEN,NULL},
  { "Move This Point",  MOVE_POINT,  1,2,0,0,DETAILPEN,NULL},
  { "Remove This Point",REMOVE_POINT,1,2,0,0,DETAILPEN,NULL}
};

struct PopUp_Item CurveItem[] = {
 { "Open B-Spline Natural Ends", OPENB_NATURAL, 1,2,0,0,DETAILPEN,NULL},
 { "Open B-Spline Triple Knots", OPENB_TRIPLE,  1,2,0,0,DETAILPEN,NULL},
 { "Open Interpolating Spline",  OPEN_INTRPL,   1,2,0,0,DETAILPEN,NULL},
 { "Closed B-Spline",            CLOSEDB,       1,2,0,0,DETAILPEN,NULL},
 { "Closed Interpolating Spline",CLOSED_INTRPL, 1,2,0,0,DETAILPEN,NULL},
 { "Toggle AFrame",              TOGGLEAFRAME,  1,2,0,0,DETAILPEN,NULL},
 { "Redraw",                     REDRAW,        1,2,0,0,DETAILPEN,NULL} ,
 { "  GET ME OUT OF HERE!!",     QUIT,          1,5,0,0,OUTLINEPEN,NULL},
};


Init_PointMenu ()
{ 
  PointItem[0].next = &PointItem[1];
  PointItem[1].next = &PointItem[2];
  PointItem[2].next = &PointItem[3];
  
  PointMenu.depth = 2;
  PointMenu.width = 100;   /* minimum width */
  PointMenu.deactivate = SELECTUP;
  PointMenu.outline_color = OUTLINEPEN;
  PointMenu.area_color = BLOCKPEN;
  PointMenu.first_item = &PointItem[0];
  if (!Init_PopUp_Menu(&PointMenu)) panic(POPUP_MENU);
}


Init_CurveMenu ()
{ 
  CurveItem[0].next = &CurveItem[1];
  CurveItem[1].next = &CurveItem[2];
  CurveItem[2].next = &CurveItem[3];
  CurveItem[3].next = &CurveItem[4]; 
  CurveItem[4].next = &CurveItem[5]; 
  CurveItem[5].next = &CurveItem[6]; 
  CurveItem[6].next = &CurveItem[7]; 
    
  CurveMenu.depth = 2;
  CurveMenu.width = 100;   /* minimum width */
  CurveMenu.deactivate = SELECTUP;
  CurveMenu.outline_color = OUTLINEPEN;
  CurveMenu.area_color = BLOCKPEN;
  CurveMenu.first_item = &CurveItem[0];
  if (!Init_PopUp_Menu(&CurveMenu)) panic(POPUP_MENU);

}


OpenLibraries ()
{
  /* Open the Intuition library -- connect to the routines in ROM 
   * If the result is NULL then something went wrong so exit immediately
   */
  if (!(IntuitionBase = (struct IntuitionBase *) 
           OpenLibrary("intuition.library",INTUITION_VERSION)))
     panic(INTUITION);
  else OpenBits |= INTUITION;
  
  /* Open the Graphics Library -- so that we can use the bit-map
   * facilities of our window.
   */
 if (!(GfxBase = (struct GfxBase *)
     OpenLibrary("graphics.library",GFX_VERSION)))
     panic(GRAPHICS);
  else OpenBits |= GRAPHICS;

 if (!(LayersBase = (struct LayersBase *)
     OpenLibrary("layers.library",LAYERS_VERSION)))
     panic(LAYERS);
 else OpenBits |= LAYERS;
}  
 

/* SetupEnvironment : initializes the screen and window that 
 * will be used. Assumes that all libraries have already been opened
 */ 
SetupEnvironment()
{ struct RastPort *RPort;

 if (!Init_MenuPackage()) panic(MENU_PACKAGE);
 Init_PointMenu();
 Init_CurveMenu();

  /* Open a customized Screen */
  if (!(Screen = (struct Screen *)OpenScreen(&ScreenInfo)))
     panic(SCREEN);
  else OpenBits |= SCREEN;

  WindowInfo.Screen = Screen;
  
  /* Open A window in the new Window */
  if (!(Window = (struct Window *)OpenWindow(&WindowInfo)))
     panic(WINDOW);
  else OpenBits |= WINDOW;

  /* set up window colors */
  LoadRGB4(ViewPortAddress(Window),&ColorTable,COLORCOUNT);

  SetRast(Window->RPort,ERASE); /* wipe out everything -- no title bar */
}


/* panic: Prints out an error message about what went wrong during the
 * setup/initialization phase of this program and ends the program
 * gracefully by calling close_things before exiting with an error code
 */
panic(error_code)
int error_code;
{
  switch (error_code) 
   {
     case LAYERS     :
          fprintf(stderr,"splines: couldn't open layers library [%d]\n",
                          LAYERS_VERSION);
          break;
     case POPUP_MENU :
          fprintf(stderr,"splines: couldn't allocate popup menu\n");
          break;
     case MENU_PACKAGE :
          fprintf(stderr,"splines: couldn't initialize menu package\n");
          break;
     case INTUITION : 
          fprintf(stderr,"splines: couldn't find Intuition Library [%d]\n",
                         INTUITION_VERSION);
          break;
     case GRAPHICS  : 
          fprintf(stderr,"splines: couldn't find Graphics Library [%d]\n",
                          GFX_VERSION);
          break;
     case SCREEN    :
          fprintf(stderr,"splines: couldn't open Custom Screen.\n");
          break;
     case WINDOW    : 
          fprintf(stderr,"splines: couldn't open Window.\n");
          break;
   }

  close_things();
  exit(error_code);
}




/* close_things : closes the Libraries that have been opened and
 * frees up whatever memory has been used.
 */
close_things()
{
  Dispose_PopUp(&PointMenu);
  Dispose_PopUp(&CurveMenu);
  Close_MenuPackage();
  if (OpenBits & WINDOW)     CloseWindow(Window);
  if (OpenBits & SCREEN)     CloseScreen(Screen);
  if (OpenBits & LAYERS)     CloseLibrary(LayersBase);
  if (OpenBits & GRAPHICS)   CloseLibrary(GfxBase);
  if (OpenBits & INTUITION)  CloseLibrary(IntuitionBase);
}


