// TSMorph - Amiga Morphing program
// Copyright (C) © 1993  Topicsave Limited

// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

// mpaddock@cix.compulink.co.uk

// include normally precompiled headers if required
#ifndef TSMORPH_H
#include "TSMorph.h"
#endif

/* Disable CTRL-C checking	*/
int CXBRK(void) { return(0); }
int chkabort(void) { return(0); }
int __regargs __chkabort(void) { return(0); }

/* Define all the Library bases	*/
struct IntuitionBase *IntuitionBase;
struct Library	*GfxBase,
					*LayersBase,
					*InputBase,
					*IFFParseBase,
					*GadToolsBase,
					*AslBase,
					*UtilityBase,
					*DiskfontBase,
					*AmigaGuideBase,
					*IconBase,
					*ReqToolsBase,
					*RexxSysBase,
					*DCTVBase;

struct OpalBase *OpalBase;

struct Library *EGSIntuiBase = NULL;
struct Library *EGSGfxBase = NULL;
struct Library *EGSBase = NULL;
struct Library *EGSRequestBase = NULL;

/* Table of system gadget sizes
 * See TSMorph.h for definitions
 */
extern struct gadgetsizing gs[] = {
	{SYSISIZE_LOWRES,13,11,16,11,13,11,16,11,13,11,15,18,18, 7, 9},
	{SYSISIZE_MEDRES,18,10,16,10,18,11,16,10,18,11,20,24,24,10,13}
};

extern UWORD 						Mode 			= NONE;
extern struct List				PointList 	= {0};
extern struct Picture	 		Pic1			= {0},
										Pic2			= {0};
extern BOOL 						Pic1_Open	= FALSE;
extern BOOL 						Pic2_Open	= FALSE;
extern struct FileRequester 	*filereq		= NULL;
//extern struct FileRequester 	*sfilereq	= NULL;
extern struct rtFileRequester	*rtfilereq	= NULL;
extern BOOL 						Saved 		= TRUE;
char 						savedfilename[256]	= "";
extern LONG							Width			= 0,
										Height		= 0;
extern LONG							SinglePicture			= 0;
extern BOOL 						Zoom			= FALSE;
extern BOOL 						ZoomAllowed	= TRUE;
extern BOOL							PaletteAllowed			= TRUE;
extern char 						**ArgArray				= NULL;
extern char 						**ArgArraySettings	= NULL;
extern AMIGAGUIDECONTEXT 		handle 		= NULL;
extern BOOL							palette		= TRUE;
extern BOOL							CreateIcons = TRUE;
extern BOOL							CreateIconsR = FALSE;/* TRUE if to write Render Icons	*/
extern BOOL							CreateIconsP = TRUE;	/* TRUE if to write prefs Icons	*/
extern BOOL							KeepSettings = TRUE; /* TRUE to save settings on quit */
extern ULONG						DX=0;
extern ULONG						DY=0;
char							LoadScript[128] = "Rexx/Loadscript";
char							PreScript[128] = "Rexx/Prescript";
char							PostScript[128] = "Rexx/Postscript";
char							PreviewScript[128] = "Rexx/Preview";
char							ScreenName[128] = "";
char							ScreenNameR[128] = "";
char							CustomName[128] = "";
extern ULONG						CustomDepth = 4;
extern BOOL							OpenedScreen = FALSE;/* Did we open the screen			*/
extern ULONG						Depth=2;
extern ULONG						RenderMode=0;
extern ULONG						SaveFormat=0;
extern ULONG						Quality=75;
extern ULONG						ASig			= 0;
extern ULONG						OpenMode		= 0;
extern int							changedboxcount	= 0;	// Used to redraw points after resizing BOTH windows
extern UWORD						n=0;							// Holds screen resolution
extern LONG 						MaxWidth		= 0;	// Max x of points
extern LONG							MaxHeight	= 0;	// Max y of points
extern BOOL							AntiAlias	= FALSE;	// Anti Alias?
extern BOOL							Integer		= FALSE;	// Integer calculation?
extern BOOL							GHelp			= FALSE;	// Gadget Help?
extern struct NewAmigaGuide	nag 	= {NULL};		// .guide stuff
extern BOOL							EGS = FALSE;		// Use EGS picture window

struct MsgPort		*WMsgPortp;			// Message port for Picture Windows
ULONG 				IDCMPFlags;			// IDCMP flags for windows
LONG 					Start;				// Start frame

/* Mapping for Boopsi gadgets	*/
struct TagItem MapToIdcmp[] = {
	{PGA_Top,ICSPECIAL_CODE},
	{GA_ID,ICSPECIAL_CODE},
	{TAG_END,}
};

/* Properties for IFF read	*/
extern LONG props[] = {	ID_ILBM,	ID_BMHD,	// Just need BitMapHeader
						ID_ILBM,	ID_CAMG,			// CAMG (not sure why)
						ID_ILBM, ID_CMAP,			// And ColourMap
						TAG_DONE };

extern LONG stops[] = {	ID_ILBM,	ID_BODY,	// Stop on Body chunk
						TAG_DONE };

extern LONG nowt[] = { TAG_DONE };			// Nothing else is required

extern LONG FrameNumber = 0;					// Current frame number

/* Wait pointer */
extern USHORT __chip BusyPointerData[] =
{
	0x0000,0x0000,
	0x0400,0x07C0,0x0000,0x07C0,0x0100,0x0380,0x0000,0x07E0,
	0x07C0,0x1FF8,0x1FF0,0x3FEC,0x3FF8,0x7FDE,0x3FF8,0x7FBE,
	0x7FFC,0xFF7F,0x7EFC,0xFFFF,0x7FFC,0xFFFF,0x3FF8,0x7FFE,
	0x3FF8,0x7FFE,0x1FF0,0x3FFC,0x07C0,0x1FF8,0x0000,0x07E0,
	0x0000,0x0000,
};


/* Version string for CLI version */
char *Version = "$VER: TSMorph 3.2 (12.3.95)";

/* Display About requester
 * using reqtools.library if available
 */
void
About(void) {
	UBYTE *body;
	UBYTE *title = "TSMorph 3.2 (12.3.95)";
	UBYTE *gad;
	struct EasyStruct EasyStruct = {
	  	sizeof(struct EasyStruct),
		0,
		NULL,
		NULL,
		NULL
	};
	DisableWindows(DI_About);
	body = MyGetMsg(MSG_ABOUT);
	gad = MyGetMsg(MSG_OK);
	if (ReqToolsBase) {
		rtEZRequestTags(body,MyGetMsg(MSG__OK),NULL,NULL,
							RT_Window,		TSMorphWnd,
							RTEZ_ReqTitle,	title,
							RTEZ_Flags,		EZREQF_CENTERTEXT,
							RT_Underscore,	'_',
							TAG_END);
	}
	else {
		EasyStruct.es_Title = title;
		EasyStruct.es_TextFormat = body;
		EasyStruct.es_GadgetFormat = gad;
		EasyRequestArgs(TSMorphWnd,&EasyStruct,NULL,NULL);
	}
	EnableWindows();
}

/* The main procedure	*/
int
main(int argc,char **argv) {
 BOOL 				OkFlag		= FALSE;		// Still running ok
 struct IOStdReq	InputIO;						// Input device to check Shift key
 struct Message 	*Message;					// To discard messages from ports
 struct WBStartup *argmsg;						// Workbench stuff
 struct WBArg 		*wb_arg;						// Workbench arguments
 struct Window		*oldWindowPtr;				// Retain old pointer for system requesters
 struct Process	*process;					// This process for system requesters
 char 				*e				= NULL;		// Main error message string
 char 				*e1			= NULL;		// Variable part of error message
 char 				*filename;					// General file name
 LONG					hnum			= 0;			// Help to display on an error message

 /* Initalise list of points	*/
 NewList(&PointList);
 // try and open optional libraries
 DCTVBase = OpenLibrary("dctv.library",3L);
 OpalBase = (struct OpalBase *)OpenLibrary("opal.library",0L);
 ReqToolsBase = OpenLibrary("reqtools.library",38);
 /* If we can open amigaguide.library
  * then set up the help stuff
  */
 if (AmigaGuideBase = OpenLibrary ("amigaguide.library", 34L)) {
  nag.nag_BaseName		= "TSMorph";
  nag.nag_Name				= "TSMorph.guide";
  nag.nag_ClientPort		= "TSMorph_HELP";
  nag.nag_Context			= context;
  nag.nag_Flags			= HTF_NOACTIVATE;
  nag.nag_PubScreen		= NULL;
  if (handle = OpenAmigaGuideAsync(&nag, NULL)) {
   ASig = AmigaGuideSignal(handle);
  }
 }
 /* Open all the libraries/devices/message ports/file requesters etc.	*/
 if (IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37L)) {
  if (RexxSysBase = OpenLibrary("rexxsyslib.library",0L)) {
  if (IconBase = OpenLibrary("icon.library",37L)) {
   if (IFFParseBase = OpenLibrary("iffparse.library",37L)) {
    if (!OpenDevice("input.device",NULL,(struct IORequest *)&InputIO,NULL)) {
     InputBase = (struct Library *)InputIO.io_Device;
     if (GfxBase = OpenLibrary("graphics.library",37L)) {
      if (LayersBase = OpenLibrary("layers.library",37L)) {
       if (GadToolsBase = OpenLibrary("gadtools.library",37L)) {
        if (AslBase = OpenLibrary("asl.library",37L)) {
         if (UtilityBase = OpenLibrary("utility.library",37)) {
          if (DiskfontBase = OpenLibrary("diskfont.library",36)) {
           if (WMsgPortp = CreateMsgPort()) {
            /* Read all the parameters/tooltypes/settings file	*/
            MyArgArrayInit(argc,argv);
            InitParams(TRUE);
            if (MatchToolValue(MyArgString("REQTOOLS","YES",FALSE),"NO")) {
             if (ReqToolsBase) {
              CloseLibrary(ReqToolsBase);
              ReqToolsBase = NULL;
             }
            }
            if (MatchToolValue(MyArgString("EGS","NO",FALSE),"YES")) {
             if ((EGSBase = OpenLibrary("egs.library",0)) &&
                 (EGSGfxBase = OpenLibrary("egsgfx.library", 0)) &&
                 (EGSIntuiBase = OpenLibrary("egsintui.library", 0)) &&
                 (EGSRequestBase = OpenLibrary("egsrequest.library", 0))) {
              EGS = TRUE;
              ZoomAllowed = FALSE;
             }
            }
            if ((MatchToolValue(MyArgString("REQTOOLS","YES",FALSE),"ALL") &&
                (rtfilereq = (struct rtFileRequester *)rtAllocRequestA(RT_FILEREQ,NULL))) ||
                (filereq = (struct FileRequester *)AllocFileRequest())) {
              /* Open custom screen if required				*/
              if (OpenCustomScreen()) {
               if (PubScreenName && *PubScreenName) {
                /* Since the screen now exists reopen amigaguide on it! */
                if (handle) {
                 CloseAmigaGuide(handle);
                 handle = NULL;
                }
                if (AmigaGuideBase) {
                 nag.nag_PubScreen		= PubScreenName;
                 if (handle = OpenAmigaGuideAsync(&nag, NULL)) {
                  ASig = AmigaGuideSignal(handle);
                 }
                }
               }
               /* Update the Info window menus and open	*/
               if (!SetupScreen()) {
                if (!OpenTSMorphWindow()) {
                 /* Set up system requester redirection	*/
                 process = (struct Process *)FindTask(NULL);
                 oldWindowPtr = process->pr_WindowPtr;
                 process->pr_WindowPtr = TSMorphWnd;
                 /* Activate the window and disable		*/
                 ActivateWindow(TSMorphWnd);
                 DisableWindows(DI_LoadBrush);
                 /* Load brushes if possible					*/
                 LoadBrushes();
                 /* No filename as yet							*/
 		           *savedfilename = 0;
 		           if (argc) {
 	               if (filename = ArgString(ArgArray,"FILES",NULL)) {
                   MyOpen(filename,FALSE,TRUE);				// From the CLI and FILES parameter supplied
                  }
                 }
                 else {
             	   argmsg = (struct WBStartup *)argv;
 				 	   if (argmsg->sm_NumArgs > 1) {
 	                wb_arg = argmsg->sm_ArgList;
    	             wb_arg++;
       	          if (wb_arg->wa_Lock) {
  	      	        NameFromLock(wb_arg->wa_Lock,savedfilename,256);
  	      	       }
      	       	 if (AddPart(savedfilename,wb_arg->wa_Name,256)) {
         	    	  MyOpen(savedfilename,FALSE,TRUE);		// From the WB and project supplied
             	    }
             	   }
                 }
                 /* Enable the windows and do the main stuff	*/
                 EnableWindows();
                 doMsgLoop();
                 if (KeepSettings) {
                  SaveSettings("ENV:TSMorph/TSMorph.prefs");	// save settings for next run
                 }
                 /* Close everything down in reverse order
                  * Setting up error message if required
                  */
                 if (Pic1_Open) {
                  CloseAPicture(&Pic1);
                  Pic1_Open = FALSE;
                 }
                 if (Pic2_Open) {
                  CloseAPicture(&Pic2);
                  Pic2_Open = FALSE;
                 }
                 DeleteAllPoints();
                 if (ControlWindow) {
                  CloseControlWindow();
                 }
                 process->pr_WindowPtr = oldWindowPtr;
                 OkFlag = TRUE;
                }
                CloseTSMorphWindow();
                if (!OkFlag && !e) {
                 e = MyGetMsg(MSG_FAILURE);					// e and e1 to save memory as e is reused
                 e1 = MyGetMsg(MSG_OTSMW);
                 hnum = HE_OMorph;
                }
               }
               CloseDownScreen();
               if (!OkFlag && !e) {
                e = MyGetMsg(MSG_FAILURE);
                e1 = MyGetMsg(MSG_SUSCR);
                hnum = HE_Screen;
               }
              }
              else {
               // Displayed error message elsewhere
               OkFlag = TRUE;
              }
              MyArgArrayDone();
              if (rtfilereq) {
               rtFreeRequest(rtfilereq);
              }
              else {
               FreeFileRequest(filereq);
              }
            }
            if (!OkFlag && !e) {
             e = MyGetMsg(MSG_UNABLE);
             e1 = MyGetMsg(MSG_FILER);
             hnum = HE_FileReq;
            }
            Forbid();
            while (Message = GetMsg(WMsgPortp)) {
             ReplyMsg(Message);
            }
            DeleteMsgPort(WMsgPortp);
            Permit();
           }
           if (!OkFlag && !e) {
            e = MyGetMsg(MSG_UNABLE);
            e1 = MyGetMsg(MSG_CWMP);
            hnum = HE_WPort;
           }
           CloseLibrary(DiskfontBase);
          }
          if (!OkFlag && !e) {
           e = MyGetMsg(MSG_CANNOTOP);
           e1= "diskfont.library(36)";
           hnum = HE_Library;
	 	 	 }
          CloseLibrary(UtilityBase);
         }
         if (!OkFlag && !e) {
          e = MyGetMsg(MSG_CANNOTOP);
          e1 = "utility.library(37)";
          hnum = HE_Library;
         }
         CloseLibrary(AslBase);
        }
        if (!OkFlag && !e) {
         e = MyGetMsg(MSG_CANNOTOP);
         e1 = "asl.library(37)";
         hnum = HE_Library;
        }
        CloseLibrary(GadToolsBase);
       }
       if (!OkFlag && !e) {
        e = MyGetMsg(MSG_CANNOTOP);
        e1 = "gadtools.library(37)";
        hnum = HE_Library;
       }
       CloseLibrary(LayersBase);
      }
      if (!OkFlag && !e) {
       e = MyGetMsg(MSG_CANNOTOP);
       e1 = "layers.library(37)";
       hnum = HE_Library;
      }
      CloseLibrary(GfxBase);
     }
     if (!OkFlag && !e) {
      e = MyGetMsg(MSG_CANNOTOP);
      e1 = "graphics.library(37)";
      hnum = HE_Library;
     }
     CloseDevice(&InputIO);
    }
    if (!OkFlag && !e) {
     e = MyGetMsg(MSG_CANNOTOP);
     e1 = "input.device";
     hnum = HE_IDevice;
    }
    CloseLibrary(IFFParseBase);
   }
   if (!OkFlag && !e) {
    e = MyGetMsg(MSG_CANNOTOP);
    e1 = "iffparse.library(37)";
    hnum = HE_Library;
   }
 	CloseLibrary(IconBase);
  }
  if (!OkFlag && !e) {
   e = MyGetMsg(MSG_CANNOTOP);
   e1 = "icon.library(37)";
   hnum = HE_Library;
  }
 	CloseLibrary(RexxSysBase);
  }
  if (!OkFlag && !e) {
   e = MyGetMsg(MSG_CANNOTOP);
   e1 = "rexxsyslib.library(0)";
   hnum = HE_Library;
  }
  if (!OkFlag) {
   Error(e,MyGetMsg(MSG_QUIT),e1,hnum);			// Display error message if it failed
  }
  /* Close AmigaGuide (so we can close the screen)
   * It will be reopened if required
   */
  if (handle) {
   CloseAmigaGuide(handle);
   handle = NULL;
   ASig = NULL;
  }
  if (OpenedScreen) {
   CloseCustomScreen();
  }
 }
 if (EGSRequestBase) {
  CloseLibrary(EGSRequestBase);
 }
 if (EGSIntuiBase) {
  CloseLibrary(EGSIntuiBase);
 }
 if (EGSGfxBase) {
  CloseLibrary(EGSGfxBase);
 }
 if (EGSBase) {
  CloseLibrary(EGSBase);
 }
 if (AmigaGuideBase) {
  CloseLibrary(AmigaGuideBase);
 }
 if (OpalBase) {
  CloseLibrary((struct Library *)OpalBase);
 }
 if (ReqToolsBase) {
  CloseLibrary(ReqToolsBase);
 }
 if (DCTVBase) {
  CloseLibrary(DCTVBase);
 }
 if (IntuitionBase) {
  CloseLibrary((struct Library *)IntuitionBase);
 }
 return 0;
}

/* Open and image in a window
 * returns	: TRUE or FALSE for sucess failure
 * filename	: Name of file, can be NULL in which case ASL file requester is displayed
 * pic		: pointer to a structure to hold all the stuff
 * GUI		: TRUE or FALSE to display error message on failure
 */
