#include <exec/types.h>
#include <exec/devices.h>
#include <intuition/intuition.h>

#include <graphics/gels.h>
#include <graphics/copper.h>
#include <graphics/regions.h>
#include <devices/keymap.h>

#define I_REV   29
#define G_REV   29

struct IntuitionBase *IntuitionBase;
struct GfxBase  { int b; } *GfxBase;

#define FAST register      /* Registro che scrive variabile  */

#define DPTH 5       /* Dimensioni Raster */
#define WDTH 320
#define HGHT 200

#define NL 0

#define BCOL 1          /* Colore di Background per i menu */

#define CTSIZ  32       /* Misura Tavola Colore */

struct TextAttr MyFont = {"topaz.font",TOPAZ_EIGHTY,FS_NORMAL,FPF_ROMFONT };

/* Usato per aprire uno Screen */
struct NewScreen NewScreen = {
   0,0,WDTH,HGHT,DPTH,       /* Sinistra,Alto,Larghezza,Altezza,Profondita' */
   1,2,NL,                   /* DetailPen, BlockPen, ViewModes */
   CUSTOMSCREEN,&MyFont,     /* Scrittura, Font  */
   (UBYTE *)"            ",  /* Titolo       */
   NL,NL };                  /* Gadget, BitMap  */

/* Usato per aprire una Window   */
struct NewWindow NewWindow = {
   0,0,WDTH,HGHT, /* AngoloSinistro,AngoloAlto,Larghezza,Altezza */
   8,BCOL,         /* DetailPen,BlockPen     */
   MOUSEBUTTONS | MOUSEMOVE | MENUVERIFY | MENUPICK | GADGETUP |
      GADGETDOWN | CLOSEWINDOW | ACTIVEWINDOW,
   SMART_REFRESH | REPORTMOUSE | ACTIVATE | BACKDROP | BORDERLESS, /*Flag*/
   NL,NL,NL,       /* PrimoGadget, CheckMark, Titolo  */
   NL,             /* MUST SET SCREEN AFTER OPENSCREEN!!! */
   NL,             /* BitMap    */
   100,60,32767,32767, /* MinW, MinH, MaxW, MaxH */
   CUSTOMSCREEN };     /* Scrittura */


/****    Variabili Inizializzate con init_program()  **********/
struct Screen   *p_S;
struct Window   *p_W;
struct ViewPort *p_Vp;
struct ColorMap *p_Co;
USHORT *p_ct;           /* Tavola Colore come parole */

USHORT default_color[CTSIZ];     /* Save una copia dei default   */


/****************************************************************
* init_program()
*
*     Apre lo schermo e la window per il programma di disegno.
*     Colloca e inizializza le varie aree dei buffer...
*
*
*  Vedi anche: clear_program()                                     */
init_program()
{
FAST int i;

   if ( ! (IntuitionBase = (struct IntuitionBase *)
     OpenLibrary("intuition.library",I_REV)) ||
      ! (GfxBase =(struct GfxBase *)OpenLibrary("graphics.library",G_REV)) )
         exit(20);

   if ( ! (p_S =(struct Screen *)OpenScreen(&NewScreen)) ) {
      printf("Can't Open Screen! Get More Mem!\n");
      exit(21);
      }

   NewWindow.Screen = p_S;   /* NEED TO SET SCREEN!!! */

   if ( ! (p_W =(struct Window *)OpenWindow(&NewWindow)) ) {
      CloseScreen(p_S);
      printf("This is not good.\n");
      exit(22);
      }

   p_Vp = (struct ViewPort *)ViewPortAddress(p_W);

   p_Co = (struct ColorMap *)GetColorMap(CTSIZ);
   p_ct = (USHORT *)p_Co->ColorTable;

   for ( i=0; i<CTSIZ; i++)
      default_color[i] = p_ct[i];
   default_color[0] = 0x20f; default_color[1] = 0xfff;
   default_color[2] = 0x000; default_color[3] = 0xe30;
   set_defmap();
}



/*************************************************
* clear_program
*
*  Esce dal modo programma, pulisce lo schermo e le variabli window
*************************************************/
clear_program()
{
   FreeColorMap(p_Co);
   CloseWindow(p_W);
   CloseScreen(p_S);
   CloseLibrary(GfxBase);
   CloseLibrary(IntuitionBase);
}


