char message[] =
 "HP11, by David Gay(86-87). You may freely copy & distribute this program.";
char message2[] =
 "Vous pouvez librement copier & distribuer ce programme.";
#include "exec/types.h"
#include "graphics/text.h"
#include "intuition/intuition.h"
#include "workbench/workbench.h"
#include "workbench/startup.h"
#include "libraries/dos.h"
#include "libraries/arpbase.h"
#include "proto/arp.h"
#define NODOS
#include "libraries/arp_pragmas.h"

#include "proto/exec.h"
#include "proto/graphics.h"
#include "proto/intuition.h"
#include "proto/icon.h"
#include "proto/dos.h"

#include "string.h"
#include "math.h"

#include "hp11/hp11.h"
#include "hp11/io.h"
#include "hp11/ins.h"
#include "hp11/amiga/menus.h"
#include "hp11/amiga/internal.h"
#include "hp11/amiga/cbio.h"

#define PROJECTWIDTH (75 + COMMWIDTH) /* Width of Project menu options */
#define EDITWIDTH (65 + COMMWIDTH)
#define OPTIONSWIDTH 80
#define DECIMALWIDTH (CHECKWIDTH + 65 + COMMWIDTH)
#define SPEEDWIDTH (CHECKWIDTH + 55)

static struct TextAttr topaz9attr = { "topaz.font", 9, 0, 0 }; /* The text font desired */
static struct TextFont *topaz9;

/* Texts for menu options */
static struct IntuiText hp11text[] = {
   { 2, 1, JAM1, 4, 1, NULL, "New", NULL },
   { 2, 1, JAM1, 4, 1, NULL, "Open", NULL },
   { 2, 1, JAM1, 4, 1, NULL, "Save", NULL },
   { 2, 1, JAM1, 4, 1, NULL, "Save as", NULL },
   { 2, 1, JAM1, 4, 1, NULL, "Print", NULL },
   { 2, 1, JAM1, 4, 1, NULL, "Quit", NULL },
   { 2, 1, JAM1, 4, 1, NULL, "Copy", NULL },
   { 2, 1, JAM1, 4, 1, NULL, "Paste", NULL },
   { 2, 1, JAM1, CHECKWIDTH, 1, NULL, "Radix", NULL },
      { 2, 1, JAM1, CHECKWIDTH, 1, NULL, "Point", NULL },
      { 2, 1, JAM1, CHECKWIDTH, 1, NULL, "Comma", NULL },
   { 2, 1, JAM1, CHECKWIDTH, 1, NULL, "Speed", NULL },
      { 2, 1, JAM1, CHECKWIDTH, 1, NULL, "Slow", NULL },
      { 2, 1, JAM1, CHECKWIDTH, 1, NULL, "Fast", NULL },
   { 2, 1, JAM1, CHECKWIDTH, 1, NULL, "Icons", NULL }
};

/* The various menu items */
static struct MenuItem hp11item[] = {
   { &hp11item[1], 0, 0, PROJECTWIDTH, 10, /* New */
     ITEMTEXT | ITEMENABLED | HIGHCOMP, 0,
     (APTR)&hp11text[0], NULL, 0, NULL },

   { &hp11item[2], 0, 10, PROJECTWIDTH, 10, /* Open */
     ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ, 0,
     (APTR)&hp11text[1], NULL, 'O', NULL },

   { &hp11item[3], 0, 20, PROJECTWIDTH, 10, /* Save */
     ITEMTEXT | ITEMENABLED | HIGHCOMP, 0,
     (APTR)&hp11text[2], NULL, 0, NULL },

   { &hp11item[4], 0, 30, PROJECTWIDTH, 10, /* Save as */
     ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ,  0,
     (APTR)&hp11text[3], NULL, 'S', NULL },

   { &hp11item[5], 0, 40, PROJECTWIDTH, 10, /* Print */
     ITEMTEXT | ITEMENABLED | HIGHCOMP, 0,
     (APTR)&hp11text[4], 0, NULL },

   { NULL, 0, 50, PROJECTWIDTH, 10, /* Quit */
     ITEMTEXT | ITEMENABLED | HIGHCOMP, 0,
     (APTR)&hp11text[5], NULL, 0, NULL },