BOOL
openAPicture(char *filename,struct Picture *pic,BOOL GUI) {
 char dirname[257];	// full filename from ASL requester or FrameNumber
 char rtfilename[108] = "\0";	// reqtools filename from requester
 char *ifilename	= NULL;	// filename to use
 char *e 			= NULL;	// first part of error message
 char *e1 			= NULL;	// 2nd part of error message
 int i;							// Loop counter for bit planes
 LONG hnum			= 0;		// Help number for error
 struct EI_NewWindow EGS_NewWindow = {0};	// EGS New window
 /* Set file name from input supplied
  * or by using ASL file requester
  */
 if (filename) {
  if ((SinglePicture == 2) || (SinglePicture == 3)) {
   sprintf(dirname,filename,FrameNumber);		// Add in frame number
   ifilename = dirname;
  }
  else {
   ifilename = filename;
  }
 }
 else {
  if (rtfilereq) {
   if (rtFileRequestA(rtfilereq,rtfilename,MyGetMsg(MSG_PICKIFF),NULL)) {
    strncpy(dirname,rtfilereq->Dir,256);
    if (AddPart(dirname,rtfilename,256)) {
     ifilename=dirname;
    }
   }
  }
  else {
   if (AslRequestTags((APTR) filereq,ASL_Hail,(Tag) MyGetMsg(MSG_PICKIFF),TAG_DONE)) {
    strncpy(dirname,filereq->rf_Dir,256);
    if (AddPart(dirname,filereq->rf_File,256)) {
     ifilename=dirname;
    }
   }
  }
 }
 /* If we now have a file name then find the screen (passed in PUBSCREEN=)
  * determine its resolution and get some data
  */
 if (ifilename) {
  if (pic->Screen = LockPubScreen(PubScreenName)) {
   if (pic->DRI = GetScreenDrawInfo(pic->Screen)) {
    /* Load the image using IFF stuff
     * and do some validation and set some gadgets
     */
    if (pic->ilbm = (struct ILBMInfo *)AllocMem(sizeof(struct ILBMInfo),MEMF_PUBLIC|MEMF_CLEAR)) {
     if (!MyLoadBrush(pic,ifilename)) {
      e = (char *)-1;
      GUI = FALSE;	// already displayed message
     }
     else {
      if (!EGS) {
       pic->width = pic->ilbm->Bmhd.w;
       pic->height = pic->ilbm->Bmhd.h;
      }
      if (pic == &Pic1) {
		 if ((Pic1.width < MaxWidth) ||
  	        (Pic1.height < MaxHeight)) {
        e = MyGetMsg(MSG_IMSMALL);
        hnum = HE_ISmall;
       }
      }
      else {
       if ((Pic1.width != Pic2.width) ||
           (Pic1.height != Pic2.height)) {
        e = MyGetMsg(MSG_IMDIFF);
        hnum = HE_IDifferent;
       }
       else {
        Width = Pic1.width;
        Height = Pic1.height;
		  GT_SetGadgetAttrs(TSMorphGadgets[GDX_Width],TSMorphWnd,NULL,
								GTNM_Number,Width,
								TAG_END );
		  GT_SetGadgetAttrs(TSMorphGadgets[GDX_Height],TSMorphWnd,NULL,
								GTNM_Number,Height,
								TAG_END );
       }
      }
      /* If Zoom is allowed then we always display the Zoom bitmap
       * This is either 2x the normal bit map or just use the top left corner
       */
      if (!e) {
       if (ZoomAllowed) {
        InitBitMap(&(pic->BitMap),min(min(pic->ilbm->Bmhd.nPlanes,8),pic->Screen->BitMap.Depth),pic->ilbm->Bmhd.w<<1,pic->ilbm->Bmhd.h<<1);
 		  for (i=0;
 				(i < pic->ilbm->Bmhd.nPlanes) && (i < 8) && (i < pic->Screen->BitMap.Depth) && !e; // Allow up to 8 bitplanes
 				++i) {
		   if (!(pic->BitMap.Planes[i] = AllocRaster(pic->ilbm->Bmhd.w<<1,pic->ilbm->Bmhd.h<<1))) {
          e = MyGetMsg(MSG_UNALLOC);
          e1 = MyGetMsg(MSG_ZOOMR);
          hnum = HE_ZRaster;
         }
		  }
		  if (!e) {
		   pic->BitScaleArgs.bsa_SrcX 		= 0;
		   pic->BitScaleArgs.bsa_SrcY 		= 0;
		   pic->BitScaleArgs.bsa_SrcWidth 	= pic->ilbm->Bmhd.w;
		   pic->BitScaleArgs.bsa_SrcHeight 	= pic->ilbm->Bmhd.h;
		   pic->BitScaleArgs.bsa_DestX 		= 0;
		   pic->BitScaleArgs.bsa_DestY 		= 0;
		   pic->BitScaleArgs.bsa_DestWidth 	= pic->ilbm->Bmhd.w<<1;
		   pic->BitScaleArgs.bsa_DestHeight = pic->ilbm->Bmhd.h<<1;
		   pic->BitScaleArgs.bsa_XSrcFactor = 1;
		   pic->BitScaleArgs.bsa_XDestFactor= 2;
		   pic->BitScaleArgs.bsa_YSrcFactor = 1;
		   pic->BitScaleArgs.bsa_YDestFactor= 2;
		   pic->BitScaleArgs.bsa_SrcBitMap 	= pic->ilbm->brbitmap;
		   pic->BitScaleArgs.bsa_DestBitMap = &(pic->BitMap);
		   pic->BitScaleArgs.bsa_Flags 		= 0;
		   /* Either scale image 2x or straight copy	*/
 		   if (Zoom) {
 		    BitMapScale(&(pic->BitScaleArgs));
 		   }
		   else {
		    BltBitMap(pic->ilbm->brbitmap,0,0,
		     			  &(pic->BitMap),0,0,
		     			  pic->ilbm->Bmhd.w,pic->ilbm->Bmhd.h,
		     			  0xC0,0xff,NULL);
		   }
		  }
		 }
		}
      if (!e) {
       pic->Left = 0;	//	Need to do this as Pic structures can be closed and reopened
       pic->Top = 0;
       if (EGS) {
        if (pic->filename = AllocVec(strlen(ifilename)+1+20,MEMF_PUBLIC|MEMF_CLEAR)) {	// Extra for other frames
         strcpy(pic->filename,ifilename);
         EGS_NewWindow.LeftEdge = (pic == &Pic1)?0:
         			max(min(Pic1.EGS_Win->Width + Pic1.EGS_Win->BorderLeft + Pic1.EGS_Win->BorderRight,
         				Pic1.EGS_Win->WScreen->Width - Pic1.EGS_Win->Width - Pic1.EGS_Win->BorderLeft - Pic1.EGS_Win->BorderRight),0);
         EGS_NewWindow.TopEdge = (pic == &Pic1)?20:
           			max(min(Pic1.EGS_Win->Height + Pic1.EGS_Win->BorderTop + Pic1.EGS_Win->BorderBottom + 16,
         				Pic1.EGS_Win->WScreen->Height - Pic1.EGS_Win->Height - Pic1.EGS_Win->BorderTop - Pic1.EGS_Win->BorderBottom - 16),0);
         EGS_NewWindow.Width = pic->width;
         EGS_NewWindow.Height = pic->height;
         EGS_NewWindow.MinWidth = 20;
         EGS_NewWindow.MinHeight = 20;
         EGS_NewWindow.MaxWidth = pic->width;
         EGS_NewWindow.MaxHeight = pic->height;
         EGS_NewWindow.Screen = NULL;
         EGS_NewWindow.Bordef.SysGadgets = EI_WINDOWCLOSE | EI_WINDOWSIZE | EI_WINDOWFRONT | EI_WINDOWFLIP |
														EI_WINDOWARROWL | EI_WINDOWARROWR | EI_WINDOWARROWU | EI_WINDOWARROWD |
														EI_WINDOWSCROLLH | EI_WINDOWSCROLLV | EI_WINDOWDRAG;
         EGS_NewWindow.FirstGadgets = NULL;
         EGS_NewWindow.Title = FilePart(pic->filename);
         EGS_NewWindow.Flags = EI_GIMMEZEROZERO | EI_SUPER_BITMAP | EI_WINDOWACTIVE | EI_REPORTMOUSE | EI_QUICKSCROLL | EI_RMBTRAP;
         EGS_NewWindow.IDCMPFlags = EI_iCLOSEWINDOW | EI_iVANILLAKEY | EI_iMOUSEBUTTONS | EI_iMOUSEMOVE | EI_iACTIVEWINDOW | EI_iNEWSIZE;
         EGS_NewWindow.Port = WMsgPortp;
//       EGS_NewWindow.Colors = ??;
         EGS_NewWindow.Menu = NULL;
         EGS_NewWindow.Render = NULL;
         if (pic->EGS_Win = EI_OpenWindow(&EGS_NewWindow)) {
//        EI_ReportMouse(pic->EGS_Win,TRUE);
          EI_SetWindowTitles(pic->EGS_Win,(UBYTE *)-1,pic->filename);
          pic->EGS_Win->UserData  = (BYTE *)pic;
          if (pic == &Pic2) {
           E_ActivateEGSScreen();
          }
          EG_CopyBitMapRastPort(pic->EGS_BitMap,pic->EGS_Win->RPort,0,0,pic->width,pic->height,0,0);
          E_DisposeBitMap(pic->EGS_BitMap);
          pic->EGS_BitMap = NULL;
          EG_SetDrMd(pic->EGS_Win->RPort,EG_INVERT);
          if (pic == &Pic1) {
           E_ActivateAmigaScreen();
           ScreenToFront(Scr);
          }
          return TRUE;
         }
         if (!e) {
          e = MyGetMsg(MSG_UNABLE);
          e1 = MyGetMsg(MSG_OPENW);
          hnum = HE_OWindow;
         }
        }
        if (!e) {
         e = MyGetMsg(MSG_UNABLE);
         e1 = MyGetMsg(MSG_ALLOCFIL);
         hnum = HE_MemFile;
        }
       }
       else {
        /* Allocate all gadgets and images	*/
        if (pic->BotGad = (struct Gadget *)NewObject(NULL,"propgclass",
          PGA_Freedom,		FREEHORIZ,
          PGA_NewLook,		TRUE,
          PGA_Borderless,	(pic->Screen->BitMap.Depth>1)?TRUE:FALSE,
          PGA_Top,				pic->Left,
          PGA_Visible,		pic->ilbm->Bmhd.w<<Zoom,
          PGA_Total,			pic->ilbm->Bmhd.w<<Zoom,
          ICA_TARGET,			ICTARGET_IDCMP,
          GA_Left,				pic->Screen->WBorLeft - 1,
          GA_Height,			SIZEIMAGE_H(n) - 4,
          GA_RelBottom,		-SIZEIMAGE_H(n) + 3,
          GA_RelWidth,		-(SIZEIMAGE_W(n)+LEFTIMAGE_W(n)+RIGHTIMAGE_W(n)+pic->Screen->WBorLeft+1),
          GA_ID,				LEFT_RIGHT_GADGET,
          GA_GZZGadget,		TRUE,
          GA_Immediate,		TRUE,
          GA_RelVerify,		TRUE,
          GA_BottomBorder,	TRUE,
          ICA_MAP,				MapToIdcmp,
          GA_UserData,		pic,
          TAG_END)) {
         if (pic->SideGad = (struct Gadget *)NewObject(NULL,"propgclass",
           PGA_Freedom,		FREEVERT,
           PGA_NewLook,		TRUE,
           PGA_Borderless,	(pic->Screen->BitMap.Depth>1)?TRUE:FALSE,
           PGA_Top,			pic->Top,
           PGA_Visible,		pic->ilbm->Bmhd.h<<Zoom,
           PGA_Total,			pic->ilbm->Bmhd.h<<Zoom,
           ICA_TARGET,		ICTARGET_IDCMP,
           GA_Top,				pic->Screen->WBorTop + pic->Screen->Font->ta_YSize + 2,
           GA_Width,			VSCROLL_W(n),
           GA_RelRight,		-VSCROLL_L(n),
           GA_RelHeight,		-(pic->Screen->WBorTop+pic->Screen->Font->ta_YSize+3+UPIMAGE_H(n)+DOWNIMAGE_H(n)+SIZEIMAGE_H(n)),
           GA_ID,				UP_DOWN_GADGET,
           GA_GZZGadget,		TRUE,
           GA_Immediate,		TRUE,
           GA_RelVerify,		TRUE,
           GA_RightBorder,	TRUE,
           GA_Previous,		pic->BotGad,
           ICA_MAP,			MapToIdcmp,
           GA_UserData,		pic,
           TAG_END)) {
          if (pic->Limage = (struct Image *)NewObject(NULL,"sysiclass",
            SYSIA_DrawInfo,	pic->DRI,
            SYSIA_Which,		LEFTIMAGE,
            SYSIA_Size,		SYSISIZE(n),
            TAG_END)) {
           if (pic->Rimage = (struct Image *)NewObject(NULL,"sysiclass",
             SYSIA_DrawInfo,pic->DRI,
             SYSIA_Which,	RIGHTIMAGE,
             SYSIA_Size,		SYSISIZE(n),
             TAG_END)) {
            if (pic->Dimage = (struct Image *)NewObject(NULL,"sysiclass",
              SYSIA_DrawInfo,	pic->DRI,
              SYSIA_Which,		DOWNIMAGE,
              SYSIA_Size,		SYSISIZE(n),
              TAG_END)) {
             if (pic->Uimage = (struct Image *)NewObject(NULL,"sysiclass",
               SYSIA_DrawInfo,	pic->DRI,
               SYSIA_Which,		UPIMAGE,
               SYSIA_Size,		SYSISIZE(n),
               TAG_END)) {
              if (pic->Lgad = (struct Gadget *)NewObject(NULL,"buttongclass",
                ICA_TARGET,			ICTARGET_IDCMP,
                GA_RelRight,		-(SIZEIMAGE_W(n)+RIGHTIMAGE_W(n)+LEFTIMAGE_W(n)-1),
                GA_RelBottom,		-SIZEIMAGE_H(n)+1,
                GA_Height,			LEFTIMAGE_H(n),
                GA_Width,			LEFTIMAGE_W(n),
                GA_ID,				LEFT_GADGET,
                GA_GZZGadget,		TRUE,
                GA_Immediate,		TRUE,
                GA_RelVerify,		TRUE,
                GA_BottomBorder,	TRUE,
                GA_Previous,		pic->SideGad,
                ICA_MAP,				MapToIdcmp,
                GA_Image,			pic->Limage,
                GA_UserData,		pic,
                TAG_END)) {
               if (pic->Rgad = (struct Gadget *)NewObject(NULL,"buttongclass",
                 ICA_TARGET,		ICTARGET_IDCMP,
                 GA_RelRight,		-(SIZEIMAGE_W(n)+RIGHTIMAGE_W(n)-1),
                 GA_RelBottom,		-SIZEIMAGE_H(n)+1,
                 GA_Height,			LEFTIMAGE_H(n),
                 GA_Width,			LEFTIMAGE_W(n),
                 GA_ID,				RIGHT_GADGET,
                 GA_GZZGadget,		TRUE,
                 GA_Immediate,		TRUE,
                 GA_RelVerify,		TRUE,
                 GA_BottomBorder,	TRUE,
                 GA_Previous,		pic->Lgad,
                 ICA_MAP,			MapToIdcmp,
                 GA_Image,			pic->Rimage,
                 GA_UserData,		pic,
                 TAG_END)) {
                if(pic->Ugad = (struct Gadget *)NewObject(NULL,"buttongclass",
                  ICA_TARGET,		ICTARGET_IDCMP,
                  GA_RelRight,		-SIZEIMAGE_W(n)+1,
                  GA_RelBottom,	-(SIZEIMAGE_H(n)+UPIMAGE_H(n)+DOWNIMAGE_H(n)-1),
                  GA_Height,		UPIMAGE_H(n),
                  GA_Width,			UPIMAGE_W(n),
                  GA_ID,				UP_GADGET,
                  GA_GZZGadget,	TRUE,
                  GA_Immediate,	TRUE,
                  GA_RelVerify,	TRUE,
                  GA_RightBorder,	TRUE,
                  GA_Previous,		pic->Rgad,
                  ICA_MAP,			MapToIdcmp,
                  GA_Image,			pic->Uimage,
                  GA_UserData,		pic,
                  TAG_END)) {
                 if (pic->Dgad = (struct Gadget *)NewObject(NULL,"buttongclass",
                   ICA_TARGET,			ICTARGET_IDCMP,
                   GA_RelRight,		-SIZEIMAGE_W(n)+1,
                   GA_RelBottom,		-(SIZEIMAGE_H(n)+DOWNIMAGE_H(n)-1),
                   GA_Height,			DOWNIMAGE_H(n),
                   GA_Width,			DOWNIMAGE_W(n),
                   GA_ID,				DOWN_GADGET,
                   GA_GZZGadget,		TRUE,
                   GA_Immediate,		TRUE,
                   GA_RelVerify,		TRUE,
                   GA_RightBorder,	TRUE,
                   GA_Previous,		pic->Ugad,
                   ICA_MAP,				MapToIdcmp,
                   GA_Image,			pic->Dimage,
                   GA_UserData,		pic,
                   TAG_END)) {
                   /* Set up size of shrunk window	*/
                   pic->Zoom.Left 	= 0;
                   pic->Zoom.Top 		= pic->Screen->Font->ta_YSize+1;
                   pic->Zoom.Width 	= max(ZOOMIMAGE_W(n)+DEPTHIMAGE_W(n)+CLOSEIMAGE_W(n)+1,
                        							pic->Screen->WBorLeft+SIZEIMAGE_W(n)+LEFTIMAGE_W(n)+RIGHTIMAGE_W(n)+7);
                   pic->Zoom.Height 	= pic->Screen->WBorTop+pic->Screen->Font->ta_YSize+
                   						  SIZEIMAGE_H(n)+UPIMAGE_H(n)+DOWNIMAGE_H(n)+8;
                  /* Copy filename for title and open the window */
                  if (pic->filename 	= AllocVec(strlen(ifilename)+1+20,MEMF_PUBLIC|MEMF_CLEAR)) {	// Extra for other frames
                   strcpy(pic->filename,ifilename);
                   if (pic->Win = OpenWindowTags(NULL,
                     WA_Width,			(pic->ilbm->Bmhd.w<<Zoom)+
                     						pic->Screen->WBorLeft+SIZEIMAGE_W(n),
                     WA_Height,		(pic->ilbm->Bmhd.h<<Zoom)+
                     						pic->Screen->WBorTop+pic->Screen->Font->ta_YSize+1+SIZEIMAGE_H(n),
                     WA_AutoAdjust,	TRUE,
                     WA_MaxWidth,		(pic->ilbm->Bmhd.w<<Zoom)+
                     						pic->Screen->WBorLeft+SIZEIMAGE_W(n),
                     WA_MaxHeight,	(pic->ilbm->Bmhd.h<<Zoom)+
                     						pic->Screen->WBorTop + pic->Screen->Font->ta_YSize+1+SIZEIMAGE_H(n),
                     WA_MinWidth,		pic->Zoom.Width,
                     WA_MinHeight,	pic->Zoom.Height,
                     WA_IDCMP,			0,
                     WA_Flags,			WFLG_SIZEGADGET | WFLG_SIZEBRIGHT | WFLG_SIZEBBOTTOM |
                      					WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET |
                      					WFLG_SUPER_BITMAP + WFLG_GIMMEZEROZERO | WFLG_NOCAREREFRESH,
                     WA_Gadgets,		pic->BotGad,
                     WA_Title,			FilePart(pic->filename),
                     WA_ScreenTitle,	pic->filename,
                     WA_PubScreen,	pic->Screen,
                     WA_SuperBitMap,	(ZoomAllowed ? &(pic->BitMap) : pic->ilbm->brbitmap),
                     /* Open image 1 to the right of the control window
                      * Image 2 to the bottom right of the 1st image
                      */
                     WA_Left, 			((pic == &Pic1)?
                     							ControlWindow->Width:
                     							ControlWindow->Width+Pic1.Win->Width),
                     WA_Top, 			((pic == &Pic1)?
                     							ControlWindow->TopEdge:
                     							Pic1.Win->Height+Pic1.Win->TopEdge),
				 		   WA_MenuHelp,		TRUE,
				 		   WA_NewLookMenus,TRUE,
                     TAG_DONE)) {
                    // Enable gadget Help if possible
				 		  if (IntuitionBase->LibNode.lib_Version > 38) {
                     HelpControl(pic->Win,HC_GADGETHELP);
                    }
                    /* Set user data to determine window
                     * and use shared message port
                    */
                    pic->Win->UserData  = (BYTE *)pic;
                    pic->Win->UserPort	= WMsgPortp;
                    IDCMPFlags = IDCMP_IDCMPUPDATE | IDCMP_GADGETUP | IDCMP_GADGETDOWN |
                                 IDCMP_NEWSIZE | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE |
                                 IDCMP_MENUPICK | IDCMP_CLOSEWINDOW | IDCMP_MENUVERIFY |
                                 IDCMP_MENUHELP | IDCMP_RAWKEY | IDCMP_VANILLAKEY |
                                 IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_CHANGEWINDOW |
                                 IDCMP_GADGETHELP;
                    ModifyIDCMP(pic->Win,IDCMPFlags);
                    pic->Win->Flags |= WFLG_REPORTMOUSE;
						  /* Set mode to draw and erase points easily	*/
						  SetDrMd(pic->Win->RPort,COMPLEMENT);
						  /* Set the (shared with Control Window) menu
						   * and do some size calculations
						   */
						  if (SetMenuStrip(pic->Win,MyMenu)) {
                     doNewSize(pic);
                     return (TRUE);							// It all worked !!!
                    }
                    /* Set relevant error message	*/
                    if (!e) {
                     e = MyGetMsg(MSG_UNABLE);
                     e1 = MyGetMsg(MSG_SETMENU);
                     hnum = HE_Menu;
                    }
                   }
                   if (!e) {
                    e = MyGetMsg(MSG_UNABLE);
                    e1 = MyGetMsg(MSG_OPENW);
                    hnum = HE_OWindow;
                   }
                  }
                  if (!e) {
                   e = MyGetMsg(MSG_UNABLE);
                   e1 = MyGetMsg(MSG_ALLOCFIL);
                   hnum = HE_MemFile;
                  }
                 }
                 if (!e) {
                  e = MyGetMsg(MSG_UNALLOC);
                  e1 = MyGetMsg(MSG_DOWNG);
                  hnum = HE_AllocGadget;
                 }
                }
                if (!e) {
                 e = MyGetMsg(MSG_UNALLOC);
                 e1 = MyGetMsg(MSG_UPG);
                 hnum = HE_AllocGadget;
                }
               }
               if (!e) {
                e = MyGetMsg(MSG_UNALLOC);
                e1 = MyGetMsg(MSG_RIGHTG);
                hnum = HE_AllocGadget;
               }
              }
              if (!e) {
               e = MyGetMsg(MSG_UNALLOC);
               e1 = MyGetMsg(MSG_LEFTG);
               hnum = HE_AllocGadget;
              }
             }
             if (!e) {
              e = MyGetMsg(MSG_UNALLOC);
              e1 = MyGetMsg(MSG_UPI);
              hnum = HE_AllocImage;
             }
            }
            if (!e) {
             e = MyGetMsg(MSG_UNALLOC);
             e1 = MyGetMsg(MSG_DOWNI);
             hnum = HE_AllocImage;
            }
           }
           if (!e) {
            e = MyGetMsg(MSG_UNALLOC);
            e1 = MyGetMsg(MSG_RIGHTI);
            hnum = HE_AllocImage;
           }
          }
          if (!e) {
           e = MyGetMsg(MSG_UNALLOC);
           e1 = MyGetMsg(MSG_LEFTI);
           hnum = HE_AllocImage;
          }
         }
         if (!e) {
          e = MyGetMsg(MSG_UNALLOC);
          e1 = MyGetMsg(MSG_VGAD);
          hnum = HE_AllocGadget;
         }
        }
        if (!e) {
         e = MyGetMsg(MSG_UNALLOC);
         e1 = MyGetMsg(MSG_HGAD);
         hnum = HE_AllocGadget;
        }
       }
      }
     }
    }
    if (!e) {
     e = MyGetMsg(MSG_UNABLE);
     e1 = MyGetMsg(MSG_ALLOCILB);
     hnum = HE_AllocILBM;
    }
   }
   if (!e) {
    e = MyGetMsg(MSG_UNABLE);
    e1 = MyGetMsg(MSG_GETSDI);
    hnum = HE_GetDRI;
   }
  }
  if (!e) {
   e = MyGetMsg(MSG_LOCKPUBS);
   e1 = PubScreenName;
   hnum = HE_LockScreen;
  }
  /* Clear everything down
   * and display an error message if requested
   */
  CloseAPicture(pic);
  if (GUI)
   Error(e,MyGetMsg(MSG_OK),e1,hnum);
 }
 return(FALSE);
}

