/* This is needed for Lattice bug with 16 bit ints */
#undef RMBTRAP
#define RMBTRAP 0x00010000L


#define SHOWSINGLEMENU	   0
#define SUBITEMPOINTER	   1
#define ITEMSCENTERED	   2
#define POPUPWITHQUAL	   3
#define POPUPNOQUAL	   4
#define CLICKMENUES	   5
#define OPENWINDOW	   6
#define EXIT		   7

#define RESET		   0x100
#define CANCEL		   0x200
#define REMOVE		   0x300
#define USE		   0x400

#define HOTKEYQUAL	   (IEQUALIFIER_CONTROL|IEQUALIFIER_LALT)
static USHORT
  chip CheckOffData[] = {0x0000,0x0000, 0x07f0,0x0000, 0x3c1e,0x0000,
			 0x6003,0x0000, 0xc001,0x8000, 0xc001,0x8000,
			 0xc001,0x8000, 0x6003,0x0000, 0x3c1e,0x0000,
			 0x07f0,0x0000},
  chip CheckOnData[]  = {0x0000,0xf000, 0x07f3,0xf800, 0x3c1f,0xf000,
			 0x7e3f,0xe000, 0xff7f,0x8000, 0xdffd,0x8000,
			 0xcff1,0x8000, 0x67e3,0x0000, 0x3fde,0x0000,
			 0x07f0,0x0000,
			 0x0000,0x0000, 0x0000,0xf000, 0x0003,0xe000,
			 0x1c0f,0x0000, 0x1e3c,0x0000, 0x0f70,0x0000,
			 0x07e0,0x0000, 0x03c0,0x0000, 0x0180,0x0000,
			 0x0000,0x0000},

  chip LogoData[]    = { 0x7FF0,0x0000,0x6180,0x0780,0x0800,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x8C18,0x0000,0xE180,0x08C0,0x1800,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x0C18,0x0000,0x6180,0x00E0,0x3800,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x0C10,0xF8CC,0x618C,0xC0F0,0x783C,0x2618,0xC000,0x0000,0x0080,0x7000,
			 0x0FE1,0x0DD6,0x619D,0x60D8,0xD846,0x6B38,0xC000,0x0000,0x0480,0x8800,
			 0x0C03,0x0CE6,0x618E,0x60CD,0x98C4,0xF318,0xC004,0x4E58,0x0480,0x3000,
			 0x0C03,0x0CC6,0x63AC,0x60C7,0x19F8,0x6359,0xD004,0x5224,0x07C0,0x0800,
			 0x0C03,0x08C4,0x65CC,0x40C2,0x1AC2,0x639A,0xE002,0x9420,0x0084,0x8800,
			 0x0C01,0xF0F8,0x398F,0x8080,0x1C7C,0x630C,0x4001,0x0F20,0x01C4,0x7000,
			 0x1000,0x00C0,0x000C,0x0700,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x0000,0x00C0,0x000C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x0000,0x00C0,0x000C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x0000,0x00C0,0x000C,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x0000,0x0080,0x0008,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,

			 0x7FF0,0x0000,0x6180,0x0780,0x09C0,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x9FFC,0x0000,0xF9E0,0x09E0,0x1A70,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x2FFF,0x0000,0x7FF8,0x02F8,0x3E80,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x0FD7,0xF8CC,0x7FFC,0xC0FC,0x7FBC,0x2618,0xC000,0x0000,0x0000,0x0000,
			 0x0FE5,0xBFF7,0x7FFF,0x70FE,0xDFCF,0x6BBE,0xF000,0x0000,0x0000,0x0000,
			 0x0FFB,0x4FFF,0xFFFF,0xFCFF,0xBFD7,0xFBFF,0xFC00,0x0000,0x0000,0x0000,
			 0x0FFF,0xDFFF,0xFFFF,0xFEFF,0xFFFD,0x7FFF,0xFC00,0x0000,0x0000,0x0000,
			 0x0FC3,0xFBFF,0xFFFF,0xFEFF,0xDFFE,0x7FFF,0xFC00,0x0000,0x0000,0x0000,
			 0x0FC1,0xF2FD,0x7FFF,0xD6BC,0xFFFF,0xFFFF,0xFD00,0x0000,0x0000,0x0000,
			 0x13C0,0x7CFE,0x4E7F,0xE72C,0x27BF,0x3EFB,0xBE00,0x0000,0x0000,0x0000,
			 0x04C0,0x1FFF,0x839F,0xF9C8,0x01C7,0xC630,0xC400,0x0000,0x0000,0x0000,
			 0x0100,0x00FC,0x000F,0xC070,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x0000,0x00FC,0x000F,0xC000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x0000,0x00BC,0x000B,0xC000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
			 0x0000,0x002C,0x0002,0xC000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000},

  chip NameData[]     = {0x899C,0xEE88,0x339C,0xE644,
			 0xDA52,0x44C8,0x4A52,0x4964,
			 0xABDC,0x44A8,0x7A5C,0x4F54,
			 0x8A52,0x4498,0x4A52,0x494C,
			 0x8A52,0x4E88,0x4B92,0xE944,
			 0x0000,0x0000,0x0000,0x0000,
			 0x0000,0x04C6,0x6000,0x0000,
			 0x0000,0x0D29,0x1000,0x0000,
			 0x0000,0x04E7,0x2000,0x0000,
			 0x0000,0x0421,0x4000,0x0000,
			 0x0000,0x0EC6,0x7000,0x0000};

	      /* Normal gadget */