   { &hp11item[7], 0, 0, EDITWIDTH, 10, /* Copy */
     ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ, 0,
     (APTR)&hp11text[6], NULL, 'C', NULL },

   { NULL, 0, 10, EDITWIDTH, 10, /* Paste */
     ITEMTEXT | ITEMENABLED | HIGHCOMP | COMMSEQ, 0,
     (APTR)&hp11text[7], NULL, 'P', NULL },


   { &hp11item[11], 0, 0, OPTIONSWIDTH, 10, /* Radix */
     ITEMTEXT | ITEMENABLED | HIGHCOMP, 0,
     (APTR)&hp11text[8], NULL, 0, &hp11item[9] },

      { &hp11item[10], 50, 9, DECIMALWIDTH, 10, /* Point */
	ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT | CHECKED | COMMSEQ, 2,
	(APTR)&hp11text[9], NULL, '.', NULL },

      { NULL, 50, 19, DECIMALWIDTH, 10, /* Comma */
	ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT | COMMSEQ, 1,
	(APTR)&hp11text[10], NULL, ',', NULL },

   { &hp11item[14], 0, 10, OPTIONSWIDTH, 10, /* Speed */
     ITEMTEXT | ITEMENABLED | HIGHCOMP, 0,
     (APTR)&hp11text[11], NULL, 0, &hp11item[12] },

      { &hp11item[13], 50, 9, SPEEDWIDTH, 10, /* Slow */
	ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT | CHECKED, 2,
	(APTR)&hp11text[12], NULL, 0, NULL },

      { NULL, 50, 19, SPEEDWIDTH, 10, /* Fast */
	ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT, 1,
	(APTR)&hp11text[13], NULL, 0, NULL },

   { NULL, 0, 20, SPEEDWIDTH, 10, /* Icons */
     ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT | CHECKED, 0,
     (APTR)&hp11text[14], NULL, 0, NULL }
};

/* The main menu options */
struct Menu hp11menu[] = {
   { &hp11menu[1], 0, 0, 80, 9, MENUENABLED, "Project", &hp11item[0] },
   { &hp11menu[2], 100, 0, 50, 9, MENUENABLED, "Edit", &hp11item[6] },
   { NULL, 170, 0, 80, 9, MENUENABLED, "Options", &hp11item[8] }
};

/* state of Icons menu option */
static BOOL icons_on = TRUE;

/* filename for save & open, window title */
static char filename[100], undo[100], winname[110];

/* Structures for file requester */
/* ----------------------------- */

static WORD shadowvert[] = { /* Points for shadow of ok/cancel box  */
   2, 15,
   2, 17,
   82, 17,
   82, 1,
   80, 1
};
static struct Border cancelshadow = { 0, 0, 2, 0, JAM1, 5, shadowvert, NULL };
static WORD cancelvert[] = { /* Actual box */
   -1, -1,
   80, -1,
   80, 15,
   -1, 15,
   -1, -1
};
/* This defines a box with shadow 80 points wide */
static struct Border cancelborder = { 0, 0, 2, 0, JAM1, 5, cancelvert, &cancelshadow };

/* The cancel gadget */
static struct IntuiText canceltext = { 2, 1, JAM1, 10, 4, &topaz9attr, "Cancel", NULL };
static struct Gadget cancelgadget = {
   NULL,
   -100, -25, 80, 15, /* it is 100 points from the right, 25 points from
    the bottom & measures 80x15 */
   GADGHCOMP | GRELRIGHT | GRELBOTTOM,
   RELVERIFY | TOGGLESELECT | ENDGADGET,
   BOOLGADGET | REQGADGET,
   (APTR)&cancelborder,
   NULL,
   &canceltext
};

static WORD okvert[] = { /* Box thickening */
   0, 0,
   79, 0,
   79, 14,
   0, 14,
   0, 0
};
static struct Border okborder = { 0, 0, 2, 0, JAM1, 5, okvert, &cancelborder };

