/*
 *
 *            Copywrite (C) 1986 by Davide P. Cervone
 *
 *    Permission is granted for any individual or institution to use,
 *    copy, or redistribute this software, provided this copywrite
 *    notice is retained.
 *
 */

#include "exec/types.h"
#include "exec/devices.h"
#include "libraries/dos.h"
#include "intuition/intuition.h"
#include "intuition/intuitionbase.h"
#include "graphics/gfxbase.h"
#include "graphics/regions.h"
#include "graphics/copper.h"
#include "graphics/gels.h"
#include "devices/keymap.h"
#include "hardware/blit.h"

#include "mxgadget.h"

#define INTUITION_REV 0
#define GRAPHICS_REV 0

#define ERROR_EXIT 10    /* Error number to return on error exit */

struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;


/*
 *  These are the title texts of all the gadgets:
 */

struct IntuiText Title[] = {
   {
      1,0,                /* Text pen colors */
      JAM1,               /* drawing mode */
      30,1,               /* Offset */
      NULL,               /* font */
      "Choice 1",         /* text of message */
      NULL                /* next IntuiText */
   },
   {1,0, JAM1, 30,1, NULL, "Choice 2", NULL},
   {1,0, JAM1, 30,1, NULL, "Choice 3, with Sub-Items", NULL},
   {1,0, JAM1, 30,1, NULL, "Sub-Choice 1", NULL},
   {1,0, JAM1, 30,1, NULL, "Sub-Choice 2", NULL},

   {1,0, JAM1, -4,-12, NULL, "A String, or", NULL},
   {1,0, JAM1, -13,-11, NULL, "A Flag", NULL},

   {3,0, JAM1, 8,2, NULL, "1", NULL},
   {3,0, JAM1, 8,2, NULL, "2", NULL},
   {3,0, JAM1, 8,2, NULL, "4", NULL},
   {3,0, JAM1, 8,2, NULL, "8   Items", NULL},

   {1,0, JAM1, 4,2, NULL, "OK", NULL}
};


/*
 *  These are the border coordinates and border structures for
 *  the gadgets:
 */

USHORT Button[] = {0,0, 25,0, 25,13, 0,13, 0,0};    /* Boarder coordinates */
USHORT StrBox[] = {0,0, 92,0, 92,13, 0,13, 0,0};    /* string border */
USHORT ReqBox[] = {0,0,399,0,399,149,0,149,0,0};    /* Requester border */

struct Border ButtonBrdr = {
   -1,-1,              /* starting position of boarder lines */
   1,0,                /* front and back pens */
   JAM1,               /* Drawing mode */
   5,                  /* Number of points in Button Boarder */
   &Button[0],         /* pointer to outline */
   NULL                /* pointer to next boarder */
};

struct Border StrBoxBrdr  = {-6,-3, 1,0, JAM1, 5, &StrBox[0], NULL};
struct Border RequestBrdr = { 0, 0, 1,0, JAM1, 5, &ReqBox[0], NULL};


/*
 *  These are the image data for the box and the box with an X in it:
 */

USHORT EmptyBoxData[] =
{
   0xFFFF, 0xFC00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xFFFF, 0xFC00
};

USHORT CheckBoxData[] =
{
/* plane 1 */
   0xFFFF, 0xFC00,
   0xF000, 0x3C00,
   0xCC00, 0xCC00,
   0xC303, 0x0C00,
   0xC0CC, 0x0C00,
   0xC030, 0x0C00,
   0xC0CC, 0x0C00,
   0xC303, 0x0C00,
   0xCC00, 0xCC00,
   0xF000, 0x3C00,
   0xFFFF, 0xFC00,
/* plane 2 */
   0xFFFF, 0xFC00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xC000, 0x0C00,
   0xFFFF, 0xFC00
};

struct Image EmptyBox = {
   0,0,                         /* left, top */
   22,11,1,                     /* width, height, depth */
   (USHORT *) &EmptyBoxData,    /* the image data */
   0x1,0x0,                     /* PlanePick, PlaneOnOff */
   NULL                         /* next image */
};

struct Image CheckBox = {
   0,0, 22,11,2, (USHORT *) &CheckBoxData, 0x3,0x0, NULL
};


/*
 * String gadget special info:
 */

char StrBuf[11];                /* string buffer area */

struct StringInfo StrBoxInfo = {
   (UBYTE *) &StrBuf[0],        /* pointer to string buffer area */
   NULL,                        /* UNDO buffer */
   0,                           /* initial cursor position */
   11,                          /* buffer size */
   0,                           /* position of first character in display */
   0,                           /* UNDO position */
   0,                           /* number of chars in the buffer */
   0,                           /* number of characters visiable */
   0,0,                         /* position of left and top of container */
   NULL,                        /* layer pointer */
   0L,                          /* long it value (if INTEGER gadget) */
   NULL                         /* alternate kymao for input */
};


/*
 * These are the gadgets themselves:
 *   the array is a linked list, and is completely initalized here,
 *   so these gadgets can be used without additional initialization code.
 *   They are linked into the Requester structure below.
 */