static struct Image
  CheckOff = { 0, 0, 21, 10, 1, CheckOffData, 1, 0, NULL },
	     /* Selected gadget */
  CheckOn  = { 0, 0, 21, 10, 2, CheckOnData,  3, 0, NULL },
	     /* Name */
  Name	   = {170,3, 63, 11, 1, NameData,     1, 0, NULL },
	     /* PopUpMenu Logo */
  Logo	   = { 0, 0,149, 15, 2, LogoData,     3, 0, &Name};

	     /* Upper & left border for small gadget */
static SHORT
  UpperVectors1[] = {  0, 0,   0,13,   1,12,   1, 0,  58, 0 },
	     /* Lower & right border for small gadget */
  LowerVectors1[] = { 59,13,  59, 0,  58, 1,  58,13,   1,13 },
	     /* Upper & left border for big gadget */
  UpperVectors2[] = {  0, 0,   0,13,   1,12,   1, 0, 148, 0 },
	     /* Lower & Right border for big gadget */
  LowerVectors2[] = {149,13, 149, 0, 148, 1, 148,13,   1,13 };

	     /* Small border */
static struct Border
  UpBorder1b  = {-2,-1, 2,0,JAM1, 5, LowerVectors1, NULL	 },
  UpBorder1a  = {-2,-1, 1,0,JAM1, 5, UpperVectors1, &UpBorder1b  },
	     /* Big border */
  UpBorder2b  = {-2,-1, 2,0,JAM1, 5, LowerVectors2, NULL	 },
  UpBorder2a  = {-2,-1, 1,0,JAM1, 5, UpperVectors2, &UpBorder2b  };