/* Close a (partially open)
 * picture, clearing everything
 * down in reverse order
 */
void
CloseAPicture(struct Picture *pic) {
	int i;	// Loop counter for bitmaps
	if (pic) {
		if (EGS) {
			if (pic->EGS_Win) {
				EI_CloseWindow(pic->EGS_Win);
				pic->EGS_Win = NULL;
			}
			if (pic->EGS_BitMap) {
				E_DisposeBitMap(pic->EGS_BitMap);
				pic->EGS_BitMap = NULL;
			}
		}
		if (pic->Win) {
			ClearMenuStrip(pic->Win);
			CloseWindowSafely(pic->Win);
			pic->Win = NULL;
		}
		if (pic->filename) {
			FreeVec(pic->filename);
			pic->filename = NULL;
		}
		if (pic->Dgad) {
			DisposeObject(pic->Dgad);
			pic->Dgad = NULL;
		}
		if (pic->Ugad) {
			DisposeObject(pic->Ugad);
			pic->Ugad = NULL;
		}
		if (pic->Rgad) {
			DisposeObject(pic->Rgad);
			pic->Rgad = NULL;
		}
		if (pic->Lgad) {
			DisposeObject(pic->Lgad);
			pic->Lgad = NULL;
		}
		if (pic->Uimage) {
			DisposeObject(pic->Uimage);
			pic->Uimage = NULL;
		}
		if (pic->Dimage) {
			DisposeObject(pic->Dimage);
			pic->Dimage = NULL;
		}
		if (pic->Rimage) {
			DisposeObject(pic->Rimage);
			pic->Rimage = NULL;
		}
		if (pic->Limage) {
			DisposeObject(pic->Limage);
			pic->Limage = NULL;
		}
		if (pic->SideGad) {
			DisposeObject(pic->SideGad);
			pic->SideGad = NULL;
		}
		if (pic->BotGad) {
			DisposeObject(pic->BotGad);
			pic->BotGad = NULL;
		}
		if (ZoomAllowed) {
			for (i=0;
				(i < pic->ilbm->Bmhd.nPlanes) && (i < 8);
				++i) {
				if (pic->BitMap.Planes[i]) {
					FreeRaster(pic->BitMap.Planes[i],pic->ilbm->Bmhd.w<<1,pic->ilbm->Bmhd.h<<1);
					pic->BitMap.Planes[i] = NULL;
				}
			}
		}
		if (pic->ilbm) {
			unloadbrush(pic->ilbm);
			if (pic->ilbm->ParseInfo.iff) {
				FreeIFF(pic->ilbm->ParseInfo.iff);
			}
			FreeMem(pic->ilbm,sizeof(struct ILBMInfo));
			pic->ilbm = NULL;
		}
		if (pic->Screen) {
			if (pic->DRI) {
				FreeScreenDrawInfo(pic->Screen,pic->DRI);
				pic->DRI = NULL;
			}
			UnlockPubScreen(NULL,pic->Screen);
			pic->Screen = NULL;
		}
	}
}

/* After opening or resizing a window
 * this does various gadget recalculations
 */
void
doNewSize(struct Picture *pic) {
	ULONG tmp;
	/* If window made wider then may need to scroll image
	 * right to prevent gap on the right
	 */
	tmp = pic->Win->RPort->Layer->Scroll_X + pic->Win->GZZWidth;
	if (tmp >= (pic->ilbm->Bmhd.w<<Zoom)) {
		ScrollLayer(0,pic->Win->RPort->Layer,(pic->ilbm->Bmhd.w<<Zoom)-tmp,0);
		pic->Left += (pic->ilbm->Bmhd.w<<Zoom)-tmp;
	}
	/* Update sideways gadget and recalculate movement */
	SetGadgetAttrs(pic->BotGad, pic->Win, NULL,
		PGA_Visible, pic->Win->GZZWidth,
		PGA_Top, pic->Left, TAG_END);
	pic->ALeft = pic->Win->GZZWidth/10;
	pic->MLeft = (pic->ilbm->Bmhd.w<<Zoom) - pic->Win->GZZWidth;
	/* If window made taller then may need to scroll image
	 * down to prevent gap at the bottom
	 */
	tmp = pic->Win->RPort->Layer->Scroll_Y + pic->Win->GZZHeight;
	if (tmp >= (pic->ilbm->Bmhd.h<<Zoom)) {
		ScrollLayer(0,pic->Win->RPort->Layer,0,(pic->ilbm->Bmhd.h<<Zoom)-tmp);
		pic->Top += (pic->ilbm->Bmhd.h<<Zoom)-tmp;
	}
	/* Update vertical gadget and recalculate movement */
	SetGadgetAttrs(pic->SideGad, pic->Win, NULL,
		PGA_Visible, pic->Win->GZZHeight,
		PGA_Top, pic->Top, TAG_END);
	pic->ATop = pic->Win->GZZHeight/10;
	pic->MTop = (pic->ilbm->Bmhd.h<<Zoom) - pic->Win->GZZHeight;
}

/* Scroll the image when required */
void
checkGadget(struct Picture *pic) {
	WORD dX;
	WORD dY;
	if (!EGS) {
		dY = pic->Top-pic->XTop;
		dX = pic->Left-pic->XLeft;
		if (dX || dY) {
			ScrollLayer(0,pic->Win->RPort->Layer,dX,dY);
		}
	}
}

/* Draw a point and linked lines if required
 * if MyPoint is not supplied the just draw the point
 */
VOID
DrawPixels(struct Picture *pic,SHORT x,SHORT y,struct MyPoint *MyPoint) {
	SHORT zx,zy;
	int i;
	if (EGS) {
		/* draw 3x3 point
		 */
		zx = x;
		zy = y;
		EG_WritePixel(pic->EGS_Win->RPort,zx-2,zy-2);
		EG_WritePixel(pic->EGS_Win->RPort,zx-1,zy-2);
		EG_WritePixel(pic->EGS_Win->RPort,zx,zy-2);
		EG_WritePixel(pic->EGS_Win->RPort,zx+1,zy-2);
		EG_WritePixel(pic->EGS_Win->RPort,zx+2,zy-2);
		EG_WritePixel(pic->EGS_Win->RPort,zx-2,zy-1);
		EG_WritePixel(pic->EGS_Win->RPort,zx-1,zy-1);
		EG_WritePixel(pic->EGS_Win->RPort,zx,zy-1);
		EG_WritePixel(pic->EGS_Win->RPort,zx+1,zy-1);
		EG_WritePixel(pic->EGS_Win->RPort,zx+2,zy-1);
		EG_WritePixel(pic->EGS_Win->RPort,zx-2,zy);
		EG_WritePixel(pic->EGS_Win->RPort,zx-1,zy);
		EG_WritePixel(pic->EGS_Win->RPort,zx,zy);
		EG_WritePixel(pic->EGS_Win->RPort,zx+1,zy);
		EG_WritePixel(pic->EGS_Win->RPort,zx+2,zy);
		EG_WritePixel(pic->EGS_Win->RPort,zx-2,zy+1);
		EG_WritePixel(pic->EGS_Win->RPort,zx-1,zy+1);
		EG_WritePixel(pic->EGS_Win->RPort,zx,zy+1);
		EG_WritePixel(pic->EGS_Win->RPort,zx+1,zy+1);
		EG_WritePixel(pic->EGS_Win->RPort,zx+2,zy+1);
		EG_WritePixel(pic->EGS_Win->RPort,zx-2,zy+2);
		EG_WritePixel(pic->EGS_Win->RPort,zx-1,zy+2);
		EG_WritePixel(pic->EGS_Win->RPort,zx,zy+2);
		EG_WritePixel(pic->EGS_Win->RPort,zx+1,zy+2);
		EG_WritePixel(pic->EGS_Win->RPort,zx+2,zy+2);
		/* Draw linked lines in the correct window if MyPoint supplied
		 * Note: EGSMyDraw is like EG_Draw only it always draws top left to bottom right
		 * 		to prevent problems when erasing lines in the other direction
		 */
		if (pic == &Pic2) {
			if (MyPoint) {
				for (i = 0;
					  i < MAX_LINKS;
					  i++) {
					if (MyPoint->p[i]) {
						EGSMyDraw(pic->EGS_Win->RPort,MyPoint->p[i]->x1,MyPoint->p[i]->y1,zx,zy);
					}
				}
			}
		}
		else {
			if (MyPoint) {
				for (i = 0;
					  i < MAX_LINKS;
					  i++) {
					if (MyPoint->p[i]) {
						EGSMyDraw(pic->EGS_Win->RPort,MyPoint->p[i]->x,MyPoint->p[i]->y,zx,zy);
					}
				}
			}
		}
	}
	else {
		/* Scale coordinates if zoomed
		 * and draw 3x3 point
		 */
		zx = x << Zoom;
		zy = y << Zoom;
		WritePixel(pic->Win->RPort,zx-2,zy-2);
		WritePixel(pic->Win->RPort,zx-1,zy-2);
		WritePixel(pic->Win->RPort,zx,zy-2);
		WritePixel(pic->Win->RPort,zx+1,zy-2);
		WritePixel(pic->Win->RPort,zx+2,zy-2);
		WritePixel(pic->Win->RPort,zx-2,zy-1);
		WritePixel(pic->Win->RPort,zx-1,zy-1);
		WritePixel(pic->Win->RPort,zx,zy-1);
		WritePixel(pic->Win->RPort,zx+1,zy-1);
		WritePixel(pic->Win->RPort,zx+2,zy-1);
		WritePixel(pic->Win->RPort,zx-2,zy);
		WritePixel(pic->Win->RPort,zx-1,zy);
		WritePixel(pic->Win->RPort,zx,zy);
		WritePixel(pic->Win->RPort,zx+1,zy);
		WritePixel(pic->Win->RPort,zx+2,zy);
		WritePixel(pic->Win->RPort,zx-2,zy+1);
		WritePixel(pic->Win->RPort,zx-1,zy+1);
		WritePixel(pic->Win->RPort,zx,zy+1);
		WritePixel(pic->Win->RPort,zx+1,zy+1);
		WritePixel(pic->Win->RPort,zx+2,zy+1);
		WritePixel(pic->Win->RPort,zx-2,zy+2);
		WritePixel(pic->Win->RPort,zx-1,zy+2);
		WritePixel(pic->Win->RPort,zx,zy+2);
		WritePixel(pic->Win->RPort,zx+1,zy+2);
		WritePixel(pic->Win->RPort,zx+2,zy+2);
		/* Draw linked lines in the correct window if MyPoint supplied
		 * Note: MyDraw is like Draw only it always draws top left to bottom right
		 * 		to prevent problems when erasing lines in the other direction
		 */
		if (pic == &Pic2) {
			if (MyPoint) {
				for (i = 0;
					  i < MAX_LINKS;
					  i++) {
					if (MyPoint->p[i]) {
						MyDraw(pic->Win->RPort,MyPoint->p[i]->x1<<Zoom,MyPoint->p[i]->y1<<Zoom,zx,zy);
					}	
				}
			}
		}
		else {
			if (MyPoint) {
				for (i = 0;
					  i < MAX_LINKS;
					  i++) {
					if (MyPoint->p[i]) {
						MyDraw(pic->Win->RPort,MyPoint->p[i]->x<<Zoom,MyPoint->p[i]->y<<Zoom,zx,zy);
					}
				}
			}
		}
	}
}	

/* Delete all points
 * Erasing them if images are open
 */
void
DeleteAllPoints(void) {
	struct MyPoint *MyPoint;
	/* Loop round looking at the first point every time
	 * since DeletePoint removes it from the list
	 */
	while ((MyPoint = (struct MyPoint *)PointList.lh_Head)->MyNode.mln_Succ) {
		if (Pic1_Open) {
			DrawPixels(&Pic1,MyPoint->x,MyPoint->y,MyPoint);
		}
		if (Pic2_Open) {
			DrawPixels(&Pic2,MyPoint->x1,MyPoint->y1,MyPoint);
		}
		DeletePoint(MyPoint);
	}
}

/* Open a project
 * Suggests you save first if not already saved
 * Returns		: TRUE or FALSE for how well it went
 * filename		: file name to open - if NULL then display ASL file requeseter
 * JustPoints	: If TRUE then only the points are used
 * Gui         : Display error messages
 */