/* Ok gadget */
static struct IntuiText oktext = { 2, 1, JAM1, 30, 4, &topaz9attr, "Ok", NULL };
static struct Gadget okgadget = {
   &cancelgadget,
   20, -25, 80, 15,
   GADGHCOMP | GRELBOTTOM,
   RELVERIFY | TOGGLESELECT | ENDGADGET,
   BOOLGADGET | REQGADGET,
   (APTR)&okborder,
   NULL,
   &oktext
};

static WORD bluevert[] = {
   0, 8,
   199, 8
};
static struct Border blueline = { 0, 0, 0, 0, JAM1, 2, bluevert, NULL };

static WORD namevert[] = { /* for filename box */
   -1, -1,
   200, -1,
   200, 9,
   -1, 9,
   -1, -1
};
static struct Border nameborder = { 0, 0, 2, 0, JAM1, 5, namevert, &blueline };

static struct StringInfo nameinfo = {
   filename, undo,
   0, 100, 0
};

static struct IntuiText nametext = { 2, 1, JAM1, -55, 0, &topaz9attr, NULL, NULL };

/* filename gadget */
static struct Gadget namegadget = {
   &okgadget,
   62, 10, 200, 9,
   GADGHCOMP,
   ENDGADGET,
   STRGADGET | REQGADGET,
   (APTR)&nameborder,
   NULL,
   &nametext,
   0,
   (APTR)&nameinfo
};

static WORD filevert[] = { /* for the complete requester */
   0, 0,
   269, 0,
   269, 59,
   0, 59,
   0, 0
};
static struct Border fileborder = { 0, 0, 2, 0, JAM1, 5, filevert, NULL };

/* The actual requester */
static struct Requester filereq = {
   NULL,
   25, 65,
   270, 60,
   0, 0,
   &namegadget,
   &fileborder,
   NULL,
   0,
   1
};

/* Message requester */
/* ----------------- */
static struct IntuiText msgtext = { 2, 1, JAM1, 10, 10, &topaz9attr, NULL, NULL };

static struct Gadget msgokgadget = {
   NULL,
   20, -25, 80, 15, /* Message inits LeftEdge */
   GADGHCOMP | GRELBOTTOM,
   RELVERIFY | TOGGLESELECT | ENDGADGET,
   BOOLGADGET | REQGADGET,
   (APTR)&okborder,
   NULL,
   &oktext
};

static WORD msgvert[][2] = {
   0, 0,
   0, 0,
   0, 59,
   0, 59,
   0, 0
};
static struct Border msgborder = { 0, 0, 2, 0, JAM1, 5, msgvert, NULL };

static struct Requester msgreq = {
   NULL,
   0, 65, /* LeftEdge is initialised by Message */
   0, 60, /* Width also */
   0, 0,
   &msgokgadget,
   &msgborder,
   &msgtext,
   0,
   1
};

/* struct DiskObject {
    int a;
};  Little problem: DiskObject def lost !!! */

struct Library *IconBase; /* for the icon library */
struct ArpBase *ArpBase; /* Arp lib */
extern char tool[]; /* Path to hp11 program */
extern struct DiskObject prog_icon;
static BOOL clip;

void LoadProg(void), OpenProg(void), StoreProg(void), SaveProg(void), Copy(void), Paste(void);

BOOL MenusInit(argc, argv)
int argc;
APTR argv;
#define argw ((struct WBStartup *)argv)
#define arg1 (argw->sm_ArgList[1])
{
   char path[PATHLEN];

   topaz9 = OpenFont(&topaz9attr); /* Open the desired font */

   IconBase = OpenLibrary("icon.library", 0);
   if (!IconBase) { /* no icon library, disable icons */
      icons_on = FALSE;
      hp11item[14].Flags &= ~(CHECKED | ITEMENABLED);
   }
   ArpBase = OpenLibrary("arp.library", 0);

   /* Set up tool path */
   strcat(strcpy(tool, hp11path), hp11name);

   if (!(clip = !CBOpen(0))) /* Disable clip options if no clipboard */
      hp11menu[1].Flags = NULL;

   SetMenuStrip(hp11, hp11menu);

   if (argc != 0) { /* CLI */
      icons_on = FALSE;
      hp11item[14].Flags &= ~CHECKED; /* by default, no icons from cli */
      if (argc > 1) { /* argument */
	 strcpy(filename, ((char **)argv)[1]);
	 LoadProg();
      }
   }
   else if (argw->sm_NumArgs > 1) { /* workbench, with argument */
      if (!mygetpath(path, arg1.wa_Lock)) path[0] = '\0';
      strcpy(filename, strcat(path, arg1.wa_Name));
      LoadProg();
   }
   return(TRUE);
}
#undef arg1
#undef argw

