char version [] = "$VER: HP11 1.2 (10.09.1998) by David Gay and Dirk Stöcker";

#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include <proto/timer.h>
#include <proto/wb.h>
#include <proto/dos.h>
#include <proto/icon.h>
#include <proto/asl.h>
#include <proto/gadtools.h>
#include <exec/memory.h>

#include <string.h>
#include <ctype.h>

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

#define FILENAMESIZE	256

#define HP11WIDTH 319 /* Drawing size */
#define HP11HEIGHT 181
#define HP11X 3
#define HP11Y 11

#define MAXWIDTH 29 /* X distance between 2 keys */
#define MAXHEIGHT 29 /* Y distance bewteen 2 keys */
#define KEYWIDTH 20 /* Width of actual key */
#define KEYHEIGHT 16 /* Height of actual key */
#define TOPKEYHEIGHT 9 /* Height of top of key */
#define KEYX (19 + HP11X) /* Position of first key */
#define KEYY (61 + HP11Y)
#define CHAROFFX -1 /* offset in display for first char */
#define CHAROFFY 3
#define CHARWIDTH 14 /* Size of char */
#define CHARHEIGHT 13
#define SCRX0 (53 + HP11X) /* Limits of display for chars */
#define SCRX1 (207 + HP11X)
#define SCRY0 (11 + HP11Y)
#define SCRY1 (37 + HP11Y)
#define fX (SCRX0 + 3 * CHARWIDTH + 2) /* Position of indicators */
#define gX (SCRX0 + 4 * CHARWIDTH - 1)
#define GX (SCRX0 + (int)(6.5 * CHARWIDTH))
#define RADX (GX + 5)
#define PRGMX (SCRX0 + 10 * CHARWIDTH - 6)
#define USERX (SCRX0 + CHARWIDTH)
#define INDICY (SCRY0 + 19)

#define CR 13
#define BS 8
#define ESC 27

#define COPY 0xc0 /* minterm for straight copy */

struct Device *		TimerBase     = 0;
struct IntuitionBase *	IntuitionBase = 0;
struct GfxBase *	GfxBase	      = 0;
struct Library *	WorkbenchBase = 0;
struct Library *	GadToolsBase  = 0;
struct Library *	IconBase      = 0;

struct Window *		hp11	      = 0;
static struct timerequest *timer      = 0; /* The timer which is used */
static struct Menu *	hp11menu      = 0;
static BOOL		icons_on      = TRUE;
static ULONG		clip	      = 0;
static char	filename[FILENAMESIZE]= "Program.HP11";
static char 		winname[110];

/* These informations are for RelKey() */
/* The method by which the latest key was obtained :
  From the menus, from the CLOSE gadget, from the keyboard, or by selecting with the mouse */
static enum {menu, gadget, keyboard, mouse} keytype;
/* The keycode of the last key read */
static short lastkey;
/* The Time at which the last key was read */
static ULONG secs, micros;

static struct NewMenu newmen[] = {
  NM_TITLE,"Project",	  0, 0, 0, 0,
  NM_ITEM, "New",	  0, 0, 0, 0,
  NM_ITEM, "Open...",	"O", 0, 0, 0,
  NM_ITEM, "Save",	  0, 0, 0, 0,
  NM_ITEM, "Save As...","S", 0, 0, 0,
  NM_ITEM, "Quit",	  0, 0, 0, 0,
  NM_TITLE,"Edit",	  0, 0, 0, 0,
  NM_ITEM, "Copy",      "C", 0, 0, 0,
  NM_ITEM, "Paste",     "V", 0, 0, 0,
  NM_TITLE,"Options",	  0, 0, 0, 0,
  NM_ITEM, "Radix",	  0, 0, 0, 0,
  NM_SUB, "Point",      ".", CHECKIT|CHECKED, 2, 0,
  NM_SUB, "Comma",      ",", CHECKIT, 1, 0,
  NM_ITEM, "Speed",	  0, 0, 0, 0,
  NM_SUB, "Slow",	  0, CHECKIT|CHECKED, 2, 0,
  NM_SUB, "Fast",	  0, CHECKIT, 1, 0,
  NM_ITEM, "Icons",	  0, CHECKIT|CHECKED, 0, 0,
  NM_END,   0, 0, 0, 0, 0};