BOOL
MyOpen(char *filename,BOOL JustPoints,BOOL Gui) {
	LONG PointCount	= 0;		// Number of points read
	LONG i;							// General loop counter
	char *ifilename	= NULL;	// File name to use
	BOOL ok				= TRUE;	// Is it all working?
	BPTR fh;							// File handle
	char buffer[257];				// Buffer to read records
	LONG w=0,h=0;					// Width and Height
	LONG x,x1,y,y1;				// Coordinates in image 1 and 2
	LONG p1,p2;						// Index to linked points
	LONG Frames;					// Number of frames
	struct MyPoint *MyPoint,	// Points to create and link
						*MyPoint1;
	BOOL JP = FALSE;				// Set if 2.0 points file
	/* If current project not saved then suggest it is saved	*/
	if (!Saved) {
		if (!SaveRequester()) {
			return ok;
		}
		DisableWindows(DI_WaitOpen);
	}
	/* Get filename, from parameter or ASL requester, save name for saving later */
	if (filename) {
		ifilename = filename;
		if (!JustPoints) {
			strncpy(savedfilename,filename,256);
		}
	}
	else {
		if (GetAFile(*savedfilename?savedfilename:"",
						 (Tag) JustPoints ? MyGetMsg(MSG_LOADPO): MyGetMsg(MSG_LOADPR),
						 0)) {
			ifilename=TempFilename;
			if (!JustPoints) {
				strncpy(savedfilename,TempFilename,256);
			}
		}
  	}
  	/* If we have a filename then delete current points and set the window title	*/
	if (ifilename) {
		if (!JustPoints) {
			OpenNewArgs(ifilename);		// Load new parameters
			InitParams(FALSE);
		}
		DeleteAllPoints();
		SetWindowTitles(TSMorphWnd,(UBYTE *)-1,savedfilename);
		if (fh=Open(ifilename,MODE_OLDFILE)) {
			// Get header
			FGets(fh,buffer,256);
			if (JustPoints && (JP = !strcmp(buffer,"TSMorph 2.0\n"))) {
				DeleteAllPoints();
			}
			else {
				if (strcmp(buffer,"TSMorph 1.2\n")) {
					Error(MyGetMsg(MSG_VERS10),MyGetMsg(MSG_OK),NULL,HE_OldFormat);
				}
				else {
					// Name of first image
					FGets(fh,buffer,256);
				}
			}
			if (!JustPoints) {
				if (strlen(buffer)) {
					buffer[strlen(buffer)-1]=0;
				}
				GT_SetGadgetAttrs(TSMorphGadgets[GDX_FileOne],TSMorphWnd,NULL,
										GTST_String, buffer, TAG_END );
			}
			// Name of second image
			if (!JP) {
				FGets(fh,buffer,256);
				if (!JustPoints) {
					if (strlen(buffer)) {
						buffer[strlen(buffer)-1]=0;
					}
					GT_SetGadgetAttrs(TSMorphGadgets[GDX_FileTwo],TSMorphWnd,NULL,
											GTST_String, buffer, TAG_END );
				}
				// 24 bit name of first image
				FGets(fh,buffer,256);
				if (!JustPoints) {
					if (strlen(buffer)) {
						buffer[strlen(buffer)-1]=0;
					}
					GT_SetGadgetAttrs(TSMorphGadgets[GDX_File241],TSMorphWnd,NULL,
											GTST_String, buffer, TAG_END );
				}
				// 24 bit name of second image
				FGets(fh,buffer,256);
				if (!JustPoints) {
					if (strlen(buffer)) {
						buffer[strlen(buffer)-1]=0;
					}
					GT_SetGadgetAttrs(TSMorphGadgets[GDX_File242],TSMorphWnd,NULL,
											GTST_String, buffer, TAG_END );
				}
				// Name of animation
				FGets(fh,buffer,256);
				if (!JustPoints) {
					if (strlen(buffer)) {
						buffer[strlen(buffer)-1]=0;
					}
					GT_SetGadgetAttrs(TSMorphGadgets[GDX_Name],TSMorphWnd,NULL,
											GTST_String, buffer, TAG_END );
				}
				// General stuff
				FGets(fh,buffer,256);
				if (!JustPoints) {
					if (ok && (sscanf(buffer,"w=%ld,h=%ld,Frames=%ld,Single=%ld,Start=%ld",&w,&h,&Frames,&SinglePicture,&Start) != 5)) {
						Error(MyGetMsg(MSG_INVLINE),MyGetMsg(MSG_OK),buffer,HE_FileFormat);
						ok = FALSE;
					}
					else {
						GT_SetGadgetAttrs(TSMorphGadgets[GDX_Frames],TSMorphWnd,NULL,
												GTIN_Number,Frames, TAG_END );
						GT_SetGadgetAttrs(TSMorphGadgets[GDX_Start],TSMorphWnd,NULL,
													GTIN_Number,Start, TAG_END );
						GT_SetGadgetAttrs(TSMorphGadgets[GDX_SinglePicture],TSMorphWnd,NULL,
												GTCY_Active,SinglePicture, TAG_END );
						if (ok && ControlWindow &&
								((w > Pic1.ilbm->Bmhd.w) ||
							 (h > Pic1.ilbm->Bmhd.h))) {
							Error(MyGetMsg(MSG_ITOOSM),MyGetMsg(MSG_OK),NULL,HE_TooSmall);
							ok = FALSE;
						}
					}
				}
			}
			if (ok) {
				MaxWidth 	= 0;
				MaxHeight 	= 0;
				// Read and validate point
				while (ok &&
					FGets(fh,buffer,256) &&
					(sscanf(buffer,"x=%ld,y=%ld,x1=%ld,y1=%ld",&x,&y,&x1,&y1) == 4)) {
					if (Pic1_Open) {
						if ((x<0)||(x>(Pic1.ilbm->Bmhd.w-1)) ||
							 (y<0)||(y>(Pic1.ilbm->Bmhd.h-1))) {
							Error(MyGetMsg(MSG_POOR),MyGetMsg(MSG_OK),buffer,HE_Range);
							ok = FALSE;
						}
					}
					// Create point and add to list
					if (MyPoint = AllocMem(sizeof(struct MyPoint),MEMF_CLEAR)) {
						MyPoint->x = x;
						MyPoint->y = y;
						MyPoint->x1 = x1;
						MyPoint->y1 = y1;
						MaxWidth = max(x,MaxWidth);
						MaxWidth = max(x1,MaxWidth);
						MaxHeight = max(y,MaxHeight);
						MaxHeight = max(y1,MaxHeight);
						AddTail(&PointList,(struct Node *)MyPoint);
						++PointCount;
						if (ControlWindow) {
							// If the windows are open then actually draw the points
							DrawPixels(&Pic1,x,y,MyPoint);
							DrawPixels(&Pic2,x1,y1,MyPoint);
						}
					}
					else {
						Error(MyGetMsg(MSG_OOMPO),MyGetMsg(MSG_OK),NULL,HE_MemPoints);
						ok=FALSE;
					}
				}
				Width = max(w,MaxWidth);
				Height = max(h,MaxHeight);
				if (Pic1_Open) {
					Width = max(Width,Pic1.width);
					Height = max(Height,Pic1.height);
				}
				GT_SetGadgetAttrs(TSMorphGadgets[GDX_Width],TSMorphWnd,NULL,
										GTNM_Number,Width, TAG_END );
				GT_SetGadgetAttrs(TSMorphGadgets[GDX_Height],TSMorphWnd,NULL,
										GTNM_Number,Height, TAG_END );
				// Read all the links
				while (ok &&
					(sscanf(buffer,"p1=%ld,p2=%ld",&p1,&p2) == 2)) {
					if ((p1>PointCount) || (p2>PointCount)) {
						Error(MyGetMsg(MSG_INVPOLI),MyGetMsg(MSG_OK),buffer,HE_InvLink);
						ok = FALSE;
					}
					else {
						// Link two points based on indexes to linked lists
						i = 0;
						MyPoint = (struct MyPoint *)PointList.lh_Head;
						while (i < p1) {
							MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ;
							++i;
						}
						i = 0;
						MyPoint1 = (struct MyPoint *)PointList.lh_Head;
						while (i < p2) {
							MyPoint1 = (struct MyPoint *)MyPoint1->MyNode.mln_Succ;
							++i;
						}
						LinkPoints(MyPoint,MyPoint1);
					}
					if (!FGets(fh,buffer,256)) {
						ok = FALSE;
					}
				}
			}
			// Close file and return cleanly
			if (!Close(fh)) {
				if (ok) {
					Error(MyGetMsg(MSG_ECLOF),MyGetMsg(MSG_OK),ifilename,HE_Close);
					ok = FALSE;
				}
			}
		}
		else {
			if (Gui) {
				Error(MyGetMsg(MSG_EOPF),MyGetMsg(MSG_OK),ifilename,HE_Open);
			}
			ok = FALSE;
		}
	}
	if (ok && !JustPoints) {
		Saved = TRUE;
	}
	else {
		if (ok && JustPoints) {
			Saved = FALSE;
		}
	}
	return ok;
}

/* Saves a project
 * Returns		: TRUE or FALSE for how well it went
 * filename		: file name to open - if NULL then display ASL file requeseter
 */
BOOL
SaveAs(char *filename) {
	char buffer[257];				// buffer to write records
	char *ifilename	= NULL;	// File name to use
	BPTR fh;							// File handle
	LONG i,							// Loop counters
		  j,
		  k;
	BOOL ok;							// How well is it going
	struct MyPoint *MyPoint,	// Points to write
						*MyPoint1;
	struct DiskObject *MyDiskObject;	// The Icon
	/* Set up the file name from the parameter or using and ASL requester	*/
	if (filename && *filename) {
		ifilename = filename;
		strncpy(savedfilename,filename,256);
	}
	else {
		if (GetAFile(*savedfilename?savedfilename:"",MyGetMsg(MSG_SAVEP),FILF_SAVE)) {
			ifilename=TempFilename;
			strncpy(savedfilename,TempFilename,256);
		}
  	}
  	/* If we have a file name then set the window title
  	 * and write out the fixed information
  	 */
	if (ifilename) {
		SetWindowTitles(TSMorphWnd,(UBYTE *)-1,savedfilename);
		if (fh=Open(ifilename,MODE_NEWFILE)) {
			FPuts(fh,"TSMorph 1.2\n");
			FPuts(fh,GetString(TSMorphGadgets[GDX_FileOne]));
			FPuts(fh,"\n");
			FPuts(fh,GetString(TSMorphGadgets[GDX_FileTwo]));
			FPuts(fh,"\n");
			FPuts(fh,GetString(TSMorphGadgets[GDX_File241]));
			FPuts(fh,"\n");
			if ((SinglePicture == 0) || (SinglePicture == 2)) {
				FPuts(fh,GetString(TSMorphGadgets[GDX_File242]));
			}
			FPuts(fh,"\n");
			FPuts(fh,GetString(TSMorphGadgets[GDX_Name]));
			FPuts(fh,"\n");
			sprintf(buffer,"w=%ld,h=%ld,Frames=%ld,Single=%ld,Start=%ld\n",
					Width,Height,GetNumber(TSMorphGadgets[GDX_Frames]),SinglePicture,GetNumber(TSMorphGadgets[GDX_Start]));
			ok = !FPuts(fh,buffer);
			if ((SinglePicture == 2) || (SinglePicture == 3)) {
				if (ControlWindow) {
					if (!Close(fh)) {
						if (ok) {
							Error(MyGetMsg(MSG_ECLOF),MyGetMsg(MSG_OK),ifilename,HE_Close);
							ok = FALSE;
						}
					}
					strcpy(buffer,ifilename);
					strcat(buffer,".%03ld");
					sprintf(TempFilename,buffer,FrameNumber);
					ifilename = TempFilename;
					if (fh=Open(ifilename,MODE_NEWFILE)) {
						FPuts(fh,"TSMorph 2.0\n");
					}
					else {
						Error(MyGetMsg(MSG_EOPF),MyGetMsg(MSG_OK),ifilename,HE_Open);
						ok = FALSE;
					}
				}
			}
			// Write out all the points
			for (MyPoint = (struct MyPoint *)PointList.lh_Head;
					MyPoint->MyNode.mln_Succ && ok;
					MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
				sprintf(buffer,"x=%ld,y=%ld,x1=%ld,y1=%ld\n",MyPoint->x,MyPoint->y,MyPoint->x1,MyPoint->y1);
				ok = !FPuts(fh,buffer);
			}
			// Write out all the links
			i = 0;
			for (MyPoint = (struct MyPoint *)PointList.lh_Head;
					MyPoint->MyNode.mln_Succ && ok;
					MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
				j = 0;
				for (MyPoint1= (struct MyPoint *)PointList.lh_Head;
						MyPoint1->MyNode.mln_Succ;
						MyPoint1 = (struct MyPoint *)MyPoint1->MyNode.mln_Succ) {
					// Only write each link once
					if (j>i) {
						for (k = 0;
							  k < MAX_LINKS;
							  k++) {
							if (MyPoint->p[k] == MyPoint1) {
								sprintf(buffer,"p1=%ld,p2=%ld\n",i,j);
								ok = !FPuts(fh,buffer);
							}
						}
					}
					++j;
				}
				++i;
			}
			if (!ok) {
				Error(MyGetMsg(MSG_EWRR),MyGetMsg(MSG_OK),ifilename,HE_Write);
			}
			// Close file and clean up
			if (!Close(fh)) {
				if (ok) {
					Error(MyGetMsg(MSG_ECLOF),MyGetMsg(MSG_OK),ifilename,HE_Close);
					ok = FALSE;
				}
			}
		}
		else {
			Error(MyGetMsg(MSG_EOPF),MyGetMsg(MSG_OK),ifilename,HE_Open);
			ok = FALSE;
		}
		// Write Icon if required and none already exists
		if (ok) {
			if (CreateIcons) {
				if (MyDiskObject = GetDiskObject(savedfilename)) {
					FreeDiskObject(MyDiskObject);
				}
				else {
					if ((MyDiskObject = GetDiskObject("ENV:TSMorph/def_points")) ||
					    (MyDiskObject = GetDiskObject("ENV:SYS/def_points")) ||
						 (MyDiskObject = GetDefDiskObject(WBPROJECT))) {
						PutDiskObject(savedfilename,MyDiskObject);
						FreeDiskObject(MyDiskObject);
					}
				}
			}
			Saved = TRUE;
		}
	}
	else {
		ok = FALSE;
	}
	return ok;
}

/* Set editing mode
 * This sets the window title, pointer, gadgets, menus etc.
 */
void
MySetMode(UWORD NewMode) {
	UWORD 			oldpos;				// Pointer to unlink gadgets
	UWORD 			menupos;				// menu pointer
	struct Gadget 	*Gadget1	= NULL;	// Gadget to update
	ULONG				HNum;
	// Determine "current" menu and gadget
	switch(Mode) {
	case EDIT1:
		Gadget1 = &OneGadget;
		menupos = MI_EDITONE;
		break;
	case EDIT2:
		Gadget1 = &TwoGadget;
		menupos = MI_EDITTWO;
		break;
	case EDITREL:
	 	Gadget1 = &RelGadget;
		menupos = MI_EDITREL;
	 	break;
	case ADD:
		Gadget1 = &MyAddGadget;
		menupos = MI_ADD;
		break;
	case DELETE:
		Gadget1 = &DelGadget;
		menupos = MI_DELETE;
		break;
	case LINK1:
	case LINK2:
	case LINK2A:
		Gadget1 = &LinkGadget;
		menupos = MI_LINK;
		break;
	case UNLINK1:
	case UNLINK2:
	case UNLINK2A:
		Gadget1 = &UnlinkGadget;
		menupos = MI_UNLINK;
		break;
	case NONE:
		Gadget1 = &NoneGadget;
		menupos = MI_NONE;
		break;
	}
	// Unselect old gadget
	oldpos = RemoveGList(ControlWindow,Gadget1,1);
	Gadget1->Flags &= ~GFLG_SELECTED;
	AddGList(ControlWindow,Gadget1,oldpos,1,NULL);
	RefreshGList(Gadget1,ControlWindow,NULL,1);
	/* Remove menus and
	 * Unselect old menu item
	 * Actually unselects all (why?)
	 */
	if (!EGS) {
		if (Pic1_Open) {
			ClearMenuStrip(Pic1.Win);
		}
		if (Pic2_Open) {
			ClearMenuStrip(Pic2.Win);
		}
	}
	ClearMenuStrip(ControlWindow);
	(ItemAddress(MyMenu,FULLMENUNUM(M_EDIT,MM_MODE,0)))->Flags &= ~CHECKED;
	(ItemAddress(MyMenu,FULLMENUNUM(M_EDIT,MM_MODE,1)))->Flags &= ~CHECKED;
	(ItemAddress(MyMenu,FULLMENUNUM(M_EDIT,MM_MODE,2)))->Flags &= ~CHECKED;
	(ItemAddress(MyMenu,FULLMENUNUM(M_EDIT,MM_MODE,3)))->Flags &= ~CHECKED;
	(ItemAddress(MyMenu,FULLMENUNUM(M_EDIT,MM_MODE,4)))->Flags &= ~CHECKED;
	(ItemAddress(MyMenu,FULLMENUNUM(M_EDIT,MM_MODE,5)))->Flags &= ~CHECKED;
	(ItemAddress(MyMenu,FULLMENUNUM(M_EDIT,MM_MODE,6)))->Flags &= ~CHECKED;
	(ItemAddress(MyMenu,FULLMENUNUM(M_EDIT,MM_MODE,7)))->Flags &= ~CHECKED;
	// Determine "new" title, gadget and menu
	switch (NewMode) {
	case EDIT1:
		SetWindowTitles(ControlWindow,MyGetMsg(MSG_1),(UBYTE *)-1);
		Gadget1 = &OneGadget;
		menupos = MI_EDITONE;
		HNum = H_EOne;
		break;
	case EDIT2:
		SetWindowTitles(ControlWindow,MyGetMsg(MSG_2),(UBYTE *)-1);
		Gadget1 = &TwoGadget;
		menupos = MI_EDITTWO;
		HNum = H_ETwo;
		break;
	case EDITREL:
		SetWindowTitles(ControlWindow,MyGetMsg(MSG_REL),(UBYTE *)-1);
	 	Gadget1 = &RelGadget;
		menupos = MI_EDITREL;
		HNum = H_ERel;
		break;
	case ADD:
		SetWindowTitles(ControlWindow,MyGetMsg(MSG_ADD),(UBYTE *)-1);
	  	Gadget1 = &MyAddGadget;
		menupos = MI_ADD;
		HNum = H_EAdd;
		break;
	case DELETE:
		SetWindowTitles(ControlWindow,MyGetMsg(MSG_DEL),(UBYTE *)-1);
	  	Gadget1 = &DelGadget;
		menupos = MI_DELETE;
		HNum = H_EDel;
		break;
	case LINK1:
		SetWindowTitles(ControlWindow,MyGetMsg(MSG_L1),(UBYTE *)-1);
	  	Gadget1 = &LinkGadget;
		menupos = MI_LINK;
		HNum = H_ELnk;
		break;
	case UNLINK1:
		SetWindowTitles(ControlWindow,MyGetMsg(MSG_U1),(UBYTE *)-1);
	  	Gadget1 = &UnlinkGadget;
		menupos = MI_UNLINK;
		HNum = H_EUnl;
		break;
	case NONE:
		SetWindowTitles(ControlWindow,MyGetMsg(MSG_MOV),(UBYTE *)-1);
	 	Gadget1 = &NoneGadget;
		menupos = MI_NONE;
		HNum = H_EMov;
		break;
	}
	// Select new gadget
	oldpos = RemoveGList(ControlWindow,Gadget1,1);
	Gadget1->Flags |= GFLG_SELECTED;
	AddGList(ControlWindow,Gadget1,oldpos,1,NULL);
	RefreshGList(Gadget1,ControlWindow,NULL,1);
	// Select new menu item and readd menus
	(ItemAddress(MyMenu,FULLMENUNUM(M_EDIT,MM_MODE,menupos)))->Flags |= CHECKED;
	ResetMenuStrip(ControlWindow,MyMenu);
	if (!EGS) {
		if (Pic1_Open) {
			ResetMenuStrip(Pic1.Win,MyMenu);
		}
		if (Pic2_Open) {
			ResetMenuStrip(Pic2.Win,MyMenu);
		}
	}
	// Set mode and set the pointer
	Mode = NewMode;
	SetMyPointer();
	// Display (short) help
	if (GHelp) {
		help(HNum);
	}
	else {
		ihelp(HNum);
	}
}

BOOL 						SelDown = FALSE;	// Set if left button currently pressed
UWORD 					OldLeft,		// Old position of image
							OldTop;
UWORD 					OldLeft1,	// Old position of other image
							OldTop1;