/****************************************************************
* set_defmap()
*    Questa routine setta una routine 'default' della mappa colore.  Essa
* presume che voi abbiate initializzato la variabile p_ct da puntare alla
* tavola colore, e che il default_color abbia i colori da voi voluti.*/
set_defmap()
{
FAST int i;

   for (i=0; i<CTSIZ ; i++)
      *(p_ct+i) = default_color[i];

   set_cmap();
}



/****************************************************************
* set_cmap()
*     Questa routine carica una tavola colore p_ct aggiornata nella
* viewport.  Voi dovete aver inizializzato le variabili p_ct e
* p_Vp per puntare alla tavola colore e alla ViewPort            */
set_cmap()
{
   LoadRGB4(p_Vp,p_ct,CTSIZ);
}


/***   seguono le routine di modifica palette    ************************/

#define PLX 165      /* Misura Window Palette  */
#define PLY 132

#define PGAD 0
#define PGHI   PGAD+CTSIZ

struct IntuiText rtxt = {2,2,JAM1,-9,2,NL,(UBYTE *)"R",NL};
struct IntuiText gtxt = {2,2,JAM1,-9,2,NL,(UBYTE *)"G",NL};
struct IntuiText btxt = {2,2,JAM1,-9,2,NL,(UBYTE *)"B",NL};

struct Image    r_img, g_img, b_img;
struct PropInfo r_prop,g_prop,b_prop;

struct Gadget blue_gad = {
   NL, 17,112, 90,11, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
   PROPGADGET,(APTR)&b_img, NL,
   &btxt, NL,(APTR)&b_prop, PGHI+3, NL };

struct Gadget green_gad = {
   &blue_gad, 17,97, 90,11, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
   PROPGADGET,(APTR)&g_img, NL,
   &gtxt, NL,(APTR)&g_prop, PGHI+4, NL };

struct Gadget red_gad = {
   &green_gad, 17,82, 90,11, GADGHCOMP, GADGIMMEDIATE | RELVERIFY,
   PROPGADGET,(APTR)&r_img, NL,
   &rtxt, NL,(APTR)&r_prop, PGHI+5, NL };

struct IntuiText oktxt = {3,2,JAM2,8,2,NL,(UBYTE *)" OK ",NL};
struct IntuiText cntxt = {3,2,JAM2,0,2,NL,(UBYTE *)"Cancel",NL};
struct IntuiText retxt = {3,2,JAM2,4,2,NL,(UBYTE *)"Reset",NL};

struct IntuiText mstxt={2,2,JAM1,0,0,NL,(UBYTE *)"Palette",NL};

char frog[] = "hex";
struct IntuiText hxtxt = {3,2,JAM2,136,31,NL,(UBYTE *)frog,NL};

struct Gadget re_gad = {
   &red_gad, 110,112, 54,11, GADGHCOMP, RELVERIFY,
   BOOLGADGET, NL, NL,
   &retxt, NL,NL, PGHI+2, NL };
struct Gadget cn_gad = {
   &re_gad, 110,97, 54,11, GADGHCOMP, RELVERIFY,
   BOOLGADGET, NL, NL,
   &cntxt, NL,NL, PGHI+1, NL };
struct Gadget ok_gad = {
   &cn_gad, 110,82, 54,11, GADGHCOMP, RELVERIFY,
   BOOLGADGET, NL, NL,
   &oktxt, NL,NL, PGHI, NL };

