/* Convert and display images */

/* mark@topic.demon.co.uk */
/* mpaddock@cix.compulink.co.uk */

/* This is freely distributable */

#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/utility.h>
#include <proto/locale.h>
extern struct Library *LocaleBase = NULL;

#include <dos/dos.h>

#include <math.h>

/* EGS Stuff	*/
#include <egs/clib/egs_protos.h>
#include <egs/pragmas/egs_pragmas.h>

#include <egs/clib/egsintui_protos.h>
#include <egs/pragmas/egsintui_pragmas.h>

#include <egs/clib/egsgfx_protos.h>
#include <egs/pragmas/egsgfx_pragmas.h>

#include <egs/egsintui.h>

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

#include <libraries/MPImage.h>
#include <pragmas/MPImage_pragmas.h>
#include <clib/MPImage_protos.h>
#include <dos.h>
#include <string.h>
#include <dos/rdargs.h>

#define TEMPLATE "FROM/A/M,X/N/K,Y/N/K,MINX/N/K,MINY/N/K,MAXX/N/K,MAXY/N/K,KEEPASPECT/S,QUICKSCALE/S,PUBSCREEN/K,EGS/S,NOREMAP/S,CLONE/S,TO=TODIR/K,FORMAT/K,FORCEGREY/S,PALETTE/K,COLOURS/K/N,12BIT/S,LINEAR/S,WHITE0/S,MODENAME/K,NOPROGRESS/S,GUI/S"

#define OPT_FILE			0
#define OPT_X				1
#define OPT_Y				2
#define OPT_MINX			3
#define OPT_MINY			4
#define OPT_MAXX			5
#define OPT_MAXY			6
#define OPT_KEEPASPECT	7
#define OPT_QUICKSCALE	8
#define OPT_SCREEN		9
#define OPT_EGS			10
#define OPT_NOREMAP		11
#define OPT_CLONE			12
#define OPT_TO				13
#define OPT_FORMAT		14
#define OPT_FORCEGREY	15
#define OPT_PALETTE		16
#define OPT_COLOURS		17
#define OPT_12BIT			18
#define OPT_LINEAR		19
#define OPT_WHITE0		20
#define OPT_MODENAME		21
#define OPT_PROGRESS		22
#define OPT_GUI			23

#define OPT_COUNT			24

extern long __oslibversion=39;

extern long __stack = 16000;

struct Library *MPImageBase;

const char Version[]="$VER: ConvertMPImage 8.1 (10.7.97)";

UBYTE NewMap256[256] = {  1,   2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
								  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
								  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
								  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
								  64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
								  80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
								  96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
								 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
								 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
								 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
								 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
								 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
								 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
								 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
								 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
								 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,  0
								};
UBYTE NewMap16[16] = {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,  0
							};

extern struct Catalog *Catalog=NULL;

#define CATCOMP_BLOCK
#define CATCOMP_NUMBERS
#include "Cmessages.h"

char
*GetMessage(UWORD message) {
	LONG   *l;
	UWORD  *w;
	STRPTR  builtIn;

   l = (LONG *)CatCompBlock;

	while (*l != message)  {
		w = (UWORD *)((ULONG)l + 4);
		l = (LONG *)((ULONG)l + (ULONG)*w + 6);
	}
	builtIn = (STRPTR)((ULONG)l + 6);
	return(GetCatalogStr(Catalog,message,builtIn));
}

#define RESIZEA \
	if (minx) { \
		if (newx < minx) { \
			newx = minx; \
		} \
	} \
	if (maxx) { \
		if (newx > maxx) { \
			newx = maxx; \
		} \
	} \
	if (!minx && !maxx) { \
		if (x) { \
			newx = x; \
		} \
	} \
	if (miny) { \
		if (newy < miny) { \
			newy = miny; \
		} \
	} \
	if (maxy) { \
		if (newy > maxy) { \
			newy = maxy; \
		} \
	} \
	if (!miny && !maxy) { \
		if (y) { \
			newy = y; \
		} \
	}