struct MyPoint 		*MyPoint,	// Points to add, link etc.
							*MyPoint1;
SHORT 					OldX,			// Old coordinates
							OldY;
SHORT 					OldX1,		// Old coordinates in other window
							OldY1;
SHORT 					CurX,			// Current coordinates
							CurY;
SHORT 					CurX1,		// Current coordinates in other window
							CurY1;
struct Picture 		*pic1;		// The other image

/* The main program
 * this loops until the program is quited
 */
void
doMsgLoop(void) {
	UWORD 					X,				// Coordinates
								Y;
	struct IntuiMessage 	*msg;			// Message from the Control window
	struct EI_EIntuiMsg 	*EGSmsg;		// Message from the EGS windows
	struct Picture 		*pic;			// Main image pointer
	int 						flag 	= 1;	// 1 = keep going, 0 = quit, 2 = Close control and image windows
	UWORD 					Shift;		// Set if either Shift key pressed
	ULONG 					Signals;		// Signals set after Wait()
	UWORD 					Selection;	// Menu selection
	struct AmigaGuideMsg *agm;			// message from amigaguide
	ULONG HNum;								// The Help node to use
	/* Loop until we quit	*/
	while (flag==1) {
		// Wait on open windows etc.
		Signals = Wait((ASig) |
							(1L << TSMorphWnd->UserPort->mp_SigBit) |
							(1L << WMsgPortp->mp_SigBit) |
							(ControlWindow ? (1L << ControlWindow->UserPort->mp_SigBit) : 0));
		// Something for the Information window
		if (Signals & (1L << TSMorphWnd->UserPort->mp_SigBit)) {
			flag = HandleTSMorphIDCMP();
		}
		/* Something for amigaguide
		 * Note: all we do is reply the message(s)
		 */
		if (Signals & ASig) {
			if (handle) {
				while (agm = GetAmigaGuideMsg(handle)) {
					switch (agm->agm_Type) {
					case ToolCmdReplyID:
						break;
					case ToolStatusID:
						break;
					default:
						break;
					}
					ReplyAmigaGuideMsg(agm);
				}
			}
		}
		// Something for the Control window
		if (ControlWindow &&
			(Signals & (1L << ControlWindow->UserPort->mp_SigBit))) {
			// Loop on all messages
		 	while (msg = (struct IntuiMessage *)GetMsg(ControlWindow->UserPort)) {
		 		switch (msg->Class) {
		 		// gadget help
		 		case IDCMP_GADGETHELP:
	 				if (msg->IAddress == NULL) {
	 					HNum = 0;
	 				}
	 				else {
	 					if (msg->IAddress == ControlWindow) {
							switch(Mode) {
							case EDIT1:
								HNum = H_EOne;
								break;
							case EDIT2:
								HNum = H_ETwo;
								break;
							case EDITREL:
								HNum = H_ERel;
							 	break;
							case ADD:
								HNum = H_EAdd;
								break;
							case DELETE:
								HNum = H_EDel;
								break;
							case LINK1:
							case LINK2:
							case LINK2A:
								HNum = H_ELnk;
								break;
							case UNLINK1:
							case UNLINK2:
							case UNLINK2A:
								HNum = H_EUnl;
								break;
							case NONE:
								HNum = H_EMov;
								break;
							default:
								HNum = H_CWindow;
								break;
							}
						}
	 					else {
	 						switch (((struct Gadget *)msg->IAddress)->GadgetType &0xf0) {
	 						case GTYP_WDRAGGING:
	 							HNum = H_CWindow;
	 							break;
	 						case GTYP_WUPFRONT:
	 							HNum = H_CDepth;
	 							break;
	 						case GTYP_CLOSE:
	 							HNum = H_CClose;
	 							break;
	 						case 0:
	 							switch (((struct Gadget *)msg->IAddress)->GadgetID) {
	 							case ONEGADGET:
	 								HNum = H_EOne;
	 								break;
	 							case TWOGADGET:
	 								HNum = H_ETwo;
	 								break;
	 							case RELGADGET:
	 								HNum = H_ERel;
	 								break;
	 							case DELGADGET:
	 								HNum = H_EDel;
	 								break;
	 							case UNLINKGADGET:
	 								HNum = H_EUnl;
	 								break;
	 							case LINKGADGET:
	 								HNum = H_ELnk;
	 								break;
	 							case NONEGADGET:
	 								HNum = H_EMov;
	 								break;
	 							case ADDGADGET:
	 								HNum = H_EAdd;
	 								break;
	 							case STGADGET:
	 								HNum = HC_First;
	 								break;
	 							case PREVGADGET:
	 								HNum = HC_Previous;
	 								break;
	 							case GOTOGADGET:
	 								HNum = HC_Goto;
	 								break;
	 							case NEXTGADGET:
	 								HNum = HC_Next;
	 								break;
	 							case LASTGADGET:
	 								HNum = HC_Last;
	 								break;
	 							default:
	 								HNum = H_CWindow;
	 								break;
	 							}
	 							break;
	 						default:
	 							HNum = H_CWindow;
	 							break;
	 						}
	 					}
	 				}
	 				if (HNum) {
	 					if (GHelp) {
			 				help(HNum);
			 			}
			 			else {
			 				ihelp(HNum);
			 			}
		 			}
		 			break;
		 		case IDCMP_VANILLAKEY:
			 		// No vanilla keys currently defined
		 			break;
		 		case IDCMP_RAWKEY:
			 		// only raw key is the help key
		 			switch (msg->Code) {
		 			case 0x5F:
		 				/* determine if pointer is in a gadget
		 				 * otherwise show help on the whole window
		 				 */
						X = ControlWindow->MouseX;
						Y = ControlWindow->MouseY;
						if (PointInBox(X,Y,0,0,
												CLOSEIMAGE_W(n),ControlWindow->BorderTop))
							HNum = H_CClose;
						else
						if (PointInBox(X,Y,(ControlWindow->Width - DEPTHIMAGE_W(n)),0,
												ControlWindow->Width,ControlWindow->BorderTop))
							HNum = H_CDepth;
						else
						if (PointInBox(X,Y,OneGadget.LeftEdge,OneGadget.TopEdge,
												OneGadget.LeftEdge+OneGadget.Width,OneGadget.TopEdge+OneGadget.Height))
							HNum = H_EOne;
						else
						if (PointInBox(X,Y,TwoGadget.LeftEdge,TwoGadget.TopEdge,
												TwoGadget.LeftEdge+TwoGadget.Width,TwoGadget.TopEdge+TwoGadget.Height))
							HNum = H_ETwo;
						else
						if (PointInBox(X,Y,RelGadget.LeftEdge,RelGadget.TopEdge,
												RelGadget.LeftEdge+RelGadget.Width,RelGadget.TopEdge+RelGadget.Height))
							HNum = H_ERel;
						else
						if (PointInBox(X,Y,DelGadget.LeftEdge,DelGadget.TopEdge,
												DelGadget.LeftEdge+DelGadget.Width,DelGadget.TopEdge+DelGadget.Height))
							HNum = H_EDel;
						else
						if (PointInBox(X,Y,UnlinkGadget.LeftEdge,UnlinkGadget.TopEdge,
												UnlinkGadget.LeftEdge+UnlinkGadget.Width,UnlinkGadget.TopEdge+UnlinkGadget.Height))
							HNum = H_EUnl;
						else
						if (PointInBox(X,Y,LinkGadget.LeftEdge,LinkGadget.TopEdge,
												LinkGadget.LeftEdge+LinkGadget.Width,LinkGadget.TopEdge+LinkGadget.Height))
							HNum = H_ELnk;
						else
						if (PointInBox(X,Y,NoneGadget.LeftEdge,NoneGadget.TopEdge,
												NoneGadget.LeftEdge+NoneGadget.Width,NoneGadget.TopEdge+NoneGadget.Height))
							HNum = H_EMov;
						else
						if (PointInBox(X,Y,MyAddGadget.LeftEdge,MyAddGadget.TopEdge,
												MyAddGadget.LeftEdge+MyAddGadget.Width,MyAddGadget.TopEdge+MyAddGadget.Height))
							HNum = H_EAdd;
						else
						if (PointInBox(X,Y,stGadget.LeftEdge,stGadget.TopEdge,
												stGadget.LeftEdge+stGadget.Width,stGadget.TopEdge+stGadget.Height))
							HNum = HC_First;
						else
						if (PointInBox(X,Y,prevGadget.LeftEdge,prevGadget.TopEdge,
												prevGadget.LeftEdge+prevGadget.Width,prevGadget.TopEdge+prevGadget.Height))
							HNum = HC_Previous;
						else
						if (PointInBox(X,Y,gotoGadget.LeftEdge,gotoGadget.TopEdge,
												gotoGadget.LeftEdge+gotoGadget.Width,gotoGadget.TopEdge+gotoGadget.Height))
							HNum = HC_Goto;
						else
						if (PointInBox(X,Y,nextGadget.LeftEdge,nextGadget.TopEdge,
												nextGadget.LeftEdge+nextGadget.Width,nextGadget.TopEdge+nextGadget.Height))
							HNum = HC_Next;
						else
						if (PointInBox(X,Y,lastGadget.LeftEdge,lastGadget.TopEdge,
												lastGadget.LeftEdge+lastGadget.Width,lastGadget.TopEdge+lastGadget.Height))
							HNum = HC_Last;
						else
							HNum = H_CWindow;
						help(HNum);
		 				break;
		 			default:
		 				// any other key
		 				break;
		 			}
		 			break;
		 		case IDCMP_MENUHELP:
			 		// Show help on the Control and image windows menus
		 			DoMenuHelp(msg->Code);
		 			break;
		 		case IDCMP_GADGETDOWN:
			 		// Gadget down so set mode to the gadget pressed
		 			switch (((struct Gadget *)(msg->IAddress))->GadgetID) {
					case ONEGADGET:
						MySetMode(EDIT1);
 						break;
 					case TWOGADGET:
 						MySetMode(EDIT2);
  						break;
 					case RELGADGET:
  						MySetMode(EDITREL);
  						break;
 					case ADDGADGET:
 						MySetMode(ADD);
  						break;
 					case DELGADGET:
 						MySetMode(DELETE);
  						break;
  					case LINKGADGET:
  						MySetMode(LINK1);
  						break;
 					case UNLINKGADGET:
 						MySetMode(UNLINK1);
  						break;
  					case NONEGADGET:
  						MySetMode(NONE);
	  					break;
	  				default:
	  					// unkown gadget ?
	  					break;
		 			}
		 			break;
		 		case IDCMP_GADGETUP:
			 		// Gadget up so change frame
			 		switch (((struct Gadget *)(msg->IAddress))->GadgetID) {
					case STGADGET:
						flag = FirstFrame();
 						break;
 					case PREVGADGET:
 						flag = PrevFrame();
 						break;
 					case GOTOGADGET:
 						flag = GotoFrame();
 						break;
 					case NEXTGADGET:
 						flag = NextFrame();
 						break;
 					case LASTGADGET:
 						flag = LastFrame();
 						break;
					default:
						break;
					}
					break;
		 		case IDCMP_CLOSEWINDOW:
			 		// Close window - set flag to close image windows as well
					flag = 2;
		 			break;
		 		case IDCMP_MENUPICK:
			 		// Loop around menu selections
					Selection = msg->Code;
					while ((Selection != MENUNULL) && (flag==1)) {
						flag = DoMenu(NULL,Selection);
						Selection = ((struct MenuItem *)ItemAddress(MyMenu,(LONG)Selection))->NextSelect;
					}
		 			break;
		 		default:
			 		// unknown message
		 			break;
		 		}
				ReplyMsg((struct Message *)msg);
		 	}
	  	}
	  	// Something from one of the image windows
		if (Signals & (1L << WMsgPortp->mp_SigBit)) {
		 if (EGS) {
		  while (EGSmsg = (struct EI_EIntuiMsg *)GetMsg(WMsgPortp)) {
			pic = (struct Picture *)(EGSmsg->IDCMPWindow->UserData);
		   switch (EGSmsg->Class) {
		   case EI_iNEWSIZE:
		    // On resize reset EGS pointer (to prevent staying as arrow)
		    SetMyPointer();
		    break;
		   case EI_iCLOSEWINDOW:
          flag = 2;
		    break;
		 	case EI_iVANILLAKEY:
		 		Vanilla(EGSmsg->Code);
				break;
			case EI_iMOUSEBUTTONS:
				MouseButtons(pic,EGSmsg->Code,EGSmsg->Seconds);
				break;
			case EI_iMOUSEMOVE:
				MouseMove(pic);
				break;
			case EI_iACTIVEWINDOW:
				/* Window became active
				 * Store time so that we can ignore the first click
				 * (for which we may next recieve a message)
				 * and change the screen palette (if required)
				 */
				pic->JustSeconds = EGSmsg->Seconds;
				break;
		   default:
		    break;
		   }
		   ReplyMsg((struct Message *)EGSmsg); 
		  }
		 }
		 else {
		  // Loop round messages
		  while (msg = (struct IntuiMessage *)GetMsg(WMsgPortp)) {
		 	// determine which image it relates to
			pic = (struct Picture *)(msg->IDCMPWindow->UserData);
			switch (msg->Class) {
			case IDCMP_GADGETHELP:
 				if (msg->IAddress == NULL) {
 					HNum = 0;
 				}
 				else {
 					if (msg->IAddress == pic->Win) {
						switch(Mode) {
						case EDIT1:
							HNum = H_EOne;
							break;
						case EDIT2:
							HNum = H_ETwo;
							break;
						case EDITREL:
							HNum = H_ERel;
						 	break;
						case ADD:
							HNum = H_EAdd;
							break;
						case DELETE:
							HNum = H_EDel;
							break;
						case LINK1:
						case LINK2:
						case LINK2A:
							HNum = H_ELnk;
							break;
						case UNLINK1:
						case UNLINK2:
						case UNLINK2A:
							HNum = H_EUnl;
							break;
						case NONE:
							HNum = H_EMov;
							break;
						default:
							HNum = H_EWindow;
							break;
						}
 					}
 					else {
 						switch (((struct Gadget *)msg->IAddress)->GadgetType &0xf0) {
 						case GTYP_SIZING:
 							HNum = H_ESize;
 							break;
 						case GTYP_WDRAGGING:
 							HNum = H_EWindow;
 							break;
 						case GTYP_WUPFRONT:
 							HNum = H_EDepth;
 							break;
 						case GTYP_WDOWNBACK:
 							HNum = H_EZoom;
 							break;
 						case GTYP_CLOSE:
 							HNum = H_EClose;
 							break;
 						case 0:
 							switch (((struct Gadget *)msg->IAddress)->GadgetID) {
 							case LEFT_RIGHT_GADGET:
 								HNum = H_Horiz;
 								break;
 							case UP_DOWN_GADGET:
 								HNum = H_Vert;
 								break;
 							case UP_GADGET:
 								HNum = H_Up;
 								break;
 							case DOWN_GADGET:
 								HNum = H_Down;
 								break;
 							case LEFT_GADGET:
 								HNum = H_Left;
 								break;
 							case RIGHT_GADGET:
 								HNum = H_Right;
 								break;
 							default:
 								HNum = H_EWindow;
 								break;
 							}
 							break;
 						default:
 							HNum = H_EWindow;
 							break;
 						}
 					}
 				}
 				if (HNum) {
 					if (GHelp) {
		 				help(HNum);
		 			}
		 			else {
		 				ihelp(HNum);
		 			}
	 			}
				break;
			case IDCMP_NEWSIZE:
				// Image resized so resize the gadgets etc.
				pic->JustSeconds = 0;	// Note No break !!!!!!!
			case IDCMP_CHANGEWINDOW:
				/* reset window size after change in Zoom
				 * Changing from 2x to normal size may require the windows
				 * to be made smaller - this can be delayed by intuition.
				 * The window limits can only be reset when the window has
				 * been actually resized.
				 */
				if (ZoomAllowed && !Zoom) {
					if (changedboxcount < 3) {
						if (WindowLimits(pic->Win,0,0,pic->ilbm->Bmhd.w+pic->Screen->WBorLeft+SIZEIMAGE_W(n),
										pic->ilbm->Bmhd.h+pic->Screen->WBorTop + pic->Screen->Font->ta_YSize+1+SIZEIMAGE_H(n))) {
							if (pic == &Pic1) {
								changedboxcount |= 1;
							}
							else {
								if (pic == &Pic2) {
									changedboxcount |= 2;
								}
							}
							if (changedboxcount == 3) {
								/* Once both windows have been resized then we
								 * can redraw all the points
								 */
								DrawAllPoints();
							}
						}
						else {
							/* User must have resized in the meantime
							 * so have another go
							 */
							ChangeWindowBox(pic->Win,pic->Win->LeftEdge,pic->Win->TopEdge,
										 min(pic->Win->Width,pic->ilbm->Bmhd.w+pic->Screen->WBorLeft+SIZEIMAGE_W(n)),
										 min(pic->Win->Height,pic->ilbm->Bmhd.h+pic->Screen->WBorTop + pic->Screen->Font->ta_YSize+1+SIZEIMAGE_H(n)));
						}
					}
				}
				// Reset gadgets etc. for new size
				doNewSize(pic);
				break;
		 	case IDCMP_VANILLAKEY:
		 		Vanilla(msg->Code);
				break;
	  		case IDCMP_RAWKEY:
	  			// Only raw key currently used is the help key
	  			switch (msg->Code) {
	 			case 0x5F:
	 				/* Determine the gadget the pointer is over
	 				 * or show help on the whole window
	 				 */
					X = msg->IDCMPWindow->MouseX;
					Y = msg->IDCMPWindow->MouseY;
					if (PointInBox(X,Y,0,0,
											CLOSEIMAGE_W(n),msg->IDCMPWindow->BorderTop))
						HNum = H_EClose;
					else
					if (PointInBox(X,Y,(msg->IDCMPWindow->Width - DEPTHIMAGE_W(n)),0,
											msg->IDCMPWindow->Width,msg->IDCMPWindow->BorderTop))
						HNum = H_EDepth;
					else
					if (PointInBox(X,Y,(msg->IDCMPWindow->Width - DEPTHIMAGE_W(n) - ZOOMIMAGE_W(n)),0,
											(msg->IDCMPWindow->Width - DEPTHIMAGE_W(n)),msg->IDCMPWindow->BorderTop))
						HNum = H_EZoom;
					else
					if (PointInBox(X,Y,(msg->IDCMPWindow->Width - SIZEIMAGE_W(n)),(msg->IDCMPWindow->Height-10),
											msg->IDCMPWindow->Width,msg->IDCMPWindow->Height))
						HNum = H_ESize;
					else
					if (PointInBox(X,Y,(msg->IDCMPWindow->Width-SIZEIMAGE_W(n)-LEFTIMAGE_W(n)-RIGHTIMAGE_W(n)),(msg->IDCMPWindow->Height-LEFTIMAGE_H(n)),
											(msg->IDCMPWindow->Width-SIZEIMAGE_W(n)-RIGHTIMAGE_W(n)),msg->IDCMPWindow->Height))
						HNum = H_Left;
					else
					if (PointInBox(X,Y,(msg->IDCMPWindow->Width-SIZEIMAGE_W(n)-RIGHTIMAGE_W(n)),(msg->IDCMPWindow->Height-RIGHTIMAGE_H(n)),
											(msg->IDCMPWindow->Width-SIZEIMAGE_W(n)),msg->IDCMPWindow->Height))
						HNum = H_Right;
					else
					if (PointInBox(X,Y,(msg->IDCMPWindow->Width-UPIMAGE_W(n)),(msg->IDCMPWindow->Height-SIZEIMAGE_H(n)-DOWNIMAGE_H(n)-UPIMAGE_H(n)),
											msg->IDCMPWindow->Width,(msg->IDCMPWindow->Height-SIZEIMAGE_H(n)-DOWNIMAGE_H(n))))
						HNum = H_Up;
					else
					if (PointInBox(X,Y,(msg->IDCMPWindow->Width-UPIMAGE_W(n)),(msg->IDCMPWindow->Height-SIZEIMAGE_H(n)-DOWNIMAGE_H(n)),
											msg->IDCMPWindow->Width,(msg->IDCMPWindow->Height-SIZEIMAGE_H(n))))
						HNum = H_Down;
					else
					if (PointInBox(X,Y,0,(msg->IDCMPWindow->Height-SIZEIMAGE_H(n)),
											(msg->IDCMPWindow->Width-SIZEIMAGE_W(n)-LEFTIMAGE_W(n)-RIGHTIMAGE_W(n)),msg->IDCMPWindow->Height))
						HNum = H_Horiz;
					else
					if (PointInBox(X,Y,(msg->IDCMPWindow->Width-SIZEIMAGE_W(n)),msg->IDCMPWindow->BorderTop,
											msg->IDCMPWindow->Width,(msg->IDCMPWindow->Height-SIZEIMAGE_H(n)-UPIMAGE_H(n)-DOWNIMAGE_H(n))))
						HNum = H_Vert;
					else
						HNum = H_EWindow;
					help(HNum);
	  				break;
	  			default:
	  				// some other key
	  				break;
	  			}
	  			break;
	  		case IDCMP_MENUHELP:
	  			// Display help on Control and Image window menus
	  			DoMenuHelp(msg->Code);
	  			break;
			case IDCMP_ACTIVEWINDOW:
				/* Window became active
				 * Store time so that we can ignore the first click
				 * (for which we may next recieve a message)
				 * and change the screen palette (if required)
				 */
				pic->JustSeconds = msg->Seconds;
				if (flag == 1) {
					ColorWindow(pic);
				}
				break;
			case IDCMP_INACTIVEWINDOW:
				/* Window just became inactive
				 * change the screen palette back if required
				 */
				UnColorWindow(pic);
				break;
			case IDCMP_MENUVERIFY:
				/* Somebody wants to display a menu
				 * If it is somebody else then just let them
				 * otherwise if the left mouse button is down then
				 * do not display the menu as we are going to use
				 * the right button up/down message to cancel the current action
				 * otherwise change the screen palette back if required
				 * so that our menus can be readably displayed
				 */
				switch (msg->Code) {
				case MENUWAITING:
					break;
				case MENUHOT:
					pic->JustSeconds = 0;
					if (SelDown) {
						msg->Code = MENUCANCEL;
					}
					else {
						UnColorWindow(pic);
					}
					break;
				default:
					break;
				}
				break;
	  		case IDCMP_MENUPICK:
	  			// Menu item selected, use any further clicks and loop round menu selections
				pic->JustSeconds = 0;
				Selection = msg->Code;
				while ((Selection != MENUNULL) && flag) {
					flag = DoMenu(pic,Selection);
					Selection = ((struct MenuItem *)ItemAddress(MyMenu,(LONG)Selection))->NextSelect;
		 		}
		 		/* If we are changing palettes and quit
		 		 * was not just selected then change
		 		 * palette back to the image palette
		 		 * after a menu selections
		 		 */
				if (palette && pic && (flag==1)) {
					ColorWindow(pic);
				}
				break;
	 		case IDCMP_CLOSEWINDOW:
	 			/* Close the window with Control and other image windows
	 			 * and change the palette back to original if required
	 			 */
	 			UnColorWindow(pic);
				flag = 2;
	  			break;
			case IDCMP_MOUSEBUTTONS:
				MouseButtons(pic,msg->Code,msg->Seconds);
				break;
			case IDCMP_MOUSEMOVE:
				MouseMove(pic);
				break;
			case IDCMP_GADGETDOWN:
				// Gadget down, save the current gadget id
				pic->JustSeconds = 0;
				pic->currentg = ((struct Gadget *)(msg->IAddress))->GadgetID;
				break;
			case IDCMP_GADGETUP:
				// Gadget up, no current gadget id
				pic->JustSeconds = 0;
				pic->currentg = NO_GADGET;
				break;
			case IDCMP_IDCMPUPDATE:
				// Gadget update message
				pic->JustSeconds = 0;
				/* If an arrow then check the mouse button
				 * is down (prevents image scrolling long
				 * after button is released)
				 */
				if ((pic->currentg == LEFT_RIGHT_GADGET) ||
					 (pic->currentg == UP_DOWN_GADGET) ||
					 (PeekQualifier() & IEQUALIFIER_LEFTBUTTON)) {
					pic->XLeft=pic->Left;
					pic->XTop=pic->Top;
					Shift = PeekQualifier() & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT);
					switch(pic->currentg) {
					case LEFT_RIGHT_GADGET:
						// Horizontal gadget - get position
						pic->Left = msg->Code;
						break;
					case UP_DOWN_GADGET:
						// Vertical gadget - get position
						pic->Top = msg->Code;
						break;
					case UP_GADGET:
						// Up gadget, check shift key
						if (pic->Top) {
							if (Shift)
								--(pic->Top);
							else
							if (pic->Top > pic->ATop)
									pic->Top -= pic->ATop;
								else
									pic->Top = 0;
							SetGadgetAttrs(pic->SideGad, pic->Win, NULL,
								PGA_Top, pic->Top, TAG_END);
						}
						break;
					case LEFT_GADGET:
						// Left gadget, check shift key
						if (pic->Left) {
							if (Shift)
								--(pic->Left);
							else
								if (pic->Left > pic->ALeft)
									pic->Left -= pic->ALeft;
								else
									pic->Left = 0;
							SetGadgetAttrs(pic->BotGad, pic->Win, NULL,
								PGA_Top, pic->Left, TAG_END);
						}
						break;
					case DOWN_GADGET:
						// Down gadget, check shift key
						if (Shift)
							++(pic->Top);
						else
							pic->Top += pic->ATop;
						if (pic->Top > pic->MTop)
							pic->Top = pic->MTop;
						SetGadgetAttrs(pic->SideGad, pic->Win, NULL,
							PGA_Top, pic->Top, TAG_END);
						break;
					case RIGHT_GADGET:
						// Right gadget, check shift key
						if (Shift)
							++(pic->Left);
						else
							pic->Left += pic->ALeft;
						if (pic->Left > pic->MLeft)
							pic->Left = pic->MLeft;
						SetGadgetAttrs(pic->BotGad, pic->Win, NULL,
							PGA_Top, pic->Left, TAG_END);
						break;
					}
					// Update image scroll
					checkGadget(pic); 
					break;
				}
			}
			ReplyMsg((struct Message *)msg);
		  }
		 }
		}
		/* If a window was closed etc.
		 * then turn on some menus and close the windows
		 * etc.
		 */
		if ((flag == 2) || (flag == 3)) {
			if ((flag == 2) &&
				 ((SinglePicture == 2) || (SinglePicture == 3))) {
				if (!Saved) {
					flag = SaveRequester();
				}
				DeleteAllPoints();
			}
			if (flag) {
				OnMenu(TSMorphWnd,FULLMENUNUM(0,0,NOSUB));
				OnMenu(TSMorphWnd,FULLMENUNUM(0,1,NOSUB));
				if (Pic1_Open) {
					CloseAPicture(&Pic1);
					Pic1_Open = FALSE;
				}
				if (Pic2_Open) {
					CloseAPicture(&Pic2);
					Pic2_Open = FALSE;
				}
				if (EGS) {
				 E_ActivateAmigaScreen();
				 ScreenToFront(Scr);
				}
				CloseControlWindow();
			}
			// Below just updates the correct gadgets
			EnableWindows();
 			flag = 1;
		}
	}
}