static char
  UseText[]    = {'U','s','e',0},
  ResetText[]  = {'R','e','s','e','t',0},
  CancelText[] = {'C','a','n','c','e','l',0},

  RemoveText[] = {'R','e','m','o','v','e',' ','P','o','p','U','p','M','e','n','u',0},
  ClickText[]  = {'"','C','l','i','c','k','"',' ','m','e','n','u','e','s',' ','(','C',')',0},
  SubText[]    = {'S','u','b','-','i','t','e','m',' ','p','o','i','n','t','e','r',' ','(','P',')',0},
  ItemsText[]  = {'M','e','n','u','i','t','e','m','s',' ','c','e','n','t','e','r','e','d',' ','(','I',')',0},
  SingleText[] = {'S','h','o','w',' ','s','i','n','g','l','e',' ','m','e','n','u',' ','(','S',')',0},
  PopUpText[]  = {'P','o','p','-','u','p',' ','m','e','n','u','e','s',0},
  WithText[]   = {'w','i','t','h',' ','(','W',')',0},
  WithoutText[]= {'w','i','t','h','o','u','t',' ','(','N',')',0},
  QualText[]   = {'q','u','a','l','i','f','i','e','r','s',0},
  HotKeyText[] = {'H','o','t','k','e','y',':',' ','C','T','R','L',' ','+',' ','A','L','T',' ','+',0},

  KeyText[]   = {'Q',0},
  BlankText[] = {' ',0};

static struct TextAttr
  Topaz80 = {"topaz.font", TOPAZ_EIGHTY, 0, 0 };

static struct IntuiText
  WinText13b = {1,0,JAM1, 93, 30, &Topaz80, ClickText,	NULL	   },
  WinText13a = {2,0,JAM1, 95, 31, &Topaz80, ClickText,	&WinText13b},
  WinText12b = {1,0,JAM1, 93, 45, &Topaz80, SubText,	&WinText13a},
  WinText12a = {2,0,JAM1, 95, 46, &Topaz80, SubText,	&WinText12b},
  WinText11b = {1,0,JAM1, 93, 60, &Topaz80, SingleText, &WinText12a},
  WinText11a = {2,0,JAM1, 95, 61, &Topaz80, SingleText, &WinText11b},
  WinText10b = {1,0,JAM1, 93, 75, &Topaz80, ItemsText,	&WinText11a},
  WinText10a = {2,0,JAM1, 95, 76, &Topaz80, ItemsText,	&WinText10b},
  WinText09b = {1,0,JAM1,  5,100, &Topaz80, PopUpText,	&WinText10a},
  WinText09a = {2,0,JAM1,  7,101, &Topaz80, PopUpText,	&WinText09b},
  WinText08b = {1,0,JAM1,137, 92, &Topaz80, WithText,	&WinText09a},
  WinText08a = {2,0,JAM1,139, 93, &Topaz80, WithText,	&WinText08b},
  WinText07b = {1,0,JAM1,137,107, &Topaz80, WithoutText,&WinText08a},
  WinText07a = {2,0,JAM1,139,108, &Topaz80, WithoutText,&WinText07b},
  WinText06b = {1,0,JAM1,225,100, &Topaz80, QualText,	&WinText07a},
  WinText06a = {2,0,JAM1,227,101, &Topaz80, QualText,	&WinText06b},
  WinText05b = {1,0,JAM1, 67,122, &Topaz80, HotKeyText, &WinText06a},
  WinText05a = {2,0,JAM1, 69,123, &Topaz80, HotKeyText, &WinText05b};

#define FIRSTWINTEXT WinText05a

/****************** Gadget text **********************/
static struct IntuiText
  UseIText1   = {3,0,JAM1, 17,2, &Topaz80, UseText,    NULL	  },
  UseIText    = {2,0,JAM1, 19,3, &Topaz80, UseText,    &UseIText1 },
  ResIText1   = {3,0,JAM1,  9,2, &Topaz80, ResetText,  NULL	  },
  ResIText    = {2,0,JAM1, 11,3, &Topaz80, ResetText,  &ResIText1 },
  CancIText1  = {3,0,JAM1,  5,2, &Topaz80, CancelText, NULL	  },
  CancIText   = {2,0,JAM1,  7,3, &Topaz80, CancelText, &CancIText1},
  RemIText1   = {3,0,JAM1,  5,2, &Topaz80, RemoveText, NULL	  },
  RemIText    = {2,0,JAM1,  7,3, &Topaz80, RemoveText, &RemIText1 };