struct Image m3C[CTSIZ] = {
   {0,0,16,16,1, NL ,0,0,NL },   /* Colori   */
   {0,0,16,16,1, NL ,0,1,NL },
   {0,0,16,16,1, NL ,0,2,NL },
   {0,0,16,16,1, NL ,0,3,NL },
   {0,0,16,16,1, NL ,0,4,NL },
   {0,0,16,16,1, NL ,0,5,NL },
   {0,0,16,16,1, NL ,0,6,NL },
   {0,0,16,16,1, NL ,0,7,NL },
   {0,0,16,16,1, NL ,0,8,NL },
   {0,0,16,16,1, NL ,0,9,NL },
   {0,0,16,16,1, NL ,0,10,NL },
   {0,0,16,16,1, NL ,0,11,NL },
   {0,0,16,16,1, NL ,0,12,NL },
   {0,0,16,16,1, NL ,0,13,NL },
   {0,0,16,16,1, NL ,0,14,NL },
   {0,0,16,16,1, NL ,0,15,NL },
   {0,0,16,16,1, NL ,0,16,NL },
   {0,0,16,16,1, NL ,0,17,NL },
   {0,0,16,16,1, NL ,0,18,NL },
   {0,0,16,16,1, NL ,0,19,NL },
   {0,0,16,16,1, NL ,0,20,NL },
   {0,0,16,16,1, NL ,0,21,NL },
   {0,0,16,16,1, NL ,0,22,NL },
   {0,0,16,16,1, NL ,0,23,NL },
   {0,0,16,16,1, NL ,0,24,NL },
   {0,0,16,16,1, NL ,0,25,NL },
   {0,0,16,16,1, NL ,0,26,NL },
   {0,0,16,16,1, NL ,0,27,NL },
   {0,0,16,16,1, NL ,0,28,NL },
   {0,0,16,16,1, NL ,0,29,NL },
   {0,0,16,16,1, NL ,0,30,NL },
   {0,0,16,16,1, NL ,0,31,NL } };

struct Gadget palg[CTSIZ] = {
   { &palg[1], 3, 3,  16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[0], NL,NL,NL,NL, PGAD+0, NL},
   { &palg[2], 19,3, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[1], NL,NL,NL,NL, PGAD+1, NL},
   { &palg[3], 35,3, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[2], NL,NL,NL,NL, PGAD+2, NL},
   { &palg[4], 51,3, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[3], NL,NL,NL,NL, PGAD+3, NL},
   { &palg[5], 67,3, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[4], NL,NL,NL,NL, PGAD+4, NL},
   { &palg[6], 83,3, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[5], NL,NL,NL,NL, PGAD+5, NL},
   { &palg[7], 99,3, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[6], NL,NL,NL,NL, PGAD+6, NL},
   { &palg[8],115,3,  16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[7], NL,NL,NL,NL, PGAD+7, NL},
   { &palg[9], 3,19, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[8], NL,NL,NL,NL, PGAD+8, NL},
   { &palg[10],19,19, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[9], NL,NL,NL,NL, PGAD+9, NL},
   { &palg[11],35,19, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[10], NL,NL,NL,NL, PGAD+10, NL},
   { &palg[12],51,19, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[11], NL,NL,NL,NL, PGAD+11, NL},
   { &palg[13],67,19, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[12], NL,NL,NL,NL, PGAD+12, NL},
   { &palg[14],83,19, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[13], NL,NL,NL,NL, PGAD+13, NL},
   { &palg[15],99,19,16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[14], NL,NL,NL,NL, PGAD+14, NL},
   { &palg[16],115,19,16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[15], NL,NL,NL,NL, PGAD+15, NL},
   { &palg[17], 3,35, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET, (APTR)&m3C[16], NL,NL,NL,NL, PGAD+16, NL},
   { &palg[18],19,35, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[17], NL,NL,NL,NL, PGAD+17, NL},
   { &palg[19],35,35, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[18], NL,NL,NL,NL, PGAD+18, NL},
   { &palg[20],51,35, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[19], NL,NL,NL,NL, PGAD+19, NL},
   { &palg[21],67,35, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[20], NL,NL,NL,NL, PGAD+20, NL},
   { &palg[22],83,35, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[21], NL,NL,NL,NL, PGAD+21, NL},
   { &palg[23],99,35,16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[22], NL,NL,NL,NL, PGAD+22, NL},
   { &palg[24],115,35,16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[23], NL,NL,NL,NL, PGAD+23, NL},
   { &palg[25], 3,51, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET, (APTR)&m3C[24], NL,NL,NL,NL, PGAD+24, NL},
   { &palg[26],19,51, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[25], NL,NL,NL,NL, PGAD+25, NL},
   { &palg[27],35,51, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[26], NL,NL,NL,NL, PGAD+26, NL},
   { &palg[28],51,51, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[27], NL,NL,NL,NL, PGAD+27, NL},
   { &palg[29],67,51, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[28], NL,NL,NL,NL, PGAD+28, NL},
   { &palg[30],83,51, 16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[29], NL,NL,NL,NL, PGAD+29, NL},
   { &palg[31],99,51,16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[30], NL,NL,NL,NL, PGAD+30, NL},
   { &ok_gad, 115,51,16,16, GADGHBOX | GADGIMAGE, RELVERIFY,
      BOOLGADGET,  (APTR)&m3C[31], NL,NL,NL,NL, PGAD+31, NL} };