#define RESIZE \
	newx = MPi->Width; \
	newy = MPi->Height; \
	RESIZEA; \
	if (keepaspect) { \
		float xscale, yscale; \
		xscale = (float)newx / MPi->Width; \
		yscale = (float)newy / MPi->Height; \
		if (x) { \
			newy = MPi->Height * xscale; \
		} \
		else if (y) { \
			newx = MPi->Width * yscale; \
		} \
		else { \
			float oldxy,newxy; \
			oldxy = (float)MPi->Width / MPi->Height; \
			newxy = (float)newx / newy; \
			if (oldxy > newxy) { \
				newx = MPi->Width * yscale; \
				if (maxx) { \
					if (newx > maxx) { \
						newx = maxx; \
						newy = newx / oldxy; \
					} \
				} \
			} \
			else if (oldxy < newxy) { \
				newy = MPi->Height * xscale; \
				if (maxy) { \
					if (newy > maxy) { \
						newy = maxy; \
						newx = newy * oldxy; \
					} \
				} \
			} \
		} \
		RESIZEA; \
	} \
	if ((newx != MPi->Width) || (newy != MPi->Height)) { \
		resize = TRUE; \
	}

struct MyAnchorPath {
	struct AnchorPath ap;
	char x[512];
} map;

int
main(int argc,char **argv) {
	BOOL FromWB = FALSE;
	struct RDArgs *rdargs = NULL;
	LONG opts[OPT_COUNT] = {
		0
	};
	int resx = RETURN_OK;
	struct EasyStruct es = {
		sizeof(struct EasyStruct),
		0,
		"ConvertMPImage",
		NULL,
		NULL
	};
	struct MPImage *MPi;
	struct Screen *screen;
	struct Window *win;
	struct IntuiMessage *msg;
	BOOL done;
	struct EI_NewWindow	EGS_NewWindow = {0};	// EGS New window
	struct EI_Window		*EGS_Win;				// EGS Window
	struct EI_EIntuiMsg 	*EGSmsg;					// Message from the EGS windows
	ULONG newx,newy;
	ULONG x=0,y=0,minx=0,miny=0,maxx=0,maxy=0;
	BOOL keepaspect = FALSE;
	BOOL resize = FALSE;
	char **files;
	char *filearray[2] = {NULL,NULL};
	int i;
	int err;
	char *to;
	char tobuffer[512];
	BOOL ToDir = FALSE;
	char *r=NULL,*g=NULL,*b=NULL;

	LocaleBase = OpenLibrary("locale.library",38);
	if (!LocaleBase) {
		if (FromWB) {
			es.es_TextFormat = "Error Opening locale.library(38)";
			EasyRequestArgs(NULL,&es,NULL,NULL);
		}
		else {
			Printf("Error Opening locale.library(38)");
			Printf("\n");
		}
		return RETURN_FAIL;
	}
	Catalog = OpenCatalog(NULL,
  								"mp/convertmpimage.catalog",
  								TAG_END);
	es.es_GadgetFormat = GetMessage(MSG_OK);
	if (argc == 0) {
		argc = _WBArgc;
		argv = _WBArgv;
		FromWB = TRUE;
		if (argc < 2) {
			es.es_TextFormat = GetMessage(MSG_DOUBLE);
			EasyRequestArgs(NULL,&es,NULL,NULL);
			CloseCatalog(Catalog);
			CloseLibrary(LocaleBase);
			return RETURN_WARN;
		}
		files = filearray;
		filearray[0] = argv[1];
		
	}
	else {
		if (!(rdargs = ReadArgs((char *)TEMPLATE, opts, NULL))) {
			PrintFault(IoErr(), NULL);
			CloseCatalog(Catalog);
			CloseLibrary(LocaleBase);
			return RETURN_ERROR;
		}
		if (opts[OPT_GUI]) {
			FromWB=TRUE;
		}
		files = (char **)opts[OPT_FILE];
	}
	if (opts[OPT_X]) {
		x = *((ULONG *)opts[OPT_X]);
	}
	if (opts[OPT_Y]) {
		y = *((ULONG *)opts[OPT_Y]);
	}
	if (opts[OPT_MINX]) {
		minx = *((ULONG *)opts[OPT_MINX]);
	}
	if (opts[OPT_MINY]) {
		miny = *((ULONG *)opts[OPT_MINY]);
	}
	if (opts[OPT_MAXX]) {
		maxx = *((ULONG *)opts[OPT_MAXX]);
	}
	if (opts[OPT_MAXY]) {
		maxy = *((ULONG *)opts[OPT_MAXY]);
	}
	if (opts[OPT_KEEPASPECT]) {
		keepaspect = TRUE;
	}
	if (MPImageBase = OpenLibrary("MPImage.library",6)) {
	 SetMPImageScreen((char *)opts[OPT_SCREEN],opts[OPT_PROGRESS]?0:MPIF_PROGRESS);
	 map.ap.ap_BreakBits = SIGBREAKF_CTRL_C;
	 map.ap.ap_Strlen = 510;
	 for (i=0; files[i]; ++i) {
	  err = MatchFirst(files[i],&(map.ap));
	  while (!err) {
		if (opts[OPT_TO] || opts[OPT_FORMAT]) {
			if (opts[OPT_TO] && *(char *)opts[OPT_TO]) {
				if (getfa((char *)opts[OPT_TO]) == 1) {
					ToDir = TRUE;
				}
			}
			if (MPi=LoadMPImage(map.ap.ap_Buf,NULL,
										(opts[OPT_FORCEGREY] ? MPIF_FORCEGREY : MPIF_GREY) |
										(opts[OPT_LINEAR] ? MPIF_LINEARGREY : 0))) {
				RESIZE;
				if (resize) {
					if (!RESCALEMPIMAGE(MPi,newx,newy,opts[OPT_QUICKSCALE])) {
						if (FromWB) {
							es.es_TextFormat = MPImageErrorMessage();
							EasyRequestArgs(NULL,&es,NULL,NULL);
						}
						else {
							Printf(MPImageErrorMessage());
							Printf("\n");
						}
						resx = RETURN_FAIL;
					}
				}
				if (!resx) {
					UBYTE *GreyMap = NULL;
					if (opts[OPT_WHITE0]) {
						if (!opts[OPT_FORMAT] || !stricmp((UBYTE *)opts[OPT_FORMAT],MPI_BW16)) {
							GreyMap = NewMap16;
						}
						else {
							if (!stricmp((UBYTE *)opts[OPT_FORMAT],MPI_BW256)) {
								GreyMap = NewMap256;
							}
						}
					}
					if (ToDir) {
						to = tobuffer;
						strncpy(tobuffer,(char *)opts[OPT_TO],510);
						AddPart(tobuffer,FilePart(map.ap.ap_Buf),510);
					}
					else {
						to = (char *)opts[OPT_TO];
					}
					if (!SaveMPImage(to,
										r?r:MPi->Red, r?g:MPi->Green, r?b:MPi->Blue,
										r?newx:MPi->Width, r?newy:MPi->Height,
										MPIS_MODENAME,opts[OPT_MODENAME],
										MPIS_FORMAT,opts[OPT_FORMAT],
										MPIS_PALETTE,opts[OPT_PALETTE],
										opts[OPT_COLOURS]?MPIS_COLOURS:TAG_IGNORE,opts[OPT_COLOURS] ? *((ULONG *)opts[OPT_COLOURS]) : 0,
										MPIS_12BIT, opts[OPT_12BIT],
										MPIS_LINEAR, opts[OPT_LINEAR],
										MPIS_GREYMAP, GreyMap,
										TAG_END)) {
						if (FromWB) {
							es.es_TextFormat = MPImageErrorMessage();
							EasyRequestArgs(NULL,&es,NULL,NULL);
						}
						else {
							Printf(MPImageErrorMessage());
							Printf("\n");
						}
						resx = RETURN_FAIL;
					}
					if (r) {
						FreeVec(r);
						if (r != g) {
							if (g) {
								FreeVec(g);
							}
							if (b) {
								FreeVec(b);
							}
						}
					}
				}
				FreeMPImage(MPi);
			}
			else {
				if (FromWB) {
					es.es_TextFormat = MPImageErrorMessage();
					EasyRequestArgs(NULL,&es,NULL,NULL);
				}
				else {
					Printf(MPImageErrorMessage());
					Printf("\n");
				}
				resx = RETURN_FAIL;
			}
		}
		else {
			if (opts[OPT_EGS]) {
				if ((EGSBase = OpenLibrary((char *)"egs.library",0)) &&
					 (EGSGfxBase = OpenLibrary((char *)"egsgfx.library",0)) &&
				    (EGSIntuiBase = OpenLibrary((char *)"egsintui.library", 0))) {
				   screen = NULL;
					if (MPi=LoadMPImage(map.ap.ap_Buf,screen,MPIF_EGS)) {
						RESIZE;
						if (resize) {
							if (!RescaleMPImage(MPi,newx,newy)) {
								if (FromWB) {
									es.es_TextFormat = MPImageErrorMessage();
									EasyRequestArgs(NULL,&es,NULL,NULL);
								}
								else {
									Printf(MPImageErrorMessage());
									Printf("\n");
								}
								resx = RETURN_FAIL;
							}
						}
						if (!resx) {
							EGS_NewWindow.LeftEdge = 0;
							EGS_NewWindow.TopEdge = 20;
							EGS_NewWindow.Width = MPi->Width;
							EGS_NewWindow.Height = MPi->Height;
							EGS_NewWindow.MinWidth = 20;
							EGS_NewWindow.MinHeight = 20;
							EGS_NewWindow.MaxWidth = MPi->Width;
							EGS_NewWindow.MaxHeight = MPi->Height;
							EGS_NewWindow.Screen = NULL;
							EGS_NewWindow.Bordef.SysGadgets = EI_WINDOWSIZE | EI_WINDOWFRONT | EI_WINDOWFLIP |
																		 EI_WINDOWARROWL | EI_WINDOWARROWR | EI_WINDOWARROWU | EI_WINDOWARROWD |
																		 EI_WINDOWSCROLLH | EI_WINDOWSCROLLV | EI_WINDOWDRAG |
																		 EI_WINDOWCLOSE;
							EGS_NewWindow.FirstGadgets = NULL;
							EGS_NewWindow.Title = map.ap.ap_Buf;
							EGS_NewWindow.Flags = EI_GIMMEZEROZERO | EI_SUPER_BITMAP | EI_WINDOWACTIVE | EI_REPORTMOUSE | EI_QUICKSCROLL | EI_RMBTRAP;
							EGS_NewWindow.IDCMPFlags = EI_iCLOSEWINDOW;
							EGS_NewWindow.Port = NULL;
							EGS_NewWindow.Menu = NULL;
							EGS_NewWindow.Render = NULL;
							if (EGS_Win = EI_OpenWindow(&EGS_NewWindow)) {
								E_ActivateEGSScreen();
								EG_CopyBitMapRastPort(MPi->EGS_BitMap,EGS_Win->RPort,0,0,MPi->Width,MPi->Height,0,0);
								done = FALSE;
								while	(!done) {
									WaitPort(EGS_Win->UserPort);
									while (EGSmsg = (struct EI_EIntuiMsg *)GetMsg(EGS_Win->UserPort)) {
										switch (EGSmsg->Class) {
										case EI_iCLOSEWINDOW:
											done = TRUE;
											break;
										default:
											break;
										}
										ReplyMsg((struct Message *)EGSmsg); 
									}
								}
								EI_CloseWindow(EGS_Win);
							}
						}
						FreeMPImage(MPi);
					}
					else {
						if (FromWB) {
							es.es_TextFormat = MPImageErrorMessage();
							EasyRequestArgs(NULL,&es,NULL,NULL);
						}
						else {
							Printf(MPImageErrorMessage());
							Printf("\n");
						}
						resx = RETURN_FAIL;
					}
				}
				if (EGSIntuiBase) {
					CloseLibrary(EGSIntuiBase);
				}
				if (EGSGfxBase) {
					CloseLibrary(EGSGfxBase);
				}
				if (EGSBase) {
					CloseLibrary(EGSBase);
				}
			}
			else {
				if (screen = LockPubScreen((UBYTE *)opts[OPT_SCREEN])) {
					if (MPi=LoadMPImage(map.ap.ap_Buf,screen,
								(opts[OPT_CLONE] ? MPIF_CLONEBITMAP : 0) | 
								(opts[OPT_NOREMAP] ? MPIF_NOREMAP : 0))) {
						RESIZE;
						if (resize) {
							if (!RescaleMPImage(MPi,newx,newy)) {
								if (FromWB) {
									es.es_TextFormat = MPImageErrorMessage();
									EasyRequestArgs(NULL,&es,NULL,NULL);
								}
								else {
									Printf(MPImageErrorMessage());
									Printf("\n");
								}
								resx = RETURN_FAIL;
							}
						}
						if (!resx) {
							if (win = OpenWindowTags(NULL,
														WA_CloseGadget, TRUE,
														WA_PubScreen, screen,
														WA_SuperBitMap, MPi->BitMap,
														WA_IDCMP, IDCMP_CLOSEWINDOW,
														WA_InnerWidth, MPi->Width,
														WA_InnerHeight, MPi->Height,
														WA_Title, map.ap.ap_Buf,
														WA_DragBar, TRUE,
														WA_NoCareRefresh, TRUE,
														WA_AutoAdjust, TRUE,
														WA_GimmeZeroZero,TRUE,
														TAG_END)) {
								done = FALSE;
								while	(!done) {
									WaitPort(win->UserPort);
								 	while (msg = (struct IntuiMessage *)GetMsg(win->UserPort)) {
								 		switch (msg->Class) {
								 		case IDCMP_CLOSEWINDOW:
									 		// Close window
											done = TRUE;
						 					break;
								 		default:
									 		// unknown message
								 			break;
									 		}
										ReplyMsg((struct Message *)msg);
							 		}
								}	
								CloseWindow(win);
							}
						}
						FreeMPImage(MPi);
					}
					else {
						if (FromWB) {
							es.es_TextFormat = MPImageErrorMessage();
							EasyRequestArgs(NULL,&es,NULL,NULL);
						}
						else {
							Printf(MPImageErrorMessage());
							Printf("\n");
						}
						resx = RETURN_FAIL;
					}
					UnlockPubScreen(NULL,screen);
				}
				else {
					if (FromWB) {
						es.es_TextFormat = GetMessage(MSG_SCREEN);
						EasyRequest(NULL,&es,NULL,(UBYTE *)opts[OPT_SCREEN]);
					}
					else {
						Printf(GetMessage(MSG_SCREEN),(UBYTE *)opts[OPT_SCREEN]);
						Printf("\n");
					}
				}
			}
		}
		err = MatchNext(&(map.ap));
	  }
	  MatchEnd(&(map.ap));
	 }
	 CloseLibrary(MPImageBase);
	}
	else {
		if (FromWB) {
			es.es_TextFormat = GetMessage(MSG_LIBRARY);
			EasyRequestArgs(NULL,&es,NULL,NULL);
		}
		else {
			Printf(GetMessage(MSG_LIBRARY));
			Printf("\n");
		}
		resx = RETURN_FAIL;
	}
	if (rdargs) {
		FreeArgs(rdargs);
	}
	CloseCatalog(Catalog);
	CloseLibrary(LocaleBase);
	return resx;
}