/* Hotkey */
static struct IntuiText
  HotKeyIText2 = {1,0,JAM1,235,122, &Topaz80, KeyText,	 NULL	       },
  HotKeyIText1 = {2,0,JAM2,237,123, &Topaz80, KeyText,	 &HotKeyIText2 },
  HotKeyIText  = {1,0,JAM2,235,122, &Topaz80, BlankText, &HotKeyIText1 };

/****************** All gadgets *********************/
static struct Gadget
  ClickGad  = {NULL, 70,28, 135,10, GADGHIMAGE | GADGIMAGE,
	       RELVERIFY | TOGGLESELECT,
	       BOOLGADGET, (APTR)&CheckOff, (APTR)&CheckOn,
	       NULL, 0, NULL, 1<<CLICKMENUES, NULL },
  SubGad    = {&ClickGad, 70,43,  151,10, GADGHIMAGE | GADGIMAGE,
	       RELVERIFY | TOGGLESELECT,
	       BOOLGADGET, (APTR)&CheckOff, (APTR)&CheckOn,
	       NULL, 0, NULL, 1<<SUBITEMPOINTER, NULL },
  ShowGad   = {&SubGad, 70,58, 151,10, GADGHIMAGE | GADGIMAGE,
	       RELVERIFY | TOGGLESELECT,
	       BOOLGADGET, (APTR)&CheckOff, (APTR)&CheckOn,
	       NULL, NULL, NULL, 1<<SHOWSINGLEMENU, NULL },
  ItemGad   = {&ShowGad, 70,73, 167,10, GADGHIMAGE | GADGIMAGE,
	       RELVERIFY | TOGGLESELECT,
	       BOOLGADGET, (APTR)&CheckOff, (APTR)&CheckOn,
	       NULL, NULL, NULL, 1<<ITEMSCENTERED, NULL },
  WithGad   = {&ItemGad, 114,90, 55,10, GADGHIMAGE | GADGIMAGE,
	       RELVERIFY | TOGGLESELECT,
	       BOOLGADGET, (APTR)&CheckOff, (APTR)&CheckOn,
	       NULL, NULL, NULL, 1<<POPUPWITHQUAL, NULL },
  WithoutGad= {&WithGad, 114,105, 79,10, GADGHIMAGE | GADGIMAGE,
	       RELVERIFY | TOGGLESELECT,
	       BOOLGADGET, (APTR)&CheckOff, (APTR)&CheckOn,
	       NULL, NULL, NULL, 1<<POPUPNOQUAL, NULL },
  RemoveGad = {&WithoutGad, 80,165, 145,12, GADGHCOMP, RELVERIFY,
	       BOOLGADGET, (APTR)&UpBorder2a, NULL,
	       &RemIText, NULL, NULL, REMOVE, NULL },
  UseGad    = {&RemoveGad,230,145, 56,12, GADGHCOMP, RELVERIFY,
	       BOOLGADGET, (APTR)&UpBorder1a, NULL,
	       &UseIText, NULL, NULL, USE, NULL },
  ResetGad  = {&UseGad,   121,145, 56,12, GADGHCOMP, RELVERIFY,
	       BOOLGADGET, (APTR)&UpBorder1a, NULL,
	       &ResIText, NULL, NULL, RESET, NULL },
  CancelGad = {&ResetGad, 18,145, 56,12, GADGHCOMP,  RELVERIFY,
	       BOOLGADGET, (APTR)&UpBorder1a, NULL,
	       &CancIText, NULL, NULL, CANCEL, NULL };

#define FIRSTGADGET CancelGad

static struct NewWindow OptionWindow = {
  165,55, 310,185,  0,1,
  GADGETUP | RAWKEY,
  RMBTRAP | WINDOWDRAG | WINDOWDEPTH | ACTIVATE | NOCAREREFRESH, &FIRSTGADGET,
  NULL, "PopUpMenu", NULL, NULL, 0,0,0,0, WBENCHSCREEN};

static SHORT
  WindowBorder[] = { 1,184, 308,184, 308,0,  309,0, 309,184 };