/* Usato per aprire una Window   */
struct NewWindow NewCmod = {
   40,30, PLX,PLY, 2,BCOL, NL,
   ACTIVATE | SMART_REFRESH,
   &palg[0],NL, NL,    /* PrimoGadget, CheckMark, Titolo  */
   NL,NL,
   PLX,PLY,PLX,PLY, CUSTOMSCREEN }; /* MinW, MinH, MaxW, MaxH */


/********************************************************************
* palette(window)
*    Questa routine apre la window palette e ne tiene il controllo
*    finche' l'utente no seleziona i gadget OK o CANCEL.
********************************************************************/
palette(calling_window)
struct Window *calling_window;
{
struct Window *cW;      /* Manipolazione Window Palette */

FAST struct IntuiMessage *imsg;
FAST struct Gadget *igad;

FAST int class,cursel;
BOOL keepon,munge;

USHORT backup[CTSIZ];        /* Questa tavola ripristina i colori chiamati */

static char hxtab[16] = { '0','1','2','3','4','5','6','7','8',
   '9','a','b','c','d','e','f' };

   for ( cursel=CTSIZ-1; cursel >= 0; cursel--)
      backup[cursel] = p_ct[cursel];

   cursel = 3;

   r_prop.Flags = g_prop.Flags = b_prop.Flags = FREEHORIZ | AUTOKNOB;
   r_prop.HorizBody = g_prop.HorizBody = b_prop.HorizBody = 0x1000;


   NewCmod.Screen = calling_window->WScreen;  /* NEED TO SET SCREEN!!! */
   if ( ! (cW = (struct Window *)OpenWindow(&NewCmod)) ) {
      return(FALSE); /* Oops...  */
      }

   PrintIText(cW->RPort,&mstxt,7,71);

   cW->UserPort = calling_window->UserPort;
   ModifyIDCMP(cW, GADGETUP | GADGETDOWN | MENUVERIFY );

   for ( munge = keepon = TRUE; keepon; ) {

      if ( munge ) {
         SetAPen(cW->RPort,cursel);
         RectFill(cW->RPort,133,3,PLX-5,66);

         r_prop.HorizPot = (p_ct[cursel] & 0xf00) << 4;
         g_prop.HorizPot = (p_ct[cursel] & 0x0f0) << 8;
         b_prop.HorizPot = p_ct[cursel] << 12;
         RefreshGadgets(&red_gad,cW,NL);
         munge = FALSE;
         hxtxt.FrontPen = cursel ^ 15;
         hxtxt.BackPen  = cursel;
         }

      while ( ! (imsg=(struct IntuiMessage *)GetMsg(cW->UserPort)) ) {
         class = p_ct[cursel] = ((r_prop.HorizPot >> 4) & 0xf00) +
            ((g_prop.HorizPot >> 8) & 0xf0) + (b_prop.HorizPot >>12);
         set_cmap();

         frog[0] = hxtab[class >> 8];
         frog[1] = hxtab[ (class >> 4) & 0x0f];
         frog[2] = hxtab[class & 0x0f];
         PrintIText(cW->RPort,&hxtxt,0,0);

         }

      igad =(struct Gadget *) imsg->IAddress;
      if ( (class = imsg->Class) == MENUVERIFY ) {
         imsg->Code = MENUCANCEL;      /* Don't Let Em Out! */
         DisplayBeep(NL);
         }
      ReplyMsg(imsg);

      switch ( class ) {
         case GADGETUP:
         case GADGETDOWN:
            if ((igad->GadgetID >= PGAD)&&(igad->GadgetID < PGAD+CTSIZ)) {
               cursel = igad->GadgetID - PGAD;
               munge = TRUE;
               }
            else switch ( igad->GadgetID ) {
               case PGHI+1:      /* Cancella   */
                  for ( class =0 ; class<CTSIZ; class++)
                     p_ct[class] = backup[class];
                  set_cmap();
               case PGHI:        /* OK */
                  keepon = FALSE;
                  break;

               case PGHI+2:      /* Reset */
                  set_defmap();
                  munge = TRUE;
                  break;
               }
         }
      }

   cW->UserPort = NL;
   CloseWindow(cW);
   return(TRUE);
}


/*************************************************************/

main()
{
init_program();
palette(p_W);
clear_program();
}