/* Delete a timer */
static void DeleteTimer(struct timerequest *tr)
{
   TimerBase = (struct Device *)(-1); /* Don't call any more ! */

   if(tr != NULL)
   {
      /* Remove the port */
      if(tr->tr_node.io_Message.mn_ReplyPort)
        DeleteMsgPort(tr->tr_node.io_Message.mn_ReplyPort);

      CloseDevice((struct IORequest *)tr); /* Close the device */
      DeleteIORequest((struct IORequest *)tr); /* Free the IO request */
   }
}

/* Create a timer of type unit */
static struct timerequest *CreateTimer(ULONG unit)
{
   long error;
   struct MsgPort *timerport;
   struct timerequest *timermsg;

   if ((timerport = CreateMsgPort()) == NULL) /* first get a port */
      return(NULL); /* failed */

   if ((timermsg = (struct timerequest *) /* Then create an IO request for the timer */
		   CreateIORequest(timerport, sizeof(struct timerequest))) == NULL)
      return(NULL); /* failed */

   if ((error = OpenDevice(TIMERNAME, unit, (struct IORequest *)timermsg, 0)) != 0) /* Finally, open the timer device */
   { /* failed */
      DeleteTimer(timermsg);
      return(NULL);
   }

   TimerBase = (struct Device *)timermsg->tr_node.io_Device; /* Allow calls to the time arithmetic routines */
   return(timermsg);
}

/* Wait for a specified duration */
static void WaitFor(struct timeval *tv)
{
  timer->tr_node.io_Command = TR_ADDREQUEST;
  timer->tr_time = *tv;

  DoIO((struct IORequest *)timer); /* Wait for completion of request */
}

/* Reverse the key on the keyboard (as if user was holding it down) */
static void ReverseKey(int key)
{
   int kx, ky, h;

   if (key == 30) h = KEYHEIGHT - 1; /* ON, higher than average */
   else if (key == 25) h = MAXHEIGHT + TOPKEYHEIGHT - 1; /* ENTER, even taller */
   else h = TOPKEYHEIGHT - 1;

/* -------------------- */
/* Check for bug when using short int */

   kx = (key % 10) * MAXWIDTH + KEYX; /* Calc. key position */
   ky = (key / 10) * MAXHEIGHT + KEYY;

   SetDrMd(hp11->RPort, COMPLEMENT); /* Draw in reverse */
   RectFill(hp11->RPort, (long)kx, (long)ky, (long)(kx + (KEYWIDTH - 1)), (long)(ky + h));
}

/* From positions x & y, deduce which key was pressed */
static int DecodeKey(int x, int y)
{
   int kx, ky, px, py;

   kx = (x - KEYX) / MAXWIDTH; px = (x - KEYX) % MAXWIDTH;
   ky = (y - KEYY) / MAXHEIGHT; py = (y - KEYY) % MAXHEIGHT;

   if (/* first, check if in keyboard. x & y are tested (instead of kx, ky)
	  because kx & ky suffer a roundoff towards zero for negative values */
       (x >= KEYX && y >= KEYY && kx <= 9 && ky <= 3)
       &&
	  /* now the condition on width */
       (px < KEYWIDTH && px >= 0) /* same for all keys */
       &&
	 /* condition on height, 2 cases for ENTER is different */
       (
	   (kx == 5 && (ky == 2 || (ky == 3 && py < KEYHEIGHT) && (ky = 2))) /* ENTER, set ky to correct value when ky == 3 */
	   || /* condition on height */
	   (py < KEYHEIGHT && py >= 0)
       )
      ) return(ky * 10 + kx);
   else return(-1);
}

/* Mouse was pressed at x,y. Is this a key ? */
static int GetMouseKey(int x, int y)
{
   int key;

   if ((key = DecodeKey(x, y)) != -1) { /* yes */
      ReverseKey(key);
      keytype = mouse; /* info for RelKey() */
   }
   return(key);
}