static struct Border
  WBorder = { 0,0, 2,0, JAM1, 5, WindowBorder, NULL};

/*** These must be global (Init them to NULL to put them in the Data segment) */
static struct Window *Win = NULL;
static struct IntuitionBase *IntuitionBase = NULL;

       USHORT SelectOpt(USHORT CurrOptions);
STATIC VOID   FixGadgets(UBYTE Options);
STATIC UBYTE  DoHotKeyReq(struct Window *Win, UBYTE RawKey);
STATIC UBYTE  Raw2ASCII(UBYTE Code);
STATIC VOID   PrintHotKey(UBYTE Key);

/*VOID main()*/
/*{*/
  /* The libraries MUST be opened in this or a similar manner in     */
  /* order to use pop-up menus. 				     */

/*  IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0L);*/
/*  printf("%x",SelectOpt(0x0f55));*/
/*  CloseLibrary((struct Library *)IntuitionBase);*/
/*}*/

USHORT SelectOpt(CurrOptions)
  USHORT CurrOptions;
{
  /* Can't reach global IntuitionBase from C */
  UBYTE Options;
  UBYTE HotKey;
  char	Buf[16];

  UBYTE Quit = 0;

  CurrOptions &= ~((1<<EXIT) | (1<<OPENWINDOW));
  Options = CurrOptions>>8;
  HotKey = CurrOptions & 0xff;

  IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);

  if (IntuitionBase) {
    if (IntuitionBase->LibNode.lib_Version >= 37) { /* Kickstart 2.0 ? */
      USHORT *Temp1 = Logo.ImageData; /*&LogoData[0];*/
      USHORT *Temp2 = Temp1+150;
      USHORT i;

      for (i = 0; i < 150; i++, Temp1++, Temp2++)
	*Temp1 ^= *Temp2 ^= *Temp1 ^= *Temp2;

      /* Switch BLACK and WHITE */
      WinText13b.FrontPen = WinText12b.FrontPen = WinText11b.FrontPen =
      WinText10b.FrontPen = WinText09b.FrontPen = WinText08b.FrontPen =
      WinText07b.FrontPen = WinText06b.FrontPen = WinText05b.FrontPen =
      UseIText1.FrontPen  = ResIText1.FrontPen	= CancIText1.FrontPen =
      RemIText1.FrontPen  = UpBorder1a.FrontPen = UpBorder2a.FrontPen =
      OptionWindow.BlockPen = HotKeyIText2.FrontPen = Name.PlanePick = 2;

      WinText13a.FrontPen = WinText12a.FrontPen = WinText11a.FrontPen =
      WinText10a.FrontPen = WinText09a.FrontPen = WinText08a.FrontPen =
      WinText07a.FrontPen = WinText06a.FrontPen = WinText05a.FrontPen =
      UseIText.FrontPen   = ResIText.FrontPen	= CancIText.FrontPen  =
      RemIText.FrontPen   = UpBorder1b.FrontPen = UpBorder2b.FrontPen =
      WBorder.FrontPen	  = HotKeyIText1.FrontPen = 1;
    }

    WBenchToFront();
    if (GetScreenData(Buf,16,WBENCHSCREEN,NULL)) {    /* Get size of Workbench Screen */
      OptionWindow.LeftEdge = (USHORT)((((struct Screen *)Buf)->Width - 310))/2;
      OptionWindow.TopEdge  = (USHORT)((((struct Screen *)Buf)->Height - 185))/2;

      FixGadgets(Options);

      if (Win = OpenWindow(&OptionWindow)) {
	struct MsgPort *Port = Win->UserPort;

	if (IntuitionBase->LibNode.lib_Version < 37)
	  DrawBorder(Win->RPort, &WBorder, 0, 0);

	PrintIText(Win->RPort, &FIRSTWINTEXT, 0, 0);
	PrintHotKey(Raw2ASCII(HotKey));
	DrawImage(Win->RPort, &Logo, 74, 11);

	do {
	  struct IntuiMessage *Message;

	  WaitPort(Port);

	  while (Message = (struct IntuiMessage *)GetMsg(Port)) {
	    USHORT ID = 0;

	    if (Message->Class == RAWKEY) {
	      if ((Message->Qualifier & 0x01f8) == HOTKEYQUAL) {
		UBYTE Key = Raw2ASCII((UBYTE)Message->Code);

		if (Key > ' ') {
		  HotKey = Message->Code;
		  KeyText[0] = Key;
		  PrintHotKey(Key);
		}
	      }
	      else if ((Message->Qualifier & 0x01f8) == 0) { /* only shift allowed */
		STATIC char Keys[] = {'\x1b','R','\r','X','N','W','I','S','P','C'};
		STATIC WORD Code[] = {CANCEL, RESET, USE, REMOVE,
				      0x10,0x08,0x04,0x01,0x02,0x20};
		struct Gadget *TempGad = &FIRSTGADGET;
		UBYTE Key = Raw2ASCII((UBYTE)Message->Code);
		USHORT i;

		for (i = 0; i < sizeof(Keys); i++, TempGad = TempGad->NextGadget)
		  if (Key == Keys[i]) {
		    ID = Code[i];
		    if (ID < RESET) {
		      TempGad->Flags ^= SELECTED;
		      RefreshGadgets(&WithoutGad,Win,NULL);
		    }
		    break;
		  }
	      }
	    }
	    else if (Message->Class == GADGETUP)
	      ID = ((struct Gadget *)(Message->IAddress))->GadgetID;

	    if (ID)
	      if (ID & 0xff)
		Options ^= ID;
	      else
		switch(ID) {
		  case RESET:
		    Options = CurrOptions>>8;
		    HotKey  = CurrOptions & 0xff;
		    PrintHotKey(Raw2ASCII(HotKey));
		    FixGadgets(Options);
		    RefreshGadgets(&WithoutGad,Win,NULL);
		    break;
		  case USE:
		    Quit = 1;
		    break;
		  case CANCEL:
		    Quit = 2;
		    break;
		  case REMOVE:
		    Options |= 1<<EXIT;
		    Quit = 1;
		    break;
		} /* switch */

	    ReplyMsg((struct Message *)Message);
	  } /* while */
	} /* do */
	while (!Quit);

	CloseWindow(Win);
      } /* if (Win == ... */
    } /* if (GetScreenData ...) */

    CloseLibrary((struct Library *)IntuitionBase);
  } /* if (IntuitionBase) */

  if (Quit == 1)
    return (USHORT)((Options<<8) + HotKey);
  else
    return CurrOptions;
}