//struct E_EMouse EGS_Pointer = {0x00000001, 0xFF0000FF, 0x80000080,
//struct E_EMouse EGS_Pointer = {0x00000000, 0xFF000000, 0xFFFFFF00,
//											1,1,32,32,NULL,NULL };
//ULONG EGS_Soft[32][2] = {0};	// Should be E_SoftMouse but that is LONG!
// Fix for 3.1 EGS includes 2.2
struct E_EMouseImg32 EMouseImg = {32,32,1,1};
struct E_EMouse EGS_Pointer = {0x00000000, 0xFF000000, 0xFFFFFF00,
										 EMSF_HALF32,
										 EMSV_01,NULL,&EMouseImg,NULL};

/* SetPointer
 * based on the current mode
 */
void
SetMyPointer(void) {
	UWORD *Pointer;	// Pointer image
	int i,j;
	UWORD a,b;
	ULONG c,d;
	// Set pointer based on mode
	switch (Mode) {
	case EDIT1:
		Pointer = One;
 		break;
	case EDIT2:
		Pointer = Two;
		break;
	case EDITREL:
		Pointer = Rel;
		break;
	case ADD:
		Pointer = Add;
		break;
	case DELETE:
		Pointer = Del;
		break;
	case LINK1:
		Pointer = L1;
		break;
	case UNLINK1:
		Pointer = U1;
		break;
	case NONE:
		Pointer = Mov;
		break;
	case UNLINK2:
		Pointer = U2;
		break;
	case LINK2:
		Pointer = L2;
		break;
	}
	if (EGS) {
		// Convert intuition pointer to EGS pointer
		for (i = 0; i < 16; i++) {
			a = Pointer[(i<<1)+2];
			b = Pointer[(i<<1)+3];
			c = 0;
			for (j = 0; j < 8; j++) {
				if ((a & 0x8000) && (b & 0x8000)) {
					c |= 15;
				}
				else {
					if (b & 0x8000) {
						c |= 0x10;
					}
					else {
						if (a & 0x8000) {
							c |= 0x5;
						}
					}
				}
				a <<= 1;
				b <<= 1;
				if (j < 7) {
					c <<= 4;
				}
			}
			d = 0;
			for (j = 0; j < 8; j++) {
				if ((a & 0x8000) && (b & 0x8000)) {
					d |= 15;
				}
				else {
					if (b & 0x8000) {
						d |= 0x10;
					}
					else {
						if (a & 0x8000) {
							d |= 0x5;
						}
					}
				}
				a <<= 1;
				b <<= 1;
				if (j < 7) {
					d <<= 4;
				}
			}
//			EGS_Soft[i<<1][0] = c;
//			EGS_Soft[i<<1][1] = d;
//			EGS_Soft[(i<<1)+1][0] = c;
//			EGS_Soft[(i<<1)+1][1] = d;
			EMouseImg.image[i<<1][0] = c;
			EMouseImg.image[i<<1][1] = d;
			EMouseImg.image[(i<<1)+1][0] = c;
			EMouseImg.image[(i<<1)+1][1] = d;
		}
//		EGS_Pointer.Soft = &EGS_Soft;
	}
	// Set the window pointers
	if (Pic1_Open) {
		if (!EGS) {
			SetPointer(Pic1.Win, Pointer, 16, 16, -1, 0);
		}
		else {
			EI_ClearPointer(Pic1.EGS_Win);
			EI_SetPointer(Pic1.EGS_Win,&EGS_Pointer);
		}
	}
	if (Pic2_Open) {
		if (!EGS) {
			SetPointer(Pic2.Win, Pointer, 16, 16, -1, 0);
		}
		else {
			EI_ClearPointer(Pic2.EGS_Win);
			EI_SetPointer(Pic2.EGS_Win,&EGS_Pointer);
		}
	}
	if (ControlWindow) {
		SetPointer(ControlWindow, Pointer, 16, 16, -1, 0);
	}
}

/* Do the Control and image window menus
 * Returns	: 1 = OK, 0 = quit, 2=exit points
 * pic		: Picture structure if an image window
 * Selection: Menu item
 */
int
DoMenu(struct Picture *pic,UWORD Selection) {
	int flag = 1;			// Return value
	// Large switch statements for menu items
  	switch (MENUNUM(Selection)) {
  	case M_PROJECT:
		switch(ITEMNUM(Selection)) {
		case MM_NEW:
			/* New Points
			 * Suggest Save if not saved
			 * then delete all point
			 */
			DisableWindows(DI_New);
			if (!Saved) {
				if (SaveRequester()) {
					Saved = TRUE;
				}
			}
			if (Saved) {
				DeleteAllPoints();
				MaxWidth = 0;
				MaxHeight = 0;
				Saved = FALSE;
			}
			EnableWindows();
			break;
		case MM_OPEN:
			// Open Points - just call MyOpen() with JustPoints=TRUE
			DisableWindows(DI_WaitOpen);
			MyOpen(NULL,TRUE,TRUE);
			EnableWindows();
			break;
		case MM_SAVE:
			// Save - just call SaveAs() with last filename
			DisableWindows(DI_WaitSave);
			SaveAs(savedfilename);
			EnableWindows();
			break;
		case MM_SAVEAS:
			// Save - just call SaveAs() with no filename
			DisableWindows(DI_WaitSave);
			SaveAs(NULL);
			EnableWindows();
			break;
	  	case MM_ABOUT:
	  		// About - display requester
			DisableWindows(DI_About);
			About();
			EnableWindows();
			break;
		case MM_EXITPOINTS:
			// Exit Points - Close Image and control windows
			flag = 2;
			break;
		case MM_QUIT:
			// Quit - Suggest save first
			if (!Saved) {
		  		flag = !SaveRequester();
		  	}
		  	else {
		  		flag = 0;
		  	}
			break;
		case MM_PPREVIEW:
			Preview();
			break;
	 	default:
	 		// Some other item
	  		break;
		}
		break;
	case M_EDIT:
		switch(ITEMNUM(Selection)) {
		case MM_GRID:
			// Add Grid... - Add a grid of points
			AddGrid();
			break;
		case MM_TRIANGULATE:
			Triangulate();
			break;
		case MM_FRAME:
			// Frame sub menu
			switch (SUBNUM(Selection)) {
			case MI_FIRST:
				flag = FirstFrame();
				break;
			case MI_PREV:
				flag = PrevFrame();
				break;
			case MI_GOTO:
				flag = GotoFrame();
				break;
			case MI_NEXT:
				flag = NextFrame();
				break;
			case MI_LAST:
				flag = LastFrame();
				break;
			default:
				break;
			}
			break;
		case MM_MODE:
			switch (SUBNUM(Selection)) {
			// Edit Mode ???? - set the relevant mode
  			case MI_EDITONE:
  				MySetMode(EDIT1);
  				break;
 			case MI_EDITTWO:
  				MySetMode(EDIT2);
	  			break;
			case MI_EDITREL:
				MySetMode(EDITREL);
	  			break;
			case MI_ADD:
				MySetMode(ADD);
	  			break;
			case MI_DELETE:
				MySetMode(DELETE);
	  			break;
			case MI_LINK:
				MySetMode(LINK1);
	  			break;
			case MI_UNLINK:
				MySetMode(UNLINK1);
	  			break;
			case MI_NONE:
				MySetMode(NONE);
				break;
			default:
				break;
			}
			break;
		default:
			// Some other item
			break;
		}
		break;
	case M_SETTINGS:
		HandleSettings(Selection,pic);
		break;
	default:
		// something else ??
		break;
	}
	// return 0,1 or 2
	return flag;
}

/* Disable all windows,
 * menus, pointers,
 * gadgets etc.
 *
 * Note: This must be able to be called multiple times without EnableWindows()
 */