void MenusCleanUp()
{
   if (hp11) ClearMenuStrip(hp11);
   if (clip) CBClose();
   if (ArpBase) CloseLibrary(ArpBase);
   if (IconBase) CloseLibrary(IconBase);
   if (topaz9) CloseFont(topaz9);
}

/* Enable menus */
void MenusOn(void)
{
   SetMenuStrip(hp11, hp11menu);
}

/* Disable menus */
void MenusOff(void)
{
   ClearMenuStrip(hp11);
}

void EditOn(void)
{
   if (clip) OnMenu(hp11, SHIFTMENU(1) | SHIFTITEM(NOITEM));
}

void EditOff(void)
{
   OffMenu(hp11, SHIFTMENU(1) | SHIFTITEM(NOITEM));
}

/* The menu handler, number represents the chosen option */
int MenuHandler(UWORD number)
{
   register struct MenuItem *item;
   register int key = -1;

   MenusOff(); /* Disable menus */

   while (number != MENUNULL) {

      switch (MENUNUM(number)) {
	 case 0: /* Project */
	    switch (ITEMNUM(number)) {
	       case 0: /* New */ HP11ColdReset(); key = BRESET; break; /* back to main loop */
	       case 1: /* Open */ OpenProg(); key = BRESET; break;
	       case 2: /* Save */ StoreProg(); break;
	       case 3: /* Save as */ SaveProg(); break;
	       case 4: /* Print */ break;
	       case 5: /* Quit */ quit = TRUE; key = BRESET; break;
	    }
	    break;
	 case 1: /* Edit */
	    switch (ITEMNUM(number)) {
	       case 0: /* Copy */ Copy(); break;
	       case 1: /* Paste */ Paste(); key = BDISPLAY; break;
	    }
	    break;
	 case 2: /* Options */
	    switch (ITEMNUM(number)) {
	       case 0: /* Radix */
		  comma = SUBNUM(number); /* false for Point, true for Comma */
		  key = BDISPLAY; /* Redisplay */
		  break;
	       case 1: /* Speed */
		  fast = SUBNUM(number); /* false for Slow, true for Fast */
		  break;
	       case 2: /* Icons */
		  icons_on = !icons_on;

		  /* Toggle flag */
		  if (icons_on) hp11item[14].Flags |= CHECKED;
		  else hp11item[14].Flags &= ~CHECKED;

		  break;
	    }
	    break;
      }

      item = ItemAddress(hp11menu, (long)number);
      number = item->NextSelect;
   }

   MenusOn();
   return(key);
}

/* Display an error message */
void Message(text)
char *text;
{
   register int width;

   msgtext.IText = text;
   width = IntuiTextLength(&msgtext) + 20; /* width of requester */
   if (width < 100) width = 100; /* min width */
   msgokgadget.Flags &= ~SELECTED;
   msgreq.Width = width;
   msgreq.LeftEdge = (HP11WIDTH - width) >> 1; /* center rqeuester */
   msgokgadget.LeftEdge = (width >> 1) - 40; /* center OK */
   msgvert[1][0] = width - 1;
   msgvert[2][0] = width - 1;

   Request(&msgreq, hp11);
}

/* Read a file name, text is displayed to the left of the name box.
  Return FALSE if cancel selected, TRUE otherwise */