STATIC VOID FixGadgets(Options)
  UBYTE Options;
{
  struct Gadget *TempGad = &WithoutGad;

  do
    if (Options & TempGad->GadgetID)
      TempGad->Flags |= SELECTED;
    else
      TempGad->Flags &= ~SELECTED;
  while (TempGad = TempGad->NextGadget);
}

STATIC UBYTE Raw2ASCII(Code)
  UBYTE Code;
{
  static struct InputEvent IEvent = { NULL, IECLASS_RAWKEY, 0, 0, IEQUALIFIER_CAPSLOCK }; /* reset to 0 */
  struct Library *ConsoleDevice;
  struct IOStdReq CIO;
  UWORD  Length;
  UBYTE  Buf[4];

  OpenDevice("console.device",-1,(struct IORequest *)&CIO, 0);
  ConsoleDevice = (struct Library *)CIO.io_Device;

  IEvent.ie_Code = Code;
  Length = RawKeyConvert(&IEvent,Buf,4,NULL);

  CloseDevice((struct IORequest *)&CIO);

  if (Length == 1)
    return Buf[0];
  else
    return 0;
}

STATIC VOID PrintHotKey(Key)
  UBYTE Key;
{
  KeyText[0] = Key;
  PrintIText(Win->RPort,&HotKeyIText,0,0);
}

