// MPMorph - 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 precompiled headers if required

#ifndef MPMORPH_AMIGA_H
#include "MPMorph-amiga.h"
#endif
#ifndef MPMORPH_H
#include "MPMorph.h"
#endif
void
EGSReopenAPicture(char *dirname,struct Picture *pic,char **e,char **e1,UWORD *OldWidth,UWORD *OldHeight,LONG *hnum) {
  FreeMPImage(pic->MPi);
  // Try and load new brush - if this fails then flag error
  if (!(pic->MPi = LoadMPImage(dirname,NULL,MPIF_EGS | MPIF_CLONEBITMAP))) {
   // set up error stuff
   *e = MyGetMsg(MSG_FAILLOAD);
   *e1 = MPImageErrorMessage();
   *hnum = HE_LoadImage;
  }
  if (!e) {
   // resize if frame is not the same size as previous
   if ((pic->MPi->Width != *OldWidth) ||
		(pic->MPi->Height != *OldHeight)) {
    if (!RescaleMPImage(pic->MPi,*OldWidth,*OldHeight)) {
	  *e = MyGetMsg(MSG_MPIMAGESCALE);
	  *e1 = MPImageErrorMessage();
     *hnum = HE_MPIScale;
    }
   }
   if (!e) {
    EI_SetWindowTitles(pic->EGS_Win,FilePart(pic->filename),pic->filename);
    EG_CopyBitMapRastPort(pic->MPi->EGS_BitMap,pic->EGS_Win->RPort,0,0,pic->MPi->Width,pic->MPi->Height,0,0);
   }
   E_DisposeBitMap(pic->MPi->EGS_BitMap);
   pic->MPi->EGS_BitMap = NULL;
  }
  else {
   // failed loading new image
   // set up error stuff
   *e = MyGetMsg(MSG_FAILLOAD);
   *e1 = dirname;
   *hnum = HE_LoadImage;
  }
}

void
EGSError(char *ErrorMessage,char *Gadget,char *extra,ULONG helpnum,char *buffer,char *gad) {
	struct ER_SimpleRequest *EGS_Request;
	UBYTE *p;
	BOOL finished = FALSE;
	struct AmigaGuideMsg *agm;

	sprintf(buffer,ErrorMessage,extra);
	p = buffer;
	while (*p) {
		if (*p == '\n') {
			*p = '|';
		}
		p++;
	}
	if (handle) {
		strcat(gad,Gadget);
	}
	else {
		strcpy(gad,Gadget);
	}
	if (EGS_Request = ER_CreateSimpleReq(NULL,buffer,gad)) {
		ER_ChangeRequestPos(EGS_Request,
				max(Pic1.EGS_Win->WScreen->EScreen->MouseX-20,0),
				max(Pic1.EGS_Win->WScreen->EScreen->MouseY-20,0));
		while (!finished) {
			if (ER_DoRequest(EGS_Request)) {
				if ((!EGS_Request->Selected) && handle) {
					help(helpnum);
				}
				else {
					finished = TRUE;
				}
			  	while (agm = GetAmigaGuideMsg(handle)) {
		 			ReplyAmigaGuideMsg(agm);
		 		}
			}
			else {
				finished = TRUE;
			}
		}
		ER_DeleteRequest(EGS_Request);
	}
}

/* Similar to EG_Draw() but always draws top left to bottom right
 * to prevent stray pixels if erasing by drawing in the other direction
 */
void
EGSMyDraw(struct EG_RastPort *rp, LONG x, LONG y, LONG oldx, LONG oldy) {
	if ((oldx < x) || ((oldx == x) && (oldy < y))) {
		EG_Move(rp,(SHORT)((oldx + 0.5)/xfact),(SHORT)((oldy + 0.5)/yfact));
		EG_Draw(rp,(SHORT)((x + 0.5)/xfact),(SHORT)((y + 0.5)/yfact));
	}
	else {
		EG_Move(rp,(SHORT)((x + 0.5)/xfact),(SHORT)((y + 0.5)/yfact));
		EG_Draw(rp,(SHORT)((oldx + 0.5)/xfact),(SHORT)((oldy + 0.5)/yfact));
	}
}

BOOL
EGSOpenAPicture(struct Picture *pic,char *ifilename,char **e,char **e1,LONG *hnum) {
	struct EI_NewWindow EGS_NewWindow = {0};	// EGS New window

	if (pic->filename = AllocVec(strlen(ifilename)+1+20,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->MPi->Width;
      EGS_NewWindow.Height		= pic->MPi->Height;
      EGS_NewWindow.MinWidth	= 20;
      EGS_NewWindow.MinHeight	= 20;
      EGS_NewWindow.MaxWidth	= pic->MPi->Width;
      EGS_NewWindow.MaxHeight	= pic->MPi->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.Menu 		= NULL;
      EGS_NewWindow.Render 		= NULL;
      if (pic->EGS_Win = EI_OpenWindow(&EGS_NewWindow)) {
			EI_SetWindowTitles(pic->EGS_Win,(UBYTE *)-1,pic->filename);
       	pic->EGS_Win->UserData  = (BYTE *)pic;
       	if (pic == &Pic2) {
        		E_ActivateEGSScreen();
       	}
       	EG_CopyBitMapRastPort(pic->MPi->EGS_BitMap,pic->EGS_Win->RPort,0,0,pic->MPi->Width,pic->MPi->Height,0,0);
       	E_DisposeBitMap(pic->MPi->EGS_BitMap);
        	pic->MPi->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;
   }
   return FALSE;
}

void
EGSCloseAPicture(struct Picture *pic) {
	if (pic->EGS_Win) {
		EI_CloseWindow(pic->EGS_Win);
		pic->EGS_Win = NULL;
	}
	if (pic->MPi) {
		if (pic->MPi->EGS_BitMap) {
			E_DisposeBitMap(pic->MPi->EGS_BitMap);
			pic->MPi->EGS_BitMap = NULL;
		}
	}
}

void
EGSDrawPixels(struct Picture *pic,SHORT x,SHORT y,struct MyPoint *MyPoint) {
	SHORT zx,zy;
	int i;
	/* draw 3x3 point
	 */
	zx = (x + (xfact/2))/ xfact;
	zy = (y + (yfact/2))/ yfact;
	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,x,y);
				}
			}
		}
	}
	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,x,y);
				}
			}
		}
	}
}

void
EGSMsgLoop(int *flag) {
	struct EI_EIntuiMsg 	*EGSmsg;		// Message from the EGS windows
	struct Picture *pic;
 	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:
 			if (!Disabled) {
       		*flag = 2;
       	}
	  		break;
		case EI_iVANILLAKEY:
			if (!Disabled) {
 				Vanilla(EGSmsg->Code);
 			}
			break;
		case EI_iMOUSEBUTTONS:
			if (!Disabled) {
				MouseButtons(pic,EGSmsg->Code,EGSmsg->Seconds);
			}
			break;
		case EI_iMOUSEMOVE:
			if (!Disabled) {
				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); 
  	}
}
void
EGSSetMyPointer(UWORD *Pointer,struct E_EMouseImg32 *EMouseImg) {
	int i,j;
	UWORD a,b;
	ULONG c,d;
	// 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;
			}
		}
		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;
	}
}