#define OKGADGET 11      /* This is the gagdet number of the end gadget */

struct Gadget Choice[12] = {
   {
      &Choice[1],         /* Next Gadget */
      60,20, 22,11,       /* left and top edges, width and height */
      GADGIMAGE | SELECTED | GADGHIMAGE,          /* flags */
      GADGIMMEDIATE,      /* activation flags */
      BOOLGADGET | REQGADGET,  /* Boolean requseter gadget */
      (APTR) &EmptyBox,   /* Pointer to Image */
      (APTR) &CheckBox,   /* Pointer to select rendering */
      &Title[0],          /* text for gadget */
      1+2,                /* Mutual Exclude group 1, disable group 2 */
      NULL,               /* special info (PropInfo or StringInfo) */
      0,                  /* identification */
      (APTR) MXDISABLEGADG
         /* This one is pre-selected (SELECTED) and is an IMAGE gadget
            (GADGHIMAGE); it disabled group 2 (MXDISABLEGADG); group 2
            is specified as a disable group by a call to SetMxGadgetMasks in
            the OpenMyWindow procedure */
   },{
      &Choice[2], 60,35, 22,11, GADGIMAGE | GADGHIMAGE,
      GADGIMMEDIATE, BOOLGADGET | REQGADGET,
      (APTR) &EmptyBox, (APTR) &CheckBox, &Title[1],
      1+2,   /* Mutual Exclude group 1, disable group 2 */
      NULL, 1, (APTR) MXDISABLEGADG
   },{
      &Choice[3], 60,50, 22,11, GADGIMAGE | GADGHIMAGE,
      GADGIMMEDIATE, BOOLGADGET | REQGADGET,
      (APTR) &EmptyBox, (APTR) &CheckBox, &Title[2],
      1+2,   /* Mutual Exclude group 1, enable group 2 */
      NULL, 2, (APTR) MXENABLEGADG
         /* This one enables group 2 (MXENABLEGADG), which are
            the sub-choices */
   },{
      &Choice[4], 100,65, 22,11, GADGIMAGE | GADGDISABLED | GADGHBOX,
      GADGIMMEDIATE, BOOLGADGET | REQGADGET,
      (APTR) &EmptyBox, NULL, &Title[3],
      2+4,   /* Mutual Exclude group 4, disabled by group 2 */
      NULL, 3, (APTR) (MXGADGONOFF | MXSELECT)
         /* Disabled when a member of Mutual Exclude group 2 is enabled
            (MXGADGONOFF), start out disabled (GADGDISABLED), but selected
            when enabled (MXSELECT) */
   },{
      &Choice[5], 260,65, 22,11, GADGIMAGE | GADGDISABLED | GADGHBOX,
      GADGIMMEDIATE, BOOLGADGET | REQGADGET,
      (APTR) &EmptyBox, NULL, &Title[4],
      2+4,   /* Mutual Exclude group 4, disabled by group 2 */
      NULL, 4, (APTR) MXGADGONOFF
         /* Disabled when a member of Mutual Exclude group 2 is enabled
            (MXGADGONOFF) and starts out disabled (GADGDISABLED) */
   },{
      &Choice[6], 60,105, 81,8, GADGHCOMP,
      GADGIMMEDIATE | RELVERIFY, STRGADGET | REQGADGET,
      (APTR) &StrBoxBrdr, NULL, &Title[5],
      8,   /* Disabled by group 8 */
      (APTR) &StrBoxInfo, 5, (APTR) MXGADGONOFF
         /* Disabled by mutual exclude group 8 (MXGADGONOFF),
            but starts out enabled */
   },{
      &Choice[7], 190,104, 22,11, GADGIMAGE | GADGHIMAGE,
      GADGIMMEDIATE | TOGGLESELECT, BOOLGADGET | REQGADGET,
      (APTR) &EmptyBox, (APTR) &CheckBox, &Title[6],
      8,   /* Disable members of group 8 */
      NULL, 6, (APTR) MXDISABLEGADG
         /* Disables Mutual Exclude group 8 (MXDISABLEGADG),
            toggles to re-enable it (TOGGLESELECT) */
   },{
      &Choice[8], 130,130, 24,12, GADGHCOMP | SELECTED,
      GADGIMMEDIATE, BOOLGADGET | REQGADGET,
      (APTR) &ButtonBrdr, NULL, &Title[7],
      16,   /* Mutual Exclude group 16 */
      NULL, 7, NULL
         /* Exclude members of group 16, and complement (GADGHCOMP) */
   },{
      &Choice[9], 156,130, 24,12, GADGHCOMP,
      GADGIMMEDIATE, BOOLGADGET | REQGADGET,
      (APTR) &ButtonBrdr, NULL, &Title[8],
      16,   /* Mutual Exclude group 16 */
      NULL, 8, NULL
         /* Exclude members of group 16, and complement (GADGHCOMP) */
   },{
      &Choice[10], 182,130, 24,12, GADGHCOMP,
      GADGIMMEDIATE, BOOLGADGET | REQGADGET,
      (APTR) &ButtonBrdr, NULL, &Title[9],
      16,   /* Mutual Exclude group 16 */
      NULL, 9, NULL
         /* Exclude members of group 16, and complement (GADGHCOMP) */
   },{
      &Choice[11], 208,130, 24,12, GADGHCOMP,
      GADGIMMEDIATE, BOOLGADGET | REQGADGET,
      (APTR) &ButtonBrdr, NULL, &Title[10],
      16,   /* Mutual Exclude group 16 */
      NULL, 10, NULL
         /* Exclude members of group 16, and complement (GADGHCOMP) */
   },{
      NULL, 320,104, 24,12, GADGHCOMP,
      RELVERIFY, BOOLGADGET | REQGADGET,
      (APTR) &ButtonBrdr, NULL, &Title[11],
      0, NULL, OKGADGET, NULL
         /* OK button, this one closes the requester */
         /* it is not a Mutual Exclude gadget */
   }
};


