#include <exec/types.h>
#include <devices/clipboard.h>
#include <dos/dos.h>
#include <libraries/iffparse.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <string.h>

#define DOSPRINT(x) Write(Output(),x,strlen(x));

struct iffstart {
	ULONG form;
	ULONG length;
	ULONG formtype;
} is;

void cleanup(char *,int);
int OpenClip(void);
void CloseClip(void);
int savechunk(void);

struct DosLibrary *DOSBase=NULL;
struct IOClipReq *ioc=NULL;
struct MsgPort *port=NULL;
char buf[102],clipb=FALSE,ver[]="\0$VER: SaveClip 1.0 " __AMIGADATE__;
BPTR fh=NULL;

int __saveds __asm not_main(register __a0 char *args, register __d0 long len) {
	if(!(DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",0L))) {
		return(20);
	}
	if(!OpenClip()) cleanup("Couldn't open clipboard.device\n",20);
	args[len-1]=0;
	if(!(fh=Open(args,MODE_NEWFILE))) {
		DOSPRINT("Couldn't open ")
		DOSPRINT(args)
		DOSPRINT("\n")
		cleanup(NULL,10);
	}
	ioc->io_Offset=0;
	ioc->io_ClipID=0;
	ioc->io_Command=CMD_READ;
	ioc->io_Length=12;
	ioc->io_Data=(APTR)&is;
	DoIO((struct IORequest *)ioc);
	if(ioc->io_Actual<8 || is.form!=(ULONG)(ID_FORM) || is.formtype!=(ULONG)MAKE_ID('F','T','X','T')) {
		ioc->io_Length=~0L;
		ioc->io_Data=NULL;
		DoIO((struct IORequest *)ioc);
		if(ioc->io_Actual) DoIO((struct IORequest *)ioc);
		cleanup("Not an IFF-FTXT clip\n",5);
	}
	while(savechunk());
	cleanup(NULL,0);
}

void cleanup(char *msg,int code) {
	if(fh) Close(fh);
	if(clipb) CloseClip();
	if(DOSBase) {
		if(msg) DOSPRINT(msg);
		CloseLibrary((struct Library *)DOSBase);
	}
	Exit(code);
}

int OpenClip(void) {
	if(!(port=CreatePort(NULL,0L))) return(FALSE);
	if(!(ioc=(struct IOClipReq *)CreateExtIO(port,sizeof(struct IOClipReq)))) {
		DeletePort(port);
		return(FALSE);
	}
	if(OpenDevice("clipboard.device",0,(struct IORequest *)ioc,0)) {
		DeleteExtIO((struct IORequest *)ioc);
		DeletePort(port);
		return(FALSE);
	}
	clipb=TRUE;
	return(TRUE);
}

void CloseClip(void) {
	CloseDevice((struct IORequest *)ioc);
	DeleteExtIO((struct IORequest *)ioc);
	DeletePort(port);
}

int savechunk(void) {
	int x,read;
	ioc->io_Length=8;
	ioc->io_Data=(APTR)&is;
	DoIO((struct IORequest *)ioc);
	if(!ioc->io_Actual) return(FALSE);
	if(is.form!=(ULONG)MAKE_ID('C','H','R','S')) {
		ioc->io_Length=is.length;
		ioc->io_Data=NULL;
		DoIO((struct IORequest *)ioc);
		return(TRUE);
	}
	for(x=0;x<is.length;x+=100) {
		if((is.length-x) > 100) read=100;
		else read=is.length-x;
		ioc->io_Length=read;
		ioc->io_Data=buf;
		DoIO((struct IORequest *)ioc);
		if(Write(fh,buf,read)==-1) {
			ioc->io_Length=~0L;
			ioc->io_Data=NULL;
			DoIO((struct IORequest *)ioc);
			cleanup("Error writing file\n",10);
		}
	}
	return(TRUE);
}