/* Key keycode was pressed by the user */
static int GetKeyKey(int _keycode)
{
   int key = -1, keycode = tolower(_keycode);

   switch (keycode) {
      case ESC: key = 30; break;
      case '7': case '8': case '9': key = keycode - ('7' - 6); break;
      case '4': case '5': case '6': key = keycode - ('4' - 16); break;
      case '1': case '2': case '3': key = keycode - ('1' - 26); break;
      case '0': key = 36; break;
      case '.': key = 37; break;
      case '^': key =  3; break;
      case '*': key = 19; break;
      case '-': key = 29; break;
      case '+': key = 39; break;
      case '/': key =  9; break;
      case '_': key =  5; break;
      case CR : key = 25; break;
      case 'f': key = 31; break;
      case 'g': key = 32; break;
      case BS : key = 24; break;
      case 's': key = 12; break;
      case 'c': key = 13; break;
      case 't': key = 14; break;
   }
   if (key != -1) { /* A valid key was given */
      ReverseKey(key);
      keytype = keyboard; /* for RelKey() */
   }
   return(key);
}

static void Message(STRPTR txt)
{
  struct EasyStruct es = { sizeof(struct EasyStruct), 0, "HP11 Message",
  0, "OK"};
  es.es_TextFormat = txt;
  EasyRequest(hp11, &es, 0, 0);
}

static BOOL OpenWin(LONG x, LONG y)
{
  struct BitMap hp11bitmap;

  /* Open the window */
  if(!(hp11 = OpenWindowTags(0,
  	WA_Left,	x,
  	WA_Top,		y,
	WA_Width,	HP11WIDTH+6,
	WA_Height,	HP11HEIGHT+13,
	WA_IDCMP,	IDCMP_CLOSEWINDOW | IDCMP_MOUSEBUTTONS |
			IDCMP_VANILLAKEY | IDCMP_MENUPICK,
	WA_Flags,	WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
			WFLG_DRAGBAR | WFLG_SMART_REFRESH |
			WFLG_NOCAREREFRESH | WFLG_NEWLOOKMENUS ,
	WA_Title,	"HP11C",
	WA_Activate,	TRUE,
	WA_PubScreen,	0, TAG_DONE)))
  {
    Message("Could not open window\n");
    return FALSE;
  }

  InitBitMap(&hp11bitmap, 2, HP11WIDTH, HP11HEIGHT);
  hp11bitmap.Planes[0] = (STRPTR) pic_data;
  hp11bitmap.Planes[1] = (STRPTR) pic_data + hp11bitmap.BytesPerRow *
  			 hp11bitmap.Rows;
  BltBitMapRastPort(&hp11bitmap, 0, 0, hp11->RPort, HP11X, HP11Y, HP11WIDTH, HP11HEIGHT, COPY);
  return TRUE;
}

/* Display s */
void Display(char *s)
{
   int posx;
   int chr;
   struct RastPort *rport = hp11->RPort;

   /* Clear display */
   SetDrMd(rport, JAM1); SetAPen(rport, 2);
   RectFill(rport, SCRX0+1, SCRY0, SCRX1 - 1, SCRY1);

   /* Initial position */
   posx = SCRX0 + CHAROFFX;

   while(*s) {
      switch(*s) { /* Position of char in char array */
	 case '0': case '1': case '2': case '3': case '4': case '5': case '6':
	 case '7': case '8': case '9': chr = *s - '0'; break;
	 case '-': chr = 10; break;
	 case 'E': chr = 11; break;
	 case 'r': chr = 12; break;
	 case 'o': chr = 13; break;
	 case 'R': chr = 14; break;
	 case 'u': chr = 15; break;
	 case 'n': chr = 16; break;
	 case 'i': chr = 17; break;
	 case 'g': chr = 18; break;
	 case '.': chr = 19; break;
	 case ',': chr = 20; break;
	 case 'P': chr = 21; break;
	 default:  chr = -1; break;
      }
      if (chr != -1)
	 DrawBorder(rport, hp11char[chr], (long)posx, SCRY0 + CHAROFFY);

      if (*s != '.' && *s != ',') posx += CHARWIDTH;

      s++;
   }
}

/* Set image to be drawn/erased according to on */
static void SetCol(struct Image *im, int on)
{
   if (on) {
      im->PlanePick = 3;
      im->PlaneOnOff = 0;
   }
   else {
      im->PlanePick = 0;
      im->PlaneOnOff = 2;
   }
}

/* Display the indicators */
void Dispf(int on)
{
   SetCol(&fImage, on);
   DrawImage(hp11->RPort, &fImage, fX, INDICY);
}

void Dispg(int on)
{
   SetCol(&gImage, on);
   DrawImage(hp11->RPort, &gImage, gX, INDICY);
}