/*
 * This is the requester that uses the gadgets defined above:
 */

struct Requester myRequester =
   {
      NULL,            /* Next requester */
      120,20, 400,150, /* left-edge, top-edge, width, height */
      0,0,             /* relLeft, relRight */
      &Choice[0],      /* first Gadget */
      &RequestBrdr,    /* border */
      NULL,            /* Text */
      NULL,            /* Flags */
      2,               /* Back Fill */
      NULL,            /* Clip region */
      NULL,            /* Bit map */
      NULL             /* other bitmap */
   };


/*
 * This is the window in which the requester will be placed:
 */

struct NewWindow NewWindow = {
   0,0, 640,200,       /* left, top, width, height */
   0,1,                /* detail and block pens */
   GADGETDOWN | GADGETUP,  /* flags */
   WINDOWDEPTH | WINDOWSIZING | WINDOWDRAG | SMART_REFRESH | ACTIVATE,
   NULL,               /* first gadget */
   NULL,               /* check image */
   "Mutual Exclude Gadgets",  /* title */
   NULL,               /* screen */
   NULL,               /* bit map */
   100, 35,            /* min size */
   640, 200,           /* max size */
   WBENCHSCREEN        /* screen type */
};

struct Window *myWindow = NULL;


main()
{
   CheckLibOpen(&IntuitionBase,"intuition.library",INTUITION_REV);
   CheckLibOpen(&GfxBase,"graphics.library",GRAPHICS_REV);
   OpenMyWindow();
   if (Request(&myRequester,myWindow))
   {
      WaitForAction();
      EndRequest(&myRequester,myWindow);
   } else {
      printf("Can't open requester\n");
   }
   DoExit(0);
}

DoExit(status)
int status;
{
   CloseMyWindow();
   CloseLibraries();
   exit(status);
}

CheckLibOpen(lib,name,rev)
APTR **lib;
char *name;
long rev;
{
   if ((*lib = (APTR) OpenLibrary(name,rev)) == NULL)
   {
      printf("Can't open %s\n",name);
      DoExit(ERROR_EXIT);
   }
}

OpenMyWindow()
{
   if ((myWindow = (struct Window *) MxOpenWindow(&NewWindow)) == NULL)
   {
      printf("Can't open my window\n");
      DoExit(ERROR_EXIT);
   } else {
      SetMxGadgetMasks(myWindow,2,8+2);
         /* Mutual Exclude group  2 is an Enable group */
         /* Mutual Exclude groups 8 and 2 are Disable groups */
   }
}

CloseLibraries()
{
   if (IntuitionBase != NULL) CloseLibrary(IntuitionBase);
   IntuitionBase = NULL;
   if (GfxBase != NULL) CloseLibrary(GfxBase);
   GfxBase = NULL;
}

CloseMyWindow()
{
   if (myWindow != NULL) MxCloseWindow(myWindow);
   myWindow = NULL;
}


WaitForAction()
{
   int class,code, NotDone = 1;
   extern struct MenuItem *ItemAddress();
   struct IntuiMessage *NewMessage;
   struct Gadget *theGadget;

   while (NotDone)
   {
      Wait(1 << myWindow->UserPort->mp_SigBit);
      while (NewMessage = (struct IntuiMessage *)GetMsg(myWindow->UserPort))
      {
         class = NewMessage->Class;
         code  = NewMessage->Code;
         switch (class)
         {
            case GADGETDOWN:
               theGadget = (struct Gadget *) NewMessage->IAddress;

/*
 *  This is the call to the mutual exclude gadget handler.  Call
 *  SelectGadget whenever a mutual exclude gadget is selected.  Note that
 *  you can call it for ANY gadget, as SelecteGadget checks whether the
 *  gadget has the mutual exclude flags set.
 */
               SelectGadget(theGadget,myWindow,&myRequester);

               /* do any other stuff with the gadgets here */

               break;

            case GADGETUP:
               theGadget = (struct Gadget *) NewMessage->IAddress;
               if (theGadget->GadgetID == OKGADGET) NotDone = 0;

               /*  if you have RELVERIFY gadgets, do their stuff here */
               /*  Mutual Exclude gadgets should not be RELVERIFY gadgets */

               break;

         }
         ReplyMsg(NewMessage);
      }
   }
}