static BOOL GetFile(char *text)
{
   ULONG saveIDCMP;
   struct IntuiMessage *msg;
   int done;

   if (ArpBase) /* Use arp file req */
   {
      static char directory[DSIZE + 1];
      static struct FileRequester FR;

      filename[0] = '\0';
      FR.fr_Hail = text;
      FR.fr_File = filename;
      FR.fr_Dir = directory;

      if (FileRequest(&FR))
      {
	  long lock = Lock(directory, SHARED_LOCK);

	  if (lock)
	  {
	      CurrentDir(lock);
	      return TRUE;
	  }
      }
      return FALSE;
   }
   else
   {
      nametext.IText = text;
      okgadget.Flags &= ~SELECTED;
      cancelgadget.Flags &= ~SELECTED;

      saveIDCMP = hp11->IDCMPFlags;
      ModifyIDCMP(hp11, REQCLEAR | REQSET);
      Request(&filereq, hp11);
      do {
	     WaitPort(hp11->UserPort); /* Wait for requester to appear */
	 msg = GetMsg(hp11->UserPort);
	 done = msg->Class == REQSET;
	 ReplyMsg(msg);
      } while (!done);

      ActivateGadget(&namegadget, hp11, &filereq);

      do {
	 WaitPort(hp11->UserPort); /* Wait for requester to disappear */
	 msg = GetMsg(hp11->UserPort);
	 done = msg->Class == REQCLEAR;
	 ReplyMsg(msg);
      } while (!done);

      ModifyIDCMP(hp11, saveIDCMP);

      if (!(cancelgadget.Flags & SELECTED))
      {
	 CurrentDir(DupLock(CurrentDir(0)));
	 return TRUE;
      }
      else
	 return FALSE;
   }
}

static void SetTitle(void)
{
   SetWindowTitles(hp11, strcat(strcpy(winname, "HP11C - "), filename), (char *)(long)-1);
}

static int FileType(struct DiskObject *icon, char *type)
{
   char *value;

   if (!(value = FindToolType(icon->do_ToolTypes, "FILETYPE"))) return(FALSE);
   return((int)MatchToolValue(value, type));
}

static void LoadProg()
{
   LONG file;
   struct Regs newhp11;
   struct DiskObject *icon = NULL;
   BYTE dummy;

   if (IconBase && (icon = GetDiskObject(filename)) &&
       !FileType(icon, "HP11")) {
      Message("This isn't an HP11 program");
      goto exit;
   }

   if (file = Open(filename, MODE_OLDFILE)) {
      if ((Read(file, (char *)&newhp11, sizeof(struct Regs)) == sizeof(struct Regs))
	  && (Read(file, &dummy, 1) != 1)) { /* dummy read to check file size */
	    hp11r = newhp11; /* Set new internal state */
	    running = FALSE; /* Interrupt program */
	    PC = 0;
	    retCnt = 0;
	    ENABLE();

	    SetTitle();
	 }
	 else Message("This isn't an HP11 program");
      Close(file);
   }
   else Message("Couldn't open file");

exit: if (icon) FreeDiskObject(icon);
}

/* Save current state under current filename */
static void StoreProg()
{
   LONG file;
   struct DiskObject *temp_icon;

   file = Open(filename, MODE_NEWFILE);
   if (!file) Message("Couldn't open file");
   else {
      if (Write(file, (char *)&hp11r, sizeof(struct Regs)) != sizeof(struct Regs))
	 Message("Error writing the file");
      else {
	 SetTitle();
	 if (icons_on)
	    if (!(temp_icon = GetDiskObject(filename)))
	       PutDiskObject(filename, &prog_icon);
	    else FreeDiskObject(temp_icon);
      }
      Close(file);
   }
}

/* Save current state under a filename */
static void SaveProg()
{
   BPTR cdir, new;

   CurrentDir(cdir = CurrentDir(0));

   if (GetFile("Save:"))
   {
      StoreProg();
      if (new = CurrentDir(cdir)) UnLock(new);
   }
}

/* Load the hp11 state */
static void OpenProg()
{
   BPTR cdir, new;

   CurrentDir(cdir = CurrentDir(0));

   if (GetFile("Open:")) /* Get file name */
   {
      LoadProg();
      if (new = CurrentDir(cdir)) UnLock(new);
   }
}

static void Copy()
{
   CBCut(NbStr(X));
}

static void Paste()
{
   char buf[256];

   if (CBPaste(buf)) {
      Enter(); ENABLE();
      X = Check(atof(buf));
   }
}