void
DisableWindows(ULONG dnum) {
	if (dnum < 1000) {
		ihelp(dnum);
	}
	else {
		if (*(disabled[dnum-1000])) {
			if (Scr) {		// Need to check as TSMorphWnd is also used for backdrop temp window
				if (TSMorphWnd) {
					GT_SetGadgetAttrs(TSMorphGadgets[GDX_Help],TSMorphWnd,NULL,
										GTTX_Text,disabled[dnum-1000], TAG_END );
				}
			}
		}
	}
	if (ControlWindow) {
		// All 3 menus off
		OffMenu(ControlWindow,FULLMENUNUM(M_PROJECT,NOITEM,NOSUB));
		OffMenu(ControlWindow,FULLMENUNUM(M_EDIT,NOITEM,NOSUB));
		OffMenu(ControlWindow,FULLMENUNUM(M_SETTINGS,NOITEM,NOSUB));
		// All gadgets off
		OffGadget(&OneGadget,ControlWindow,NULL);
		OffGadget(&TwoGadget,ControlWindow,NULL);
		OffGadget(&RelGadget,ControlWindow,NULL);
		OffGadget(&MyAddGadget,ControlWindow,NULL);
		OffGadget(&DelGadget,ControlWindow,NULL);
		OffGadget(&LinkGadget,ControlWindow,NULL);
		OffGadget(&UnlinkGadget,ControlWindow,NULL);
		OffGadget(&NoneGadget,ControlWindow,NULL);
		OffGadget(&stGadget,ControlWindow,NULL);
		OffGadget(&prevGadget,ControlWindow,NULL);
		OffGadget(&gotoGadget,ControlWindow,NULL);
		OffGadget(&nextGadget,ControlWindow,NULL);
		OffGadget(&lastGadget,ControlWindow,NULL);
		// Wait pointer
		SetPointer(ControlWindow, BusyPointerData, 16, 16, -6, 0);
	}
	if (Pic1_Open) {
	 if (!EGS) {
		// Turn verify off
		IDCMPFlags = IDCMP_IDCMPUPDATE | IDCMP_GADGETUP | IDCMP_GADGETDOWN |
						 IDCMP_NEWSIZE | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE |
						 IDCMP_MENUPICK | IDCMP_CLOSEWINDOW | IDCMP_MENUHELP | IDCMP_RAWKEY | IDCMP_VANILLAKEY |
						 IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_CHANGEWINDOW |
						 IDCMP_GADGETHELP | IDCMP_MOUSEMOVE;
		ModifyIDCMP(Pic1.Win,IDCMPFlags);
		Pic1.Win->Flags |= WFLG_REPORTMOUSE;
		// All 3 menus off
//		OffMenu(Pic1.Win,FULLMENUNUM(0,NOITEM,NOSUB));	// These are now shared menus
//		OffMenu(Pic1.Win,FULLMENUNUM(1,NOITEM,NOSUB));
//		OffMenu(Pic1.Win,FULLMENUNUM(2,NOITEM,NOSUB));
		// Wait pointer
		SetPointer(Pic1.Win, BusyPointerData, 16, 16, -6, 0);
		// all gadgets off
		SetGadgetAttrs(Pic1.Lgad,Pic1.Win,0,GA_Disabled,TRUE,TAG_END);
		SetGadgetAttrs(Pic1.Ugad,Pic1.Win,0,GA_Disabled,TRUE,TAG_END);
		SetGadgetAttrs(Pic1.Dgad,Pic1.Win,0,GA_Disabled,TRUE,TAG_END);
		SetGadgetAttrs(Pic1.Rgad,Pic1.Win,0,GA_Disabled,TRUE,TAG_END);
		SetGadgetAttrs(Pic1.SideGad,Pic1.Win,0,GA_Disabled,TRUE,TAG_END);
		SetGadgetAttrs(Pic1.BotGad,Pic1.Win,0,GA_Disabled,TRUE,TAG_END);
		RefreshGadgets(Pic1.BotGad,Pic1.Win,NULL);
	 }
	 else {
	  EI_ClearPointer(Pic1.EGS_Win);
	  EI_SetPointer(Pic1.EGS_Win,EI_GetPrefPointer(EIM_SLEEP_MOUSE));
	 }
	}
	if (Pic2_Open) {
	 if (!EGS) {
		// Turn verify off
		IDCMPFlags = IDCMP_IDCMPUPDATE | IDCMP_GADGETUP | IDCMP_GADGETDOWN |
						 IDCMP_NEWSIZE | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE |
						 IDCMP_MENUPICK | IDCMP_CLOSEWINDOW | IDCMP_MENUHELP | IDCMP_RAWKEY | IDCMP_VANILLAKEY |
						 IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_CHANGEWINDOW |
						 IDCMP_GADGETHELP | IDCMP_MOUSEMOVE;
		ModifyIDCMP(Pic2.Win,IDCMPFlags);
		Pic2.Win->Flags |= WFLG_REPORTMOUSE;
		// All 3 menus off
//		OffMenu(Pic2.Win,FULLMENUNUM(0,NOITEM,NOSUB));	// These are now shared menus
//		OffMenu(Pic2.Win,FULLMENUNUM(1,NOITEM,NOSUB));
//		OffMenu(Pic2.Win,FULLMENUNUM(2,NOITEM,NOSUB));
		// Wait pointer
		SetPointer(Pic2.Win, BusyPointerData, 16, 16, -6, 0);
		// all gadgets off
		SetGadgetAttrs(Pic2.Lgad,Pic2.Win,0,GA_Disabled,TRUE,TAG_END);
		SetGadgetAttrs(Pic2.Ugad,Pic2.Win,0,GA_Disabled,TRUE,TAG_END);
		SetGadgetAttrs(Pic2.Dgad,Pic2.Win,0,GA_Disabled,TRUE,TAG_END);
		SetGadgetAttrs(Pic2.Rgad,Pic2.Win,0,GA_Disabled,TRUE,TAG_END);
		SetGadgetAttrs(Pic2.SideGad,Pic2.Win,0,GA_Disabled,TRUE,TAG_END);
		SetGadgetAttrs(Pic2.BotGad,Pic2.Win,0,GA_Disabled,TRUE,TAG_END);
		RefreshGadgets(Pic2.BotGad,Pic2.Win,NULL);
	 }
	 else {
	  EI_ClearPointer(Pic2.EGS_Win);
	  EI_SetPointer(Pic2.EGS_Win,EI_GetPrefPointer(EIM_SLEEP_MOUSE));
	 }
	}
	/* Disable gadgets in the Info window
	 * Do not disable the GetFile gadgets
	 * as it causes enforcer hits
	 */
	if (Scr) {
		if (TSMorphWnd) {
		//	GT_SetGadgetAttrs(TSMorphGadgets[GDX_GetFile1],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);	// GetFile gadgets do not like being disabled
		//	GT_SetGadgetAttrs(TSMorphGadgets[GDX_GetFile2],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
		//	GT_SetGadgetAttrs(TSMorphGadgets[GDX_GetFileOne],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
		//	GT_SetGadgetAttrs(TSMorphGadgets[GDX_GetFileTwo],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_EditPoints],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_SinglePicture],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
		//	GT_SetGadgetAttrs(TSMorphGadgets[GDX_GetSaveName],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_FileOne],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_FileTwo],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_File241],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_File242],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_Frames],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_Name],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_Start],TSMorphWnd,NULL,GA_Disabled,TRUE,TAG_END);
			// Both menus off
			OffMenu(TSMorphWnd,FULLMENUNUM(0,NOITEM,NOSUB));
			OffMenu(TSMorphWnd,FULLMENUNUM(1,NOITEM,NOSUB));
			// Wait pointer
			SetPointer(TSMorphWnd, BusyPointerData, 16, 16, -6, 0);
		}
	}
}

/* Enable all windows,
 * menus, pointers,
 * gadgets etc.
 */
void
EnableWindows(void) {
	LONG Frames,Start;
	if (Scr) {
		if (TSMorphWnd) {
			Frames = GetNumber(TSMorphGadgets[GDX_Frames]);
			Start = GetNumber(TSMorphGadgets[GDX_Start]);
		}
	}
	if (ControlWindow) {
		// Menus and gadgets on
		OnMenu(ControlWindow,FULLMENUNUM(M_PROJECT,NOITEM,NOSUB));
		OnMenu(ControlWindow,FULLMENUNUM(M_EDIT,NOITEM,NOSUB));
		OnMenu(ControlWindow,FULLMENUNUM(M_SETTINGS,NOITEM,NOSUB));
		OnGadget(&OneGadget,ControlWindow,NULL);
		OnGadget(&TwoGadget,ControlWindow,NULL);
		OnGadget(&RelGadget,ControlWindow,NULL);
		OnGadget(&MyAddGadget,ControlWindow,NULL);
		OnGadget(&DelGadget,ControlWindow,NULL);
		OnGadget(&LinkGadget,ControlWindow,NULL);
		OnGadget(&UnlinkGadget,ControlWindow,NULL);
		OnGadget(&NoneGadget,ControlWindow,NULL);
		if ((SinglePicture == 2) || (SinglePicture == 3)) {
			if (FrameNumber > Start) {
				OnGadget(&stGadget,ControlWindow,NULL);
				OnGadget(&prevGadget,ControlWindow,NULL);
				OnMenu(ControlWindow,FULLMENUNUM(M_EDIT,MM_FRAME,MI_FIRST));
				OnMenu(ControlWindow,FULLMENUNUM(M_EDIT,MM_FRAME,MI_PREV));
			}
			else {
				OffMenu(ControlWindow,FULLMENUNUM(M_EDIT,MM_FRAME,MI_FIRST));
				OffMenu(ControlWindow,FULLMENUNUM(M_EDIT,MM_FRAME,MI_PREV));
			}
			if (FrameNumber < (Start+Frames-1)) {
				OnGadget(&nextGadget,ControlWindow,NULL);
				OnGadget(&lastGadget,ControlWindow,NULL);
				OnMenu(ControlWindow,FULLMENUNUM(M_EDIT,MM_FRAME,MI_NEXT));
				OnMenu(ControlWindow,FULLMENUNUM(M_EDIT,MM_FRAME,MI_LAST));
			}
			else {
				OffMenu(ControlWindow,FULLMENUNUM(M_EDIT,MM_FRAME,MI_NEXT));
				OffMenu(ControlWindow,FULLMENUNUM(M_EDIT,MM_FRAME,MI_LAST));
			}
			if (Frames > 1) {
				OnMenu(ControlWindow,FULLMENUNUM(M_EDIT,MM_FRAME,MI_GOTO));
				OnGadget(&gotoGadget,ControlWindow,NULL);
			}
			else {
				OffMenu(ControlWindow,FULLMENUNUM(M_EDIT,MM_FRAME,MI_GOTO));
			}
		}
		else {
			OffMenu(ControlWindow,FULLMENUNUM(M_EDIT,MM_FRAME,NOSUB));
		}
	}
	if (Pic1_Open) {
	 if (!EGS) {
		// verify, menus and gadgets on
		IDCMPFlags = IDCMP_IDCMPUPDATE | IDCMP_GADGETUP | IDCMP_GADGETDOWN |
						 IDCMP_NEWSIZE | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE |
						 IDCMP_MENUPICK | IDCMP_CLOSEWINDOW | IDCMP_MENUVERIFY |
						 IDCMP_MENUHELP | IDCMP_RAWKEY | IDCMP_VANILLAKEY |
						 IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_CHANGEWINDOW |
						 IDCMP_GADGETHELP;
		ModifyIDCMP(Pic1.Win,IDCMPFlags);
		Pic1.Win->Flags |= WFLG_REPORTMOUSE;
//		OnMenu(Pic1.Win,FULLMENUNUM(0,NOITEM,NOSUB));	// These are now shared menus
//		OnMenu(Pic1.Win,FULLMENUNUM(1,NOITEM,NOSUB));
//		OnMenu(Pic1.Win,FULLMENUNUM(2,NOITEM,NOSUB));
		SetGadgetAttrs(Pic1.Lgad,Pic1.Win,0,GA_Disabled,FALSE,TAG_END);
		SetGadgetAttrs(Pic1.Ugad,Pic1.Win,0,GA_Disabled,FALSE,TAG_END);
		SetGadgetAttrs(Pic1.Dgad,Pic1.Win,0,GA_Disabled,FALSE,TAG_END);
		SetGadgetAttrs(Pic1.Rgad,Pic1.Win,0,GA_Disabled,FALSE,TAG_END);
		SetGadgetAttrs(Pic1.SideGad,Pic1.Win,0,GA_Disabled,FALSE,TAG_END);
		SetGadgetAttrs(Pic1.BotGad,Pic1.Win,0,GA_Disabled,FALSE,TAG_END);
		RefreshGadgets(Pic1.BotGad,Pic1.Win,NULL);
	 }
	 else {
	  EI_ClearPointer(Pic1.EGS_Win);
	 }
	}
	if (Pic2_Open) {
	 if (!EGS) {
		// verify, menus and gadgets on
		IDCMPFlags = IDCMP_IDCMPUPDATE | IDCMP_GADGETUP | IDCMP_GADGETDOWN |
						 IDCMP_NEWSIZE | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE |
						 IDCMP_MENUPICK | IDCMP_CLOSEWINDOW | IDCMP_MENUVERIFY |
						 IDCMP_MENUHELP | IDCMP_RAWKEY | IDCMP_VANILLAKEY |
						 IDCMP_ACTIVEWINDOW | IDCMP_INACTIVEWINDOW | IDCMP_CHANGEWINDOW |
						 IDCMP_GADGETHELP;
		ModifyIDCMP(Pic2.Win,IDCMPFlags);
		Pic2.Win->Flags |= WFLG_REPORTMOUSE;
//		OnMenu(Pic2.Win,FULLMENUNUM(0,NOITEM,NOSUB));	// These are now shared menus
//		OnMenu(Pic2.Win,FULLMENUNUM(1,NOITEM,NOSUB));
//		OnMenu(Pic2.Win,FULLMENUNUM(2,NOITEM,NOSUB));
		SetGadgetAttrs(Pic2.Lgad,Pic2.Win,0,GA_Disabled,FALSE,TAG_END);
		SetGadgetAttrs(Pic2.Ugad,Pic2.Win,0,GA_Disabled,FALSE,TAG_END);
		SetGadgetAttrs(Pic2.Dgad,Pic2.Win,0,GA_Disabled,FALSE,TAG_END);
		SetGadgetAttrs(Pic2.Rgad,Pic2.Win,0,GA_Disabled,FALSE,TAG_END);
		SetGadgetAttrs(Pic2.SideGad,Pic2.Win,0,GA_Disabled,FALSE,TAG_END);
		SetGadgetAttrs(Pic2.BotGad,Pic2.Win,0,GA_Disabled,FALSE,TAG_END);
		RefreshGadgets(Pic2.BotGad,Pic2.Win,NULL);
	 }
	 else {
	  EI_ClearPointer(Pic2.EGS_Win);
	 }
	}
	if (Scr) {
		if (TSMorphWnd) {
			// Set pointer for Control and both image windows
			SetMyPointer();
			/* Turn relevant gadgets back on
			 * Do not enable GetFile gadgets as it causes enforcer hits
			 */
			if (!ControlWindow) {
		//		GT_SetGadgetAttrs(TSMorphGadgets[GDX_GetFileOne],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);	// GetFile gadgets do not like being disabled
		//		GT_SetGadgetAttrs(TSMorphGadgets[GDX_GetFileTwo],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
				GT_SetGadgetAttrs(TSMorphGadgets[GDX_FileOne],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
				GT_SetGadgetAttrs(TSMorphGadgets[GDX_FileTwo],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
				GT_SetGadgetAttrs(TSMorphGadgets[GDX_SinglePicture],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
				GT_SetGadgetAttrs(TSMorphGadgets[GDX_Frames],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
				GT_SetGadgetAttrs(TSMorphGadgets[GDX_Start],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
			}
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_EditPoints],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
		//	GT_SetGadgetAttrs(TSMorphGadgets[GDX_GetFile1],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
		//	GT_SetGadgetAttrs(TSMorphGadgets[GDX_GetFile2],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
		//	GT_SetGadgetAttrs(TSMorphGadgets[GDX_GetSaveName],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_File241],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_File242],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_Name],TSMorphWnd,NULL,GA_Disabled,FALSE,TAG_END);
			// Menus back on
			OnMenu(TSMorphWnd,FULLMENUNUM(0,NOITEM,NOSUB));
			OnMenu(TSMorphWnd,FULLMENUNUM(1,NOITEM,NOSUB));
			// Pointer back on
			ClearPointer(TSMorphWnd);
		}
		if (TSMorphWnd) {
			GT_SetGadgetAttrs(TSMorphGadgets[GDX_Help],TSMorphWnd,NULL,
								GTTX_Text,MyGetMsg(MSG_READY), TAG_END );
		}
	}
}

void
Vanilla(ULONG code) {
	switch (code) {
	// Edit Mode ???? - set the relevant mode
	case '1':
		MySetMode(EDIT1);
		break;
	case '2':
		MySetMode(EDIT2);
		break;
	case '3':
		MySetMode(EDITREL);
		break;
	case '4':
		MySetMode(ADD);
		break;
	case '5':
		MySetMode(DELETE);
		break;
	case '6':
		MySetMode(LINK1);
		break;
	case '7':
		MySetMode(UNLINK1);
		break;
	case '8':
		MySetMode(NONE);
		break;
	default:
		break;
	}
}

void
MouseButtons(struct Picture *pic,ULONG code,ULONG seconds) {
				int k;
				/* Somebody pressed a button
				 * If the second is the same as the activate window
				 * message then ignore this click
				 */
				if (EGS && pic->JustSeconds && (pic->JustSeconds == seconds)) {
					pic->JustSeconds = 0;
				}
				else {
					/* otherwise process the mouse click/release */
					pic->JustSeconds = 0;
					switch (code) {
					case SELECTDOWN:
						/* Left button pressed
						 * remember the currentimage positions
						 * in case Cancelled
						 */
						SelDown = TRUE;
						if (!EGS) {
							OldLeft = pic->Left;
							OldTop = pic->Top;
							if (pic == &Pic1) {
								OldLeft1 = Pic2.Left;
								OldTop1 = Pic2.Top;
							}
							else {
								OldLeft1 = Pic1.Left;
								OldTop1 = Pic1.Top;
							}
						}
						if (Pic1_Open && Pic2_Open) {
							// both windows open so action current mode
							switch(Mode) {
							case EDIT1:
								/* moving points in one window
								 * Find point near click
								 * erase and draw in new position
								 */
								if (MyPoint = FindPoint(pic,EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom) >> Zoom,EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom) >> Zoom)) {
									if (pic == &Pic2) {
										DrawPixels(pic,MyPoint->x1,MyPoint->y1,MyPoint);
									}
									else {
										DrawPixels(pic,MyPoint->x,MyPoint->y,MyPoint);
									}
									CurX=EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom + pic->Left)>>Zoom;
									CurY=EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom + pic->Top)>>Zoom;
									LimitPoints(&CurX,&CurY,pic);
									DrawPixels(pic,CurX,CurY,MyPoint);
								}
								else {
									SelDown = FALSE;
								}
								break;
							case EDIT2:
								/* moving points in both windows
								 * Find point near click
								 * erase and draw in new positions
								 */
								if (MyPoint = FindPoint(pic,EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom) >> Zoom,EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom) >> Zoom)) {
									DrawPixels(&Pic1,MyPoint->x,MyPoint->y,MyPoint);
									DrawPixels(&Pic2,MyPoint->x1,MyPoint->y1,MyPoint);
									CurX=EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom + pic->Left)>>Zoom;
									CurY=EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom + pic->Top)>>Zoom;
									LimitPoints(&CurX,&CurY,pic);
									DrawPixels(pic,CurX,CurY,MyPoint);
									if (pic == &Pic1) {
										DrawPixels(&Pic2,CurX,CurY,MyPoint);
									}
									else {
										DrawPixels(&Pic1,CurX,CurY,MyPoint);
									}	
								}
								else {
									SelDown = FALSE;
								}
								break;
							case EDITREL:
								/* moving points relatively in both windows
								 * Find point near click
								 * erase and draw in new positions
								 */
								if (MyPoint = FindPoint(pic,EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom) >> Zoom,EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom) >> Zoom)) {
									DrawPixels(&Pic1,MyPoint->x,MyPoint->y,MyPoint);
									DrawPixels(&Pic2,MyPoint->x1,MyPoint->y1,MyPoint);
									CurX=EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom + pic->Left)>>Zoom;
									CurY=EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom + pic->Top)>>Zoom;
									LimitPoints(&CurX,&CurY,pic);
									if (pic == &Pic1) {
										CurX1 = CurX - MyPoint->x + MyPoint->x1;
										CurY1 = CurY - MyPoint->y + MyPoint->y1;
									}
									else {
										CurX1 = CurX - MyPoint->x1 + MyPoint->x;
										CurY1 = CurY - MyPoint->y1 + MyPoint->y;
									}
									LimitPoints(&CurX1,&CurY1,pic);
									DrawPixels(pic,CurX,CurY,MyPoint);
									if (pic == &Pic1) {
										DrawPixels(&Pic2,CurX1,CurY1,MyPoint);
									}
									else {
										DrawPixels(&Pic1,CurX1,CurY1,MyPoint);
									}	
								}
								else {
									SelDown = FALSE;
								}
								break;
							case ADD:
								/* Adding point to both windows
								 * Draw in both windows
								 */
								CurX=EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom + pic->Left)>>Zoom;
								CurY=EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom + pic->Top)>>Zoom;
								LimitPoints(&CurX,&CurY,pic);
								DrawPixels(pic,CurX,CurY,NULL);
								if (pic == &Pic1) {
									DrawPixels(&Pic2,CurX,CurY,NULL);
								}
								else {
									DrawPixels(&Pic1,CurX,CurY,NULL);
								}	
								break;
							case DELETE:
								/* Deleting point from both windows
								 * Erase in both windows - if found
								 */
								if (MyPoint = FindPoint(pic,EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom) >> Zoom,EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom) >> Zoom)) {
									DrawPixels(&Pic1,MyPoint->x,MyPoint->y,MyPoint);
									DrawPixels(&Pic2,MyPoint->x1,MyPoint->y1,MyPoint);
								}
								else {
									SelDown = FALSE;
								}
								break;
							case LINK1:
								/* Linking two points
								 * Selecting first point
								 * If we can find it then check its not already linked to
								 * 4 points then set up the new mode - finding 2nd point
								 */
								if (MyPoint = FindPoint(pic,EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom) >> Zoom,EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom) >> Zoom)) {
									if (MyPoint->NumLinks == MAX_LINKS) {
	  									SelDown = FALSE;
										XError(pic,MyGetMsg(MSG_4POINTS),MyGetMsg(MSG_OK),NULL,HE_4points);
									}
									else {
	  									SetWindowTitles(ControlWindow,MyGetMsg(MSG_L2),(UBYTE *)-1);
										Mode = LINK2;
										MyPoint1 = MyPoint;
										SetMyPointer();
									}
								}
								else {
									SelDown = FALSE;
								}
								break;
							case UNLINK1:
								/* Unlinking two points
								 * Selecting first point
								 * If we can find it then check its already linked
								 * then set up the new mode - finding 2nd point
								 */
								if (MyPoint = FindPoint(pic,EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom) >> Zoom,EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom) >> Zoom)) {
									if (MyPoint->NumLinks) {
	  									SetWindowTitles(ControlWindow,MyGetMsg(MSG_U2),(UBYTE *)-1);
										Mode = UNLINK2;
										MyPoint1 = MyPoint;
										SetMyPointer();
									}
									else {
										SelDown = FALSE;
										XError(pic,MyGetMsg(MSG_NOTLINK),MyGetMsg(MSG_OK),NULL,HE_NotLinked);
									}
								}
								else {
									SelDown = FALSE;
								}
								break;
							case LINK2:
								/* Linking two points
								 * Selecting 2nd point
								 * If we can find it then do some validation
								 * then set up the new mode
								 */
								if (MyPoint = FindPoint(pic,EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom) >> Zoom,EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom) >> Zoom)) {
									if (MyPoint == MyPoint1) {
	  									SelDown = FALSE;
										XError(pic,MyGetMsg(MSG_LINKSE),MyGetMsg(MSG_OK),NULL,HE_LinkSelf);
									}
									else {
										if (MyPoint1->NumLinks == MAX_LINKS) {
		  									SelDown = FALSE;
											XError(pic,MyGetMsg(MSG_4POINTS),MyGetMsg(MSG_OK),NULL,HE_4points);
										}
										else {
											for (k = 0;
												  k < MAX_LINKS;
												  k++) {
												if (MyPoint->p[k] == MyPoint1) {
			  										SelDown = FALSE;
													XError(pic,MyGetMsg(MSG_READYLI),MyGetMsg(MSG_OK),NULL,HE_Linked);
												}
											}
											if (SelDown) {
												LinkPoints(MyPoint,MyPoint1);
												Mode = LINK2A;
											}
										}
									}
								}
								break;
							case UNLINK2:
								/* Unlinking two points
								 * Selecting 2nd point
								 * If we can find it then do some validation
								 * then set up the new mode
								 */
								if (MyPoint = FindPoint(pic,EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom) >> Zoom,EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom) >> Zoom)) {
									if (MyPoint == MyPoint1) {
										SelDown = FALSE;
										XError(pic,MyGetMsg(MSG_UNLSE),MyGetMsg(MSG_OK),NULL,HE_UnlinkSelf);
									}
									else {
										for (k = 0;
											  k < MAX_LINKS;
											  k++) {
											if (MyPoint->p[k] == MyPoint1) {
												SelDown = FALSE;
											}
										}
										if (!SelDown) {
											SelDown = TRUE;
											UnlinkPoints(MyPoint,MyPoint1,TRUE);
											Mode = UNLINK2A;
										}
										else {
											XError(pic,MyGetMsg(MSG_NOTLINK),MyGetMsg(MSG_OK),NULL,HE_NotLinked);
											SelDown = FALSE;
										}
									}
								}
								break;
							default:
								// Some other mode?
								break;
							}
							/* If we are adding a point, or moving a point
							 * then we may need to scroll the other window
							 * to get the point in view
							 * So update the gadgets and check the values set up
							 */
							if ((Mode == ADD) || 
								 ((MyPoint) && ((Mode == EDIT2) || (Mode == EDITREL)))) {
								if (pic == &Pic1) {
									pic1 = &Pic2;
								}
								else {
									pic1 = &Pic1;
								}
								if (Mode != EDITREL) {
									// if not edit rel then both points are in the same position
									CurX1 = CurX;
									CurY1 = CurY;
								}
								pic1->XLeft=pic1->Left;
								pic1->XTop=pic1->Top;
								if (!EGS) {
									if ((CurY1<<Zoom) < pic1->Top) {
										pic1->Top = CurY1<<Zoom;
										SetGadgetAttrs(pic1->SideGad, pic1->Win, NULL,
											PGA_Top, pic1->Top, TAG_END);
									}
									if ((CurX1<<Zoom) < pic1->Left) {
										pic1->Left = CurX1<<Zoom;
										SetGadgetAttrs(pic1->BotGad, pic1->Win, NULL,
										PGA_Top, pic1->Left, TAG_END);
									}
									if ((CurY1<<Zoom) > (pic1->Win->GZZHeight+pic1->Top)) {
										pic1->Top = ((CurY1<<Zoom) - pic1->Win->GZZHeight);
										SetGadgetAttrs(pic1->SideGad, pic1->Win, NULL,
											PGA_Top, pic1->Top, TAG_END);
									}
									if ((CurX1<<Zoom) > (pic1->Win->GZZWidth+pic1->Left)) {
										pic1->Left = ((CurX1<<Zoom) - pic1->Win->GZZWidth);
										SetGadgetAttrs(pic1->BotGad, pic1->Win, NULL,
											PGA_Top, pic1->Left, TAG_END);
									}
									checkGadget(pic1);
								}
							}
						}
						break;
					case SELECTUP:
						/* Left mouse button up
						 * If we are currently doing something then
						 * this actually confirms we really want
						 * to do it, Saved is set to FALSE following any change
						 */
						if (SelDown) {
							SelDown = FALSE;
							switch(Mode) {
							case ADD:
								// Adding a point, Create and add to list
								if (MyPoint = AllocMem(sizeof(struct MyPoint),MEMF_CLEAR)) {
									MyPoint->x = CurX;
									MyPoint->y = CurY;
									MyPoint->x1 = CurX;
									MyPoint->y1 = CurY;
									MaxWidth = max(CurX,MaxWidth);
									MaxHeight = max(CurY,MaxHeight);
									AddTail(&PointList,(struct Node *)MyPoint);
									Saved = FALSE;
								}
								else {
									XError(pic,MyGetMsg(MSG_MEMPO),MyGetMsg(MSG_OK),NULL,HE_MemNewPoint);
								}
								break;
							case EDIT1:
								// Editing one window, update actual point
								if (pic == &Pic2) {
									MyPoint->x1 = CurX;
									MyPoint->y1 = CurY;
								}
								else {
									MyPoint->x = CurX;
									MyPoint->y = CurY;
								}
								Saved = FALSE;
								break;
							case EDIT2:
								// Editing two windows, update actual point
								MyPoint->x = CurX;
								MyPoint->y = CurY;
								MyPoint->x1 = CurX;
								MyPoint->y1 = CurY;
								Saved = FALSE;
								break;
							case EDITREL:
								// Editing relative, update actual point
								if (pic == &Pic1) {
									CurX1 = CurX - MyPoint->x + MyPoint->x1;
									CurY1 = CurY - MyPoint->y + MyPoint->y1;
									MyPoint->x = CurX;
									MyPoint->y = CurY;
								}
								else {
									CurX1 = CurX - MyPoint->x1 + MyPoint->x;
									CurY1 = CurY - MyPoint->y1 + MyPoint->y;
									MyPoint->x1 = CurX;
									MyPoint->y1 = CurY;
								}
								Saved = FALSE;
								LimitPoints(&CurX1,&CurY1,((pic == &Pic1)?&Pic2:&Pic1));
								if (pic == &Pic1) {
									MyPoint->x1 = CurX1;
									MyPoint->y1 = CurY1;
								}
								else {
									MyPoint->x = CurX1;
									MyPoint->y = CurY1;
								}
								break;
							case DELETE:
								// Deleting, delete actual point
								if (MyPoint) {
									DeletePoint(MyPoint);
								}
								Saved = FALSE;
								break;
							case LINK2A:
								// Linking, reset window title and pointer
	  							SetWindowTitles(ControlWindow,MyGetMsg(MSG_L1),(UBYTE *)-1);
								Mode = LINK1;
								Saved = FALSE;
								SetMyPointer();
								break;
							case UNLINK2A:
								// Unlinking, reset window title and pointer
		  						SetWindowTitles(ControlWindow,MyGetMsg(MSG_U1),(UBYTE *)-1);
								Mode = UNLINK1;
								Saved = FALSE;
								SetMyPointer();
								break;
							default:
								break;
							}
						}
						break;
					case MENUDOWN:
					case MENUUP:
						/* Menu button pressed
						 * Cancel any current action
						 */
						if (SelDown) {
							SelDown = FALSE;
							switch (Mode) {
							case ADD:
								/* Adding,
								 * erase points
								 */
								DrawPixels(&Pic1,CurX,CurY,NULL);
								DrawPixels(&Pic2,CurX,CurY,NULL);
								break;
							case EDIT1:
								/* Editing in one window,
								 * erase current postion and redraw in original
								 */
								DrawPixels(pic,CurX,CurY,MyPoint);
								if (pic == &Pic2) {
									DrawPixels(pic,MyPoint->x1,MyPoint->y1,MyPoint);
								}
								else {
									DrawPixels(pic,MyPoint->x,MyPoint->y,MyPoint);
								}
								break;
							case EDIT2:
								/* Editing in both windows,
								 * erase current postion and redraw in original
								 */
								DrawPixels(&Pic1,CurX,CurY,MyPoint);
								DrawPixels(&Pic1,MyPoint->x,MyPoint->y,MyPoint);
								DrawPixels(&Pic2,CurX,CurY,MyPoint);
								DrawPixels(&Pic2,MyPoint->x1,MyPoint->y1,MyPoint);
								break;
							case EDITREL:
								/* Editing relatively in both windows,
								 * erase current postions and redraw in original
								 */
								if (pic == &Pic1) {
									DrawPixels(&Pic1,CurX,CurY,MyPoint);
									DrawPixels(&Pic1,MyPoint->x,MyPoint->y,MyPoint);
									DrawPixels(&Pic2,CurX1,CurY1,MyPoint);
									DrawPixels(&Pic2,MyPoint->x1,MyPoint->y1,MyPoint);
								}
								else {
									DrawPixels(&Pic2,CurX,CurY,MyPoint);
									DrawPixels(&Pic2,MyPoint->x1,MyPoint->y1,MyPoint);
									DrawPixels(&Pic1,CurX1,CurY1,MyPoint);
									DrawPixels(&Pic1,MyPoint->x,MyPoint->y,MyPoint);
								}
								break;
							case DELETE:
								/* Deleting points
								 * Redraw in original position
								 */
								DrawPixels(&Pic1,MyPoint->x,MyPoint->y,MyPoint);
								DrawPixels(&Pic2,MyPoint->x1,MyPoint->y1,MyPoint);
								break;
							case LINK2A:
								/* Linking points
								 * Re-Unlink
								 */
								UnlinkPoints(MyPoint,MyPoint1,TRUE);	// no break
							case LINK2:
								/* and reset title and pointer */
	  							SetWindowTitles(ControlWindow,MyGetMsg(MSG_L1),(UBYTE *)-1);
								Mode = LINK1;
								SetMyPointer();
								break;
							case UNLINK2A:
								/* Unlinking points
								 * re-link
								 */
								LinkPoints(MyPoint,MyPoint1);				// no break
							case UNLINK2:
								/* and reset title and pointer */
		  						SetWindowTitles(ControlWindow,MyGetMsg(MSG_U1),(UBYTE *)-1);
								Mode = UNLINK1;
								SetMyPointer();
								break;
							default:
								// some other mode?
								break;
							}
							if (!EGS) {
								/* Scroll the images back to
								 * their original position
								 */
								pic->XLeft=pic->Left;
								pic->XTop=pic->Top;
								pic->Left=OldLeft;
								pic->Top=OldTop;
								SetGadgetAttrs(pic->SideGad, pic->Win, NULL,
									PGA_Top, pic->Top, TAG_END);
								SetGadgetAttrs(pic->BotGad, pic->Win, NULL,
									PGA_Top, pic->Left, TAG_END);
								checkGadget(pic); 
								if (pic == &Pic1) {
									pic1 = &Pic2;
								}
								else {
									pic1 = &Pic1;
								}
								pic1->XLeft=pic1->Left;
								pic1->XTop=pic1->Top;
								pic1->Left=OldLeft1;
								pic1->Top=OldTop1;
								SetGadgetAttrs(pic1->SideGad, pic1->Win, NULL,
									PGA_Top, pic1->Top, TAG_END);
								SetGadgetAttrs(pic1->BotGad, pic1->Win, NULL,
									PGA_Top, pic1->Left, TAG_END);
								checkGadget(pic1); 
							}
						}
						break;
					default:
						// Some other mouse button?
						break;
					}
				}
}