void DispUSER(int on)
{
   SetCol(&USERImage, on);
   DrawImage(hp11->RPort, &USERImage, USERX, INDICY);
}

void DispG(int on)
{
   SetCol(&GImage, on);
   DrawImage(hp11->RPort, &GImage, GX, INDICY);
}

void DispRAD(int on)
{
   SetCol(&RADImage, on);
   DrawImage(hp11->RPort, &RADImage, RADX, INDICY);
}

void DispPRGM(int on)
{
   SetCol(&PRGMImage, on);
   DrawImage(hp11->RPort, &PRGMImage, PRGMX, INDICY);
}

void sleep()
{
  LONG x,y;
  struct DiskObject *ti;

  Forbid();
  x = hp11->LeftEdge;
  y = hp11->TopEdge;
  Permit();
  MenusOff();
  CloseWindow(hp11);

  if((ti = GetDefDiskObject(WBPROJECT)))
  {
    struct MsgPort *m;

    ti->do_Gadget.Width 	= off_image.Width;
    ti->do_Gadget.Height	= off_image.Height;
    ti->do_Gadget.Flags		= GFLG_GADGIMAGE|GFLG_GADGHCOMP;
    ti->do_CurrentX		= 
    ti->do_CurrentY		= NO_ICON_POSITION;
    ti->do_Type			= WBAPPICON;
    ti->do_Gadget.GadgetRender	= &off_image;

    if((m = CreateMsgPort()))
    {
      struct AppIcon *a;
      if((a = AddAppIconA(0,0,"HP11C",m,0,ti,0)))
      {
        WaitPort(m);
        ReplyMsg(GetMsg(m));
        RemoveAppIcon(a);
      }
      DeleteMsgPort(m);
    }
    FreeDiskObject(ti);
  }

  /* Open the window */
  if(OpenWin(x, y))
  {
    MenusOn();
    on = TRUE;
  }
}

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

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

void EditOn(void)
{
  OnMenu(hp11, FULLMENUNUM(1,NOITEM,NOSUB));
}

void EditOff(void)
{
  OffMenu(hp11, FULLMENUNUM(1,NOITEM,NOSUB));
}

static BOOL GetFile(STRPTR text, ULONG save)
{
  BOOL ret = FALSE;
  struct Library *AslBase;

  if((AslBase = OpenLibrary("asl.library", 37)))
  {
    struct FileRequester *r;
    if((r = (struct FileRequester *) AllocAslRequest(ASL_FileRequest, 0)))
    {
      if(AslRequestTags(r, ASLFR_TitleText, text, ASLFR_DoSaveMode, save,
      ASLFR_InitialFile, filename, TAG_DONE))
      {
        strcpy(filename, r->fr_Drawer);
        AddPart(filename, r->fr_File, FILENAMESIZE);
        ret = TRUE;
      }
    }
    FreeAslRequest(r);
  }
  CloseLibrary(AslBase);
  return ret;
}  

static void SetTitle(void)
{
  SetWindowTitles(hp11, strcat(strcpy(winname, "HP11C - "), filename), (STRPTR) ~0);
}

