#include <clib/alib_protos.h>
#include <clib/datatypes_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <datatypes/pictureclass.h>
#include <dos/dostags.h>
#include <exec/memory.h>
#include <libraries/cybergraphics.h>
#include <stdio.h>
#include <string.h>

struct Arg1
{
long *n,grey;
};

struct Arg2
{
long n,grey;
};

static void ReadPrefs(struct Arg2 *arg)
{
BPTR file;
arg->n=3;
arg->grey=0;
if(file=Open("ENV:DataTypes/pcd.prefs",MODE_OLDFILE))
	{
	char var[100];
	if(FGets(file,var,100))
		{
		RDArgs *rdargs;
      if(rdargs=AllocDosObject(DOS_RDARGS,0))
			{
			RDArgs *args;
			struct Arg1 para;
			para.n=0;
			para.grey=0;
			rdargs->RDA_Source.CS_Buffer=var;
			rdargs->RDA_Source.CS_Length=strlen(var);
			rdargs->RDA_Source.CS_CurChr=0;
			if(args=ReadArgs("RESOLUTION/N,GREY/S",(long *)&para,rdargs))
				{
				if(para.n)
					{
					arg->n=*para.n;
					if(arg->n<1) arg->n=1;
					else if(arg->n>6) arg->n=6;
					}
				arg->grey=para.grey;
				FreeArgs(args);
				}
			FreeDosObject(DOS_RDARGS,rdargs);
			}
		}
	Close(file);
	}
}

static ULONG ReadP5(IClass *cl,Object *obj,struct BitMapHeader *bh,BPTR file)
{
ULONG retval=0;
UBYTE *pix;
if(pix=AllocVec(bh->bmh_Width,MEMF_PUBLIC))
	{
	UWORD y;
	for(y=0;y<bh->bmh_Height;y++)
		{
		Read(file,pix,bh->bmh_Width);
		DoSuperMethod(cl,obj,PDTM_WRITEPIXELARRAY,pix,RECTFMT_LUT8,bh->bmh_Width,0,y,bh->bmh_Width,1);
		}
	retval=1;
	FreeVec(pix);
	}
else SetIoErr(ERROR_NO_FREE_STORE);
return retval;
}

static ULONG ReadP6(IClass *cl,Object *obj,struct BitMapHeader *bh,BPTR file)
{
ULONG retval=0;
UBYTE *pix;
if(pix=AllocVec(bh->bmh_Width*3,MEMF_PUBLIC))
	{
	UWORD y;
	for(y=0;y<bh->bmh_Height;y++)
		{
		Read(file,pix,bh->bmh_Width*3);
		DoSuperMethod(cl,obj,PDTM_WRITEPIXELARRAY,pix,RECTFMT_RGB,bh->bmh_Width*3,0,y,bh->bmh_Width,1);
		}
	retval=1;
	FreeVec(pix);
	}
else SetIoErr(ERROR_NO_FREE_STORE);
return retval;
}

static ULONG ReadNum(BPTR file)
{
ULONG retval=0;
for(;;)
	{
	char c;
	Read(file,&c,1);
	if(c==10||c==32) break;
	retval*=10;
	retval+=c-'0';
	}
return retval;
}

static ULONG GetPicture(struct IClass *cl,Object *obj)
{
ULONG retval=0;
char *fname;
if(fname=AllocVec(1024,MEMF_PUBLIC))
	{
	BPTR nil;
	if(nil=Open("NIL:",MODE_OLDFILE))
		{
		char *dname,tmp[L_tmpnam];
		struct Arg2 arg;
		ReadPrefs(&arg);
		GetDTAttrs(obj,DTA_Name,&dname,TAG_END);
		tmpnam(tmp);
		strncpy(tmp,"PIPE:",5);
		SPrintf(fname,"run pcdtoppm >%s -%lu -%s \"%s%\"",tmp,arg.n,(arg.grey)?"pgm":"ppm",dname);
		if(Execute(fname,nil,nil)!=DOSFALSE&&!IoErr())
			{
			BPTR file;
			if(file=Open(tmp,MODE_OLDFILE))
				{
				BitMapHeader *bh;
				char head[3];
				GetDTAttrs(obj,PDTA_BitMapHeader,&bh,TAG_END);
				Read(file,head,3);
				bh->bmh_Width=ReadNum(file);
				bh->bmh_PageWidth=((bh->bmh_Width+7)>>3)<<3;
				bh->bmh_Height=ReadNum(file);
				bh->bmh_PageHeight=((bh->bmh_Height+7)>>3)<<3;
				bh->bmh_Compression=1;
				ReadNum(file);
				if(head[1]=='5')
					{
					ULONG i;
					UBYTE *cr;
					ULONG *cregs;
					bh->bmh_Depth=8;
					SetDTAttrs(obj,0,0,DTA_NominalHoriz,bh->bmh_Width,DTA_NominalVert,bh->bmh_Height,PDTA_ModeID,0,PDTA_SourceMode,PMODE_V43,PDTA_NumColors,256,TAG_END);
					GetDTAttrs(obj,PDTA_ColorRegisters,&cr,PDTA_CRegs,&cregs,TAG_END);
					for(i=0;i<256;i++)
						{
						UWORD j;
						for(j=0;j<3;j++)
							{
							*(cr++)=i;
							*(cregs++)=i<<24;
							}
						}
					retval=ReadP5(cl,obj,bh,file);
					}
				else if(head[1]=='6')
					{
					bh->bmh_Depth=24;
					SetDTAttrs(obj,0,0,DTA_NominalHoriz,bh->bmh_Width,DTA_NominalVert,bh->bmh_Height,PDTA_ModeID,0,PDTA_SourceMode,PMODE_V43,TAG_END);
					retval=ReadP6(cl,obj,bh,file);
					}
				else SetIoErr(ERROR_NOT_IMPLEMENTED);
				Close(file);
				}
			}
		Close(nil);
		}
	FreeVec(fname);
	}
else SetIoErr(ERROR_NO_FREE_STORE);
return retval;
}

static ULONG mNew(struct IClass *cl,Object *obj,Msg msg)
{
if(obj=(Object *)DoSuperMethodA(cl,obj,msg))
	{
	if(!GetPicture(cl,obj))
		{
		CoerceMethod(cl,obj,OM_DISPOSE);
		obj=0;
		}
	}
return ULONG(obj);
}

ULONG Dispatcher(struct IClass *cl,Object *obj,Msg msg)
{
ULONG retval;
switch(msg->MethodID)
	{
	case OM_NEW:
		retval=mNew(cl,obj,msg);
		break;
	default:
		retval=DoSuperMethodA(cl,obj,msg);
		}
return retval;
}