void
MouseMove(struct Picture *pic) {
				/* The mouse moved
				 * If we are currently doing something
				 * then update
				 */
				if (SelDown) {
					OldX = CurX;
					OldY = CurY;
					CurX=EGS?pic->EGS_Win->MouseX:(pic->Win->GZZMouseX + Zoom + pic->Left)>>Zoom;
					CurY=EGS?pic->EGS_Win->MouseY:(pic->Win->GZZMouseY + Zoom + pic->Top)>>Zoom;
					LimitPoints(&CurX,&CurY,pic);
					switch(Mode) {
					case EDIT1:
						/* Editing one window
						 * Erase old position
						 */
						DrawPixels(pic,OldX,OldY,MyPoint);
						break;
					case ADD:
						/* Adding
						 * Erase old positions
						 */
						DrawPixels(&Pic1,OldX,OldY,NULL);
						DrawPixels(&Pic2,OldX,OldY,NULL);
						break;
					case EDIT2:
						/* Editing both windows
						 * Erase old positions
						 */
						DrawPixels(&Pic1,OldX,OldY,MyPoint);
						DrawPixels(&Pic2,OldX,OldY,MyPoint);
						break;
					case EDITREL:
						/* Editing relatively both windows
						 * Erase old positions
						 */
						OldX1 = CurX1;
						OldY1 = CurY1;
						CurX1 += (CurX - OldX);
						CurY1 += (CurY - OldY);
						if (pic == &Pic1){
							DrawPixels(&Pic1,OldX,OldY,MyPoint);
							DrawPixels(&Pic2,OldX1,OldY1,MyPoint);
						}
						else {
							DrawPixels(&Pic1,OldX1,OldY1,MyPoint);
							DrawPixels(&Pic2,OldX,OldY,MyPoint);
						}
						break;
					default:
						break;
					}
					if (!EGS) {
						// Scroll the current window if required
						pic->XLeft=pic->Left;
						pic->XTop=pic->Top;
						if ((CurY<<Zoom) < pic->Top) {
							pic->Top = (CurY<<Zoom);
							SetGadgetAttrs(pic->SideGad, pic->Win, NULL,
								PGA_Top, pic->Top, TAG_END);
						}
						if ((CurX<<Zoom) < pic->Left) {
							pic->Left = (CurX<<Zoom);
							SetGadgetAttrs(pic->BotGad, pic->Win, NULL,
								PGA_Top, pic->Left, TAG_END);
						}
						if ((CurY<<Zoom) > (pic->Win->GZZHeight+pic->Top)) {
							pic->Top = ((CurY<<Zoom) - pic->Win->GZZHeight);
							SetGadgetAttrs(pic->SideGad, pic->Win, NULL,
								PGA_Top, pic->Top, TAG_END);
						}
						if ((CurX<<Zoom) > (pic->Win->GZZWidth+pic->Left)) {
							pic->Left = ((CurX<<Zoom) - pic->Win->GZZWidth);
							SetGadgetAttrs(pic->BotGad, pic->Win, NULL,
								PGA_Top, pic->Left, TAG_END);
						}
						checkGadget(pic);
					}
					// Draw new positions
					switch(Mode) {
					case EDIT1:
						/* Editing one window
						 * Draw new position
						 */
						DrawPixels(pic,CurX,CurY,MyPoint);
						break;
					case ADD:
						/* Adding
						 * Draw new positions
						 */
						DrawPixels(&Pic1,CurX,CurY,NULL);
						DrawPixels(&Pic2,CurX,CurY,NULL);
						break;
					case EDIT2:
						/* Editing both windows
						 * Draw new positions
						 */
						DrawPixels(&Pic1,CurX,CurY,MyPoint);
						DrawPixels(&Pic2,CurX,CurY,MyPoint);
						break;
					case EDITREL:
						/* Editing both windows relatively
						 * Draw new positions
						 */
						LimitPoints(&CurX1,&CurY1,pic);
						if (pic == &Pic1){
							DrawPixels(&Pic1,CurX,CurY,MyPoint);
							DrawPixels(&Pic2,CurX1,CurY1,MyPoint);
						}
						else {
							DrawPixels(&Pic2,CurX,CurY,MyPoint);
							DrawPixels(&Pic1,CurX1,CurY1,MyPoint);
						}
						break;
					default:
						// Some other mode
						break;
					}
					if (!EGS) {
						/* If we are affecting the other window then
						 * we may need to scroll it
						 */
						if ((Mode == ADD) || (Mode == EDIT2) || (Mode == EDITREL)) {
							if (pic == &Pic1) {
								pic1 = &Pic2;
							}
							else {
								pic1 = &Pic1;
							}
							if (Mode != EDITREL) {
								// Points both in the same position
								CurX1 = CurX;
								CurY1 = CurY;
							}
							pic1->XLeft=pic1->Left;
							pic1->XTop=pic1->Top;
							if ((CurY1<<Zoom) < pic1->Top) {
								pic1->Top = (CurY1<<Zoom);
								SetGadgetAttrs(pic1->SideGad, pic1->Win, NULL,
									PGA_Top, pic1->Top, TAG_END);
							}
							if ((CurX1<<Zoom) < pic1->Left) {
								pic1->Left = (CurX1<<Zoom);
								SetGadgetAttrs(pic1->BotGad, pic1->Win, NULL,
									PGA_Top, pic1->Left, TAG_END);
							}
							if ((CurY1<<Zoom) > (pic1->Win->GZZHeight+pic1->Top)) {
								pic1->Top = ((CurY1<<Zoom) - pic1->Win->GZZHeight);
								SetGadgetAttrs(pic1->SideGad, pic1->Win, NULL,
									PGA_Top, pic1->Top, TAG_END);
							}
							if ((CurX1<<Zoom) > (pic1->Win->GZZWidth+pic1->Left)) {
								pic1->Left = ((CurX1<<Zoom) - pic1->Win->GZZWidth);
								SetGadgetAttrs(pic1->BotGad, pic1->Win, NULL,
									PGA_Top, pic1->Left, TAG_END);
							}
							// Update image scroll
							checkGadget(pic1);
						}
					}
				}
}