static void LoadProg(void)
{
  BPTR file;
  struct DiskObject *icon;
  BYTE dummy;

  if((icon = GetDiskObject(filename)))
  {
    STRPTR val;

    if(!(val = FindToolType(icon->do_ToolTypes, "FILETYPE")) ||
    !MatchToolValue(val, "HP11"))
    {
      Message("This isn't an HP11 program");
      val = 0;
    }
    FreeDiskObject(icon);

    if(!val)
      return;
  }
     
  if((file = Open(filename, MODE_OLDFILE)))
  {
    struct Regs newhp11;
    if((Read(file, &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");
}

/* Save current state under current filename */
static void StoreProg(void)
{
  LONG file, i;

  if(!(file = Open(filename, MODE_NEWFILE)))
    Message("Couldn't open file");
  else
  {
    i = Write(file, &hp11r, sizeof(struct Regs));
    Close(file);

    if(i != sizeof(struct Regs))
      Message("Error writing the file");
    else
    {
      SetTitle();
      if(icons_on)
      {
        struct DiskObject *ti;
        if((ti = GetDiskObjectNew(filename)))
        {
          STRPTR tt[2] = {"FILETYPE=HP11" , 0};

	  ti->do_ToolTypes	= tt;
	  ti->do_Gadget.Width	= prog_image.Width;
	  ti->do_Gadget.Height	= prog_image.Height;
	  ti->do_Gadget.Flags   = GFLG_GADGIMAGE|GFLG_GADGHCOMP;
	  ti->do_CurrentX	= 
	  ti->do_CurrentY	= NO_ICON_POSITION;
    	  ti->do_Type		= WBPROJECT;
	  ti->do_Gadget.GadgetRender = &prog_image;
	  ti->do_DefaultTool	=	"HP11";
	  PutDiskObject(filename, ti);
          FreeDiskObject(ti);
        }
      }
    }
  }
}

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

  MenusOff(); /* Disable menus */

  while(number != MENUNULL)
  {
    item = ItemAddress(hp11menu, (long)number);

    switch(number)
    {
    case FULLMENUNUM(0,0,NOSUB): /* Project - New */
      HP11ColdReset(); key = BRESET; break; /* back to main loop */
    case FULLMENUNUM(0,1,NOSUB): /* Project - Open */
      if(GetFile("Open program", FALSE)) /* Get file name */
    	LoadProg();
      key = BRESET; break;
    case FULLMENUNUM(0,2,NOSUB): /* Project - Save */
      StoreProg(); break;
    case FULLMENUNUM(0,3,NOSUB): /* Project - Save As */
      if(GetFile("Save program", TRUE))
	StoreProg();
      break;
    case FULLMENUNUM(0,4,NOSUB): /* Project - Quit */
      quit = TRUE; key = BRESET; break;
    case FULLMENUNUM(1,0,NOSUB): /* Edit - Copy */
      CBCut(X); break;
    case FULLMENUNUM(1,1,NOSUB): /* Edit - Paste */
      {
        double x;
        if(CBPaste(&x))
        {
          Enter(); ENABLE();
          X = Check(x);
        }
      }
      key = BDISPLAY; break;
    case FULLMENUNUM(2,0,0):
    case FULLMENUNUM(2,0,1): /* Options - Radix */
      comma = SUBNUM(number); /* false for Point, true for Comma */
      key = BDISPLAY; /* Redisplay */
      break;
    case FULLMENUNUM(2,1,0):
    case FULLMENUNUM(2,1,1): /* Options - Speed */
      fast = SUBNUM(number); /* false for Slow, true for Fast */
      break;
    case FULLMENUNUM(2,2,NOSUB): /* Options - Icons */
      icons_on = item->Flags & CHECKED;
      break;
    }

    number = item->NextSelect;
  }

  MenusOn();
  return(key);
}

/* Get a key from the keyboard with/without waiting */
int PollKey(int wait)
{
   int key;
   struct IntuiMessage *msg;
   ULONG _class;
   UWORD code;
   WORD x, y;

   key = -1; /* no key yet */
   do {
      if (wait) WaitPort(hp11->UserPort); /* No active waits in multi-tasking ! */
      msg = (struct IntuiMessage *)GetMsg(hp11->UserPort); /* Get the message if there is one */
      if (msg) { /* yes, there is */
	 /* Copy relevant information */
	 _class = msg->Class;
	 code = msg->Code;
	 x = msg->MouseX;
	 y = msg->MouseY;
	 secs = msg->Seconds;
	 micros = msg->Micros;
	 ReplyMsg((struct Message *)msg); /* & reply to it */

	 switch (_class) { /* type of message */
	    case IDCMP_CLOSEWINDOW: /* Window closed = Quit */
	       quit = TRUE;
	       key = BRESET;
	       keytype = gadget;
	       break;
	    case IDCMP_MOUSEBUTTONS: /* A mouse button was pressed */
	       if(code == SELECTDOWN)
		 key = GetMouseKey(x, y);
	       break;
	    case IDCMP_VANILLAKEY: /* a key was pressed */
	       key = GetKeyKey(code);
	       break;
	    case IDCMP_MENUPICK: /* A menu option was chosen */
	       key = MenuHandler(code); /* Call menu handler */
	       keytype = menu; /* for RelKey() */
	       break;
	 }
      }
   } while (key == -1 && (msg || wait));
   /* Exit if key read or, if not waiting, no message ready */

   lastkey = key; /* save key for RelKey() */
   return(key);
}

/* Wait for latest key to be released, returns true if button released
  over key (valid only for mouse) */
BOOL RelKey(void)
{
   WORD x, y;
   BOOL Released;
   struct IntuiMessage *msg;
   struct timeval event, now, delay;
   int key = lastkey; /* key last pressed */

   lastkey = -1; /* Only release it once ! */

   if (key != -1)
      switch (keytype) {

	 case keyboard: /* Key reversed for a max of .08 secs
	    (There is no easy way to wait for its release on the keyboard) */
	    event.tv_secs = secs; event.tv_micro = micros;
	    GetSysTime(&now);
	    SubTime(&now, &event); /* Time elapsed since key pressed */
	    delay.tv_secs = 0; delay.tv_micro = 80000;
	    if(CmpTime(&now, &delay) == 1) { /* now < delay */
	       SubTime(&delay, &now);
	       WaitFor(&delay); /* Wait long enough */
	    }
	    ReverseKey(key); /* un-reverse key */
	    return(TRUE);

	 case mouse:
	    do { /* Wait for mouse button to be released */
	       WaitPort(hp11->UserPort);
	       msg = (struct IntuiMessage *)GetMsg(hp11->UserPort);
	       x = msg->MouseX;
	       y = msg->MouseY;
	       Released = (msg->Class == IDCMP_MOUSEBUTTONS &&
	       msg->Code == SELECTUP);
	       ReplyMsg((struct Message *)msg);
	    } while (!Released);
	    ReverseKey(key); /* un-reverse key */

	    return((BOOL)(DecodeKey(x, y) == key)); /* Button released over key? */
      }
   return(TRUE); /* if already released */
}

/* Amiga specific initialisation */
BOOL Init(int argc, APTR argv)
{
  DEG(); /* Initial state, all other values are zero */
  FIX(4);

  if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 37)))
    return FALSE;

  if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 37)))
    return FALSE;

  if(!(IconBase = OpenLibrary("icon.library", 37)))
    return FALSE;

  if(!(GadToolsBase = OpenLibrary("gadtools.library", 37)))
    return FALSE;

  if(!(WorkbenchBase = OpenLibrary("workbench.library", 37)))
    return FALSE;

  if(!OpenWin(0,0))
    return FALSE;

   /* Create timer */
  if(!(timer = CreateTimer(UNIT_MICROHZ)))
    return FALSE;

  if(!(clip = CBOpen(0)))
    return FALSE;

  if(argc != 0) /* CLI */
  {
    icons_on = FALSE;
    newmen[16].nm_Flags &= ~CHECKED; /* by default, no icons from cli */
    if(argc > 1)
    { /* argument */
      strcpy(filename, ((char **)argv)[1]);
      LoadProg();
    }
  }
  else if (((struct WBStartup *)argv)->sm_NumArgs > 1)
  { /* workbench, with argument */
    if(NameFromLock((((struct WBStartup *)argv)->sm_ArgList[1]).wa_Lock,
    filename, FILENAMESIZE))
    {
      AddPart(filename, (((struct WBStartup *)argv)->sm_ArgList[1]).wa_Name,
      FILENAMESIZE);
      LoadProg();
    }
  }

  if(!(hp11menu = CreateMenusA(newmen, 0)))
    return FALSE;
  else
  {
    BOOL ret = TRUE;
    struct Screen *scr;
    
    if((scr = LockPubScreen(0)))
    {
      APTR vi;

      if((vi = GetVisualInfoA(scr, 0)))
      {
        LayoutMenus(hp11menu, vi, GTMN_NewLookMenus, TRUE, TAG_DONE);
        FreeVisualInfo(vi);
      }
      else
        ret = FALSE;
      UnlockPubScreen(0, scr);
    }
    else
      ret = FALSE;
    if(!ret)
      return ret;
  }
  MenusOn();

  return TRUE;
}

void CleanUp()
{
  if(clip)		CBClose();
  if(hp11)
  {
    MenusOff();
    CloseWindow(hp11);
  }
  if(hp11menu)		FreeMenus(hp11menu);
  if(timer)		DeleteTimer(timer); /* Close timer */
  if(WorkbenchBase)	CloseLibrary(WorkbenchBase);
  if(IntuitionBase)	CloseLibrary((struct Library *)IntuitionBase); /* Close libraries */
  if(GfxBase)		CloseLibrary((struct Library *)GfxBase);
  if(IconBase)		CloseLibrary(IconBase);
  if(GadToolsBase)	CloseLibrary(GadToolsBase);
}

