#include <libraries/zbbs.h>
#include "protos.h"
#include "globals.c"

BOOL OpenXPrWindow()
{
	struct Gadget		*glist, *Gadgets[2], *g;
	struct NewGadget	ng;

	if(XPrWindow)	return(TRUE);

	if(XPrWindow = OpenWindowTags(NULL,
		WA_Width,			600,
		WA_Height,			184,
		WA_Left,				(Scr->Width - 600) >> 1,
		WA_Top,				(Scr->Height - 184) >> 1,
		WA_Activate,		FALSE,
		WA_DragBar,			TRUE,
		WA_DepthGadget,	TRUE,
		WA_CloseGadget,	TRUE,
		WA_RMBTrap,			TRUE,
		WA_IDCMP,			IDCMP_CLOSEWINDOW | IDCMP_GADGETUP,
		WA_Title,			"Z-BBS  XPr.library Transfer Window",
		WA_CustomScreen,	Scr,
		TAG_DONE))
	{
		BlockWindow(Win1);
		BlockWindow(Win2);

#define LEFTX 15
#define RIGHTX 310

		SetAPen(XPrWindow->RPort, (depth == 1 ? 1 : 2));

		wprintf(XPrWindow->RPort, LEFTX,		18,	"Selected Protocol.:");
		wprintf(XPrWindow->RPort, LEFTX,		31,	"Last XPr-Message..:");
		wprintf(XPrWindow->RPort, LEFTX,		41,	"Last XPr-Error....:");
		wprintf(XPrWindow->RPort, LEFTX,		54,	"Current Filename..:");
		wprintf(XPrWindow->RPort, LEFTX,		64,	"Current Filesize..:");
		wprintf(XPrWindow->RPort, LEFTX,		81,	"Bytes Transferred.:");
		wprintf(XPrWindow->RPort, LEFTX,		91,	"Blocks Transferred:");
		wprintf(XPrWindow->RPort, LEFTX,		101,	"Block Size........:");
		wprintf(XPrWindow->RPort, LEFTX,		111,	"Block Check Type..:");
		wprintf(XPrWindow->RPort, LEFTX,		127,	"Estimated Time....:");
		wprintf(XPrWindow->RPort, LEFTX,		137,	"Elapsed Time......:");
		wprintf(XPrWindow->RPort, RIGHTX,	81,	"Data Rate [CPS]...:");
		wprintf(XPrWindow->RPort, RIGHTX,	91,	"Charakter Delay...:");
		wprintf(XPrWindow->RPort, RIGHTX,	101,	"Packet Delay......:");
		wprintf(XPrWindow->RPort, RIGHTX,	111,	"Packet Type.......:");
		wprintf(XPrWindow->RPort, RIGHTX,	127,	"Number Of Errors..:");
		wprintf(XPrWindow->RPort, RIGHTX,	137,	"Number Of Timeouts:");

#define XLEFT	178
#define XRIGHT	472

		SetAPen(XPrWindow->RPort, 7);

		wprintf(XPrWindow->RPort, XLEFT,		18,	"- unknown -");
		wprintf(XPrWindow->RPort, XLEFT,		31,	"- none -");
		wprintf(XPrWindow->RPort, XLEFT,		41,	"- none -");
		wprintf(XPrWindow->RPort, XLEFT,		54,	"- unknown -");
		wprintf(XPrWindow->RPort, XLEFT,		64,	"-");
		wprintf(XPrWindow->RPort, XLEFT,		81,	"-");
		wprintf(XPrWindow->RPort, XLEFT,		91,	"-");
		wprintf(XPrWindow->RPort, XLEFT,		101,	"-");
		wprintf(XPrWindow->RPort, XLEFT,		111,	"--");
		wprintf(XPrWindow->RPort, XLEFT,		127,	"--:--:--");
		wprintf(XPrWindow->RPort, XLEFT,		137,	"--:--:--");
		wprintf(XPrWindow->RPort, XRIGHT,	81,	"-");
		wprintf(XPrWindow->RPort, XRIGHT,	91,	"-");
		wprintf(XPrWindow->RPort, XRIGHT,	101,	"-");
		wprintf(XPrWindow->RPort, XRIGHT,	111,	"--");
		wprintf(XPrWindow->RPort, XRIGHT,	127,	"-");
		wprintf(XPrWindow->RPort, XRIGHT,	137,	"-");

		DrawBevelBox(XPrWindow->RPort, XLEFT - 8, 15, 416, 59,
			GTBB_Recessed,	TRUE,
			GT_VisualInfo,	VisualInfo,
			TAG_DONE );
		DrawBevelBox(XPrWindow->RPort, XLEFT - 8, 78, 122, 43,
			GTBB_Recessed,	TRUE,
			GT_VisualInfo,	VisualInfo,
			TAG_DONE );
		DrawBevelBox(XPrWindow->RPort, XRIGHT - 8, 78, 122, 43,
			GTBB_Recessed,	TRUE,
			GT_VisualInfo,	VisualInfo,
			TAG_DONE );
		DrawBevelBox(XPrWindow->RPort, XLEFT - 8, 124, 122, 23,
			GTBB_Recessed,	TRUE,
			GT_VisualInfo,	VisualInfo,
			TAG_DONE );
		DrawBevelBox(XPrWindow->RPort, XRIGHT - 8, 124, 122, 23,
			GTBB_Recessed,	TRUE,
			GT_VisualInfo,	VisualInfo,
			TAG_DONE );

		DrawBevelBox(XPrWindow->RPort, LEFTX, 152, 571, 10,
			GTBB_Recessed,	TRUE,
			GT_VisualInfo,	VisualInfo,
			TAG_DONE );

		SetAPen(XPrWindow->RPort, 0);
		RectFill(XPrWindow->RPort, LEFTX + 2, 153, 564 + LEFTX + 2, 160);
		SetAPen(XPrWindow->RPort, 7);

		if(g = CreateContext(&glist))
		{
			ng.ng_LeftEdge		= LEFTX + 24;
			ng.ng_TopEdge		= 167;
			ng.ng_Width			= 200;
			ng.ng_Height		= 11;
			ng.ng_GadgetText	= "Abort Entire Transfer";
			ng.ng_TextAttr		= &FontAttr;
			ng.ng_GadgetID		= 1;
			ng.ng_Flags			= PLACETEXT_IN;
			ng.ng_VisualInfo	= VisualInfo;

			Gadgets[0] =
			g = CreateGadget(BUTTON_KIND, g, &ng,
					TAG_DONE);

			ng.ng_LeftEdge		= LEFTX + 344;
			ng.ng_GadgetText	= "Skip Current File";
			ng.ng_GadgetID		= 2;

			Gadgets[1] =
			g = CreateGadget(BUTTON_KIND, g, &ng,
					TAG_DONE);

			AddGList(XPrWindow, glist, 0, -1, NULL);
			RefreshGList(glist, XPrWindow, NULL, -1);
			GT_RefreshWindow(XPrWindow, NULL);
		}

		return(TRUE);
	}

	return(FALSE);
}

VOID CloseXPrWindow()
{
	if(XPrWindow)
	{
		FreeGadgets(XPrWindow->FirstGadget);

		ReleaseWindow(Win1);
		ReleaseWindow(Win2);

		CloseWindow(XPrWindow);
		XPrWindow = NULL;
	}
}

/*
"r"  (read-only)
"w"  (write-only, create new file if none exists, truncate existing file)
"a"  (write-only, create new file if none exists, append to existing file)
"r+" (same as "r", but may also write)
"w+" (same as "w", but may also read)
"a+" (same as "a", but may also read).
*/
LONG __saveds __asm xpr_fopen(register __a0 char *file, register __a1 char *access)
{
	BPTR FH, lock;

	FH = NULL;
	switch(access[0])
	{
		case 'r':
			FH = Open(file, (access[1] == '+' ? MODE_READWRITE : MODE_OLDFILE));
			break;

		case 'w':
			if(access[1] == '+')
			{
				if(lock = Lock(file, ACCESS_WRITE))
				{
					UnLock(lock);
					DeleteFile(file);
				}
				FH = Open(file, MODE_READWRITE);
			}
			else
			{
				FH = Open(file, MODE_NEWFILE);
			}
			break;

		case 'a':
			if(lock = Lock(file, ACCESS_WRITE))
			{
				UnLock(lock);
				if(FH = Open(file, MODE_READWRITE))
				{
					if(Seek(FH, 0, OFFSET_END) == -1)
					{
						Close(FH);
						FH = NULL;
					}
				}
			}
			else
			{
				FH = Open(file, MODE_NEWFILE);
			}
			break;
	}
	return((LONG)FH);
}

LONG __saveds __asm xpr_fclose(register __a0 BPTR FH)
{
	UBYTE SomeBuffer[256];
	LONG Success;

	Success = NameFromFH(FH, SomeBuffer, 256);
	Close(FH);

	if(Success)
	{
		if(!GetFileSize(SomeBuffer))	DeleteFile(SomeBuffer);
	}

	return(1);
}

LONG __saveds __asm xpr_fread(register __a0 APTR buff, register __d0 LONG size, register __d1 LONG count, register __a1 BPTR FH)
{
	return(Read(FH, buff, size * count) / size);
}

LONG __saveds __asm xpr_fwrite(register __a0 APTR buff, register __d0 LONG size, register __d1 LONG count, register __a1 BPTR FH)
{
	return(Write(FH, buff, size * count) / size);
}

LONG __saveds __asm xpr_fseek(register __a0 BPTR FH, register __d0 LONG offset, register __d1 LONG origin)
{
	ULONG mode;

	switch(origin)
	{
		case 0:
			mode = OFFSET_BEGINNING;
			break;

		case 1:
			mode = OFFSET_CURRENT;
			break;

		case 2:
			mode = OFFSET_END;
			break;
	}

	if(Seek(FH, offset, origin) == -1)
		return(-1);
	else
		return(0);
}

LONG __saveds __asm xpr_finfo(register __a0 char *file, register __d0 LONG info)
{
	if(info == 1)
	{
		LONG size;

		size = GetFileSize(file);
		if(size < 0)	size = 0;

		return(size);
	}

	if(info == 2)	return(1);						/* allways binary */
}

LONG __saveds xpr_chkabort()
{
	struct IntuiMessage *imsg;
	struct Gadget *gadget;
	ULONG class;

	if(XPrWindow)
	{
		while((imsg = GT_GetIMsg(XPrWindow->UserPort)))
		{
		   class = imsg->Class;
			gadget= (struct Gadget *)imsg->IAddress;

			GT_ReplyIMsg(imsg);

			if(class == IDCMP_CLOSEWINDOW)	return(-1);	/* Abort transfer */
			if(class == IDCMP_GADGETUP)
			{
				if(gadget->GadgetID == 1)		return(-1);	/* Abort transfer */
				else									return(1);	/* Skip file */
			}
		}
	}
	return(0);
}

ULONG __saveds __asm xpr_sread(register __a0 char *buff, register __d0 LONG size, register __d1 LONG timeout)
{
#define MILLION 1000000
	ULONG	 signalset, sersig, winsig, timesig;
	ULONG	 length;

	if(!CarrierSet())	return(-1);
	if(!size)		return(0);

	length = 0;
	if(timeout < 1)
	{
		WriteSER->IOSer.io_Command = SDCMD_QUERY;
		DoIO(WriteSER);

		if(length = WriteSER->IOSer.io_Actual)
		{
			if(length > (ULONG)size)	length = (ULONG)size;

			ReadSER->IOSer.io_Length	= length;
			ReadSER->IOSer.io_Data		= buff;
			ReadSER->IOSer.io_Command	= CMD_READ;
			DoIO(ReadSER);
			length = ReadSER->IOSer.io_Actual;
		}
	}
	else
	{
		DoTime->tr_node.io_Command	= TR_ADDREQUEST;
		DoTime->tr_time.tv_secs		= (timeout > MILLION) ? timeout / MILLION : 0;
		DoTime->tr_time.tv_micro	= timeout % MILLION;

		ReadSER->IOSer.io_Command	= CMD_READ;
		ReadSER->IOSer.io_Data		= buff;
		ReadSER->IOSer.io_Length	= size;

		sersig	= 1 << ReadPortSER->mp_SigBit;
		timesig	= 1 << DoTime->tr_node.io_Message.mn_ReplyPort->mp_SigBit;
		winsig	= (XPrWindow) ? (1 << XPrWindow->UserPort->mp_SigBit) : 0;
		SetSignal(0, sersig | timesig);

		SendIO(ReadSER);
		SendIO(DoTime);

		FOREVER
		{
			signalset = Wait(sersig | timesig | winsig);

			if((signalset & winsig) && xpr_chkabort())
			{
				AbortIO(DoTime);
				WaitIO(DoTime);

				AbortIO(ReadSER);
				WaitIO(ReadSER);

				return(-1);
			}

			if((signalset & timesig) && CheckIO(DoTime))
			{
				WaitIO(DoTime);

				AbortIO(ReadSER);
				WaitIO(ReadSER);

				length = ReadSER->IOSer.io_Actual;
				goto bibi;
			}

			if((signalset & sersig) && CheckIO(ReadSER))
			{
				WaitIO(ReadSER);

				AbortIO(DoTime);
				WaitIO(DoTime);

				length = ReadSER->IOSer.io_Actual;
				goto bibi;
			}
		}
	}
bibi:
	return(CarrierSet() ? length : -1);
}

LONG __saveds __asm xpr_swrite(register __a0 char *buff, register __d0 LONG size)
{
	ULONG	 signalset, sersig, winsig;

	if(!CarrierSet())	return(-1);

	sersig	= 1 << WritePortSER->mp_SigBit;
	winsig	= (XPrWindow) ? (1 << XPrWindow->UserPort->mp_SigBit) : 0;

	WriteSER->IOSer.io_Length	= size;
	WriteSER->IOSer.io_Data		= buff;
	WriteSER->IOSer.io_Command	= CMD_WRITE;
	SendIO(WriteSER);

	FOREVER
	{
		signalset = Wait(sersig | winsig);

		if((signalset & winsig) && xpr_chkabort())
		{
			WaitIO(WriteSER);

			return(-1);
		}

		if((signalset & sersig) && CheckIO(WriteSER))
		{
			WaitIO(WriteSER);

			return(CarrierSet() ? 0 : -1);
		}
	}
}

LONG __saveds xpr_squery()
{
	LONG chars;

	chars = -1;

	ReadSER->IOSer.io_Command = SDCMD_QUERY;
	if(!DoIO(ReadSER))	chars = ReadSER->IOSer.io_Actual;
	ReadSER->IOSer.io_Command = CMD_READ;

	return(chars);
}

LONG __saveds xpr_sflush()
{
	LONG err;

	if(!CheckIO(ReadSER))
	{
		AbortIO(ReadSER);
		Wait(1 << (ReadPortSER->mp_SigBit));
	}
	GetMsg(ReadPortSER);
	ReadSER->IOSer.io_Error = 0;

	ReadSER->IOSer.io_Command = CMD_CLEAR;
	err = DoIO(ReadSER);
	ReadSER->IOSer.io_Command = CMD_READ;

	return(err);
}

LONG __saveds __asm xpr_setserial(register __d0 LONG Status)
{
#define ST_PARTYON	(1 << 0)
#define ST_PARTYODD	(1 << 1)
#define ST_7WIRE	(1 << 2)
#define ST_QBREAK	(1 << 3)
#define ST_RADBOOGIE	(1 << 4)
#define ST_SHARED	(1 << 5)
#define ST_EOFMODE	(1 << 6)
#define ST_XDISABLED	(1 << 7)
#define ST_PARTYMARKON	(1 << 8)
#define ST_PARTYMARK	(1 << 9)
#define ST_2BITS	(1 << 10)
#define ST_READ7	(1 << 11)
#define ST_WRITE7	(1 << 12)

	LONG rtn, i;
	STATIC LONG XprBauds[12] = { 110, 300, 1200, 2400, 4800, 9600, 19200, 31250,
		38400, 57600, 76800, 115200 };

	WriteSER->IOSer.io_Command = SDCMD_QUERY;
	DoIO(WriteSER);

	rtn = WriteSER->io_SerFlags & 0xFF;

	if(WriteSER->io_ExtFlags & SEXTF_MSPON)	rtn |= ST_PARTYMARKON;
	if(WriteSER->io_ExtFlags & SEXTF_MARK)		rtn |= ST_PARTYMARK;
	if(WriteSER->io_StopBits	== 2)				rtn |= ST_2BITS;
	if(WriteSER->io_ReadLen		== 7)				rtn |= ST_READ7;
	if(WriteSER->io_WriteLen	== 7)				rtn |= ST_WRITE7;

	for(i = 0 ; i < 12 ; i++)
	{
		if(WriteSER->io_Baud == XprBauds[i])
		{
			rtn |= (i << 16);
			break;
		}
	}

	if(Status != -1)
	{
		WriteSER->IOSer.io_Command	= SDCMD_SETPARAMS;
		WriteSER->io_SerFlags		= Status & 0xFF;
		WriteSER->io_ExtFlags		= 0;

		if(Status & ST_PARTYMARKON)	WriteSER->io_ExtFlags |= SEXTF_MSPON;
		if(Status & ST_PARTYMARK)		WriteSER->io_ExtFlags |= SEXTF_MARK;
		if(Status & ST_2BITS)			WriteSER->io_StopBits = 2;
		else									WriteSER->io_StopBits = 1;
		if(Status & ST_READ7)			WriteSER->io_ReadLen = 7;
		else									WriteSER->io_ReadLen = 8;
		if(Status & ST_WRITE7)			WriteSER->io_WriteLen = 7;
		else									WriteSER->io_WriteLen = 8;

		DoIO(WriteSER);

		ReadSER->io_SerFlags	= WriteSER->io_SerFlags;
		ReadSER->io_ExtFlags	= WriteSER->io_ExtFlags;
		ReadSER->io_StopBits	= WriteSER->io_StopBits;
		ReadSER->io_ReadLen	= WriteSER->io_ReadLen;
		ReadSER->io_WriteLen	= WriteSER->io_WriteLen;
	}

	return(rtn);
}

LONG __saveds __asm xpr_update(register __a0 struct XPR_UPDATE *Update)
{
	if(!XPrWindow)	return(0);

	if(Update)
	{
		if(Update->xpru_updatemask & XPRU_PROTOCOL)
			wprintf(XPrWindow->RPort, XLEFT, 18, "%-50.50ls", Update->xpru_protocol);

		if(Update->xpru_updatemask & XPRU_MSG)
			wprintf(XPrWindow->RPort, XLEFT, 31, "%-50.50ls", Update->xpru_msg);

		if(Update->xpru_updatemask & XPRU_ERRORMSG)
			wprintf(XPrWindow->RPort, XLEFT, 41, "%-50.50ls", Update->xpru_errormsg);

		if(Update->xpru_updatemask & XPRU_FILENAME)
			wprintf(XPrWindow->RPort, XLEFT, 54, "%-50.50ls", Update->xpru_filename);

		if(Update->xpru_updatemask & XPRU_FILESIZE)
		{
			wprintf(XPrWindow->RPort, XLEFT, 64, "%-50.50ld", Update->xpru_filesize);
			warnung = Update->xpru_filesize;
		}

		if(Update->xpru_updatemask & XPRU_BYTES)
		{
			wprintf(XPrWindow->RPort, XLEFT, 81, "%-13.13ld", Update->xpru_bytes);
			if(warnung > 0)
			{
				ULONG __chip Check = 0x5555AAAA;

				SetAfPt(XPrWindow->RPort, (UWORD *)&Check, 1);
				RectFill(XPrWindow->RPort, LEFTX + 2, 153, ((Update->xpru_bytes * 563) / warnung) + LEFTX + 3, 160);
				SetAfPt(XPrWindow->RPort, NULL, 0);
			}
		}

		if(Update->xpru_updatemask & XPRU_BLOCKS)
			wprintf(XPrWindow->RPort, XLEFT, 91, "%-13.13ld", Update->xpru_blocks);

		if(Update->xpru_updatemask & XPRU_BLOCKSIZE)
			wprintf(XPrWindow->RPort, XLEFT, 101, "%-13.13ld", Update->xpru_blocksize);

		if(Update->xpru_updatemask & XPRU_BLOCKCHECK)
			wprintf(XPrWindow->RPort, XLEFT, 111, "%-13.13ls", Update->xpru_blockcheck);

		if(Update->xpru_updatemask & XPRU_EXPECTTIME)
			wprintf(XPrWindow->RPort, XLEFT, 127, "%-13.13ls", Update->xpru_expecttime);

		if(Update->xpru_updatemask & XPRU_ELAPSEDTIME)
			wprintf(XPrWindow->RPort, XLEFT, 137, "%-13.13ls", Update->xpru_elapsedtime);

		if(Update->xpru_updatemask & XPRU_DATARATE)
			wprintf(XPrWindow->RPort, XRIGHT, 81, "%-13.13ld", Update->xpru_datarate);

		if(Update->xpru_updatemask & XPRU_CHARDELAY)
			wprintf(XPrWindow->RPort, XRIGHT, 91, "%-13.13ld", Update->xpru_chardelay);

		if(Update->xpru_updatemask & XPRU_PACKETDELAY)
			wprintf(XPrWindow->RPort, XRIGHT, 101, "%-13.13ld", Update->xpru_packetdelay);

		if(Update->xpru_updatemask & XPRU_PACKETTYPE)
			wprintf(XPrWindow->RPort, XRIGHT, 111, "%-13.13ls", Update->xpru_packettype);

		if(Update->xpru_updatemask & XPRU_ERRORS)
			wprintf(XPrWindow->RPort, XRIGHT, 127, "%-13.13ld", Update->xpru_errors);

		if(Update->xpru_updatemask & XPRU_TIMEOUTS)
			wprintf(XPrWindow->RPort, XRIGHT, 137, "%-13.13ld", Update->xpru_timeouts);
	}

	return(1);
}

LONG __saveds __asm xpr_unlink(register __a0 char *filename)
{
	return(DeleteFile(filename) ? 0 : -1);
}

LONG __saveds __asm xpr_getptr(register __d0 LONG type)
{
	return((type == 1 ? (LONG)Scr : -1));
}

LONG __saveds __asm xpr_ffirst(register __a0 char *buff, register __a1 char *pattern)
{
	struct Line *line;

	if(line = GetHead(&FileList))
	{
		strcpy(buff, line->text);
		warnung = GetFileSize(buff); /* fuer balken in window */
		return(1);
	}
	return(0);
}

LONG __saveds __asm xpr_fnext(register __d0 LONG oldstate, register __a0 char *buff, register __a1 char *pattern)
{
	struct Line *line;
	LONG i;

	SetAPen(XPrWindow->RPort, 0);
	RectFill(XPrWindow->RPort, LEFTX + 2, 153, 564 + LEFTX + 2, 160);
	SetAPen(XPrWindow->RPort, 7);

	i = 1;
	oldstate++;
	line = GetHead(&FileList);
	while(line && i++ < oldstate)	line = GetSucc(line);
	i--;

	if(i == oldstate && line)
	{
		strcpy(buff, line->text);
		warnung = GetFileSize(buff); /* fuer balken in window */
		return(oldstate);
	}

	return(0);
}

VOID InitXPrReq(VOID)
{
   XPrReq.xpr_filename	= NULL;
	XPrReq.xpr_fopen		= xpr_fopen;
	XPrReq.xpr_fclose		= xpr_fclose;
	XPrReq.xpr_fread		= xpr_fread;
	XPrReq.xpr_fwrite		= xpr_fwrite;
	XPrReq.xpr_sread		= xpr_sread;
	XPrReq.xpr_swrite		= xpr_swrite;
	XPrReq.xpr_sflush		= xpr_sflush;
	XPrReq.xpr_update		= xpr_update;
	XPrReq.xpr_chkabort	= xpr_chkabort;
	XPrReq.xpr_gets		= NULL;	 /* brauchen keine string-req */
	XPrReq.xpr_setserial	= xpr_setserial;
	XPrReq.xpr_ffirst		= xpr_ffirst;
	XPrReq.xpr_fnext		= xpr_fnext;
	XPrReq.xpr_finfo		= xpr_finfo;
	XPrReq.xpr_fseek		= xpr_fseek;
   XPrReq.xpr_data		= NULL;
	XPrReq.xpr_extension	= 4;
	XPrReq.xpr_options	= NULL;	/* brauchen kein opt-window */
	XPrReq.xpr_unlink		= xpr_unlink;			/* Extension 2 */
	XPrReq.xpr_squery		= xpr_squery;			/* Extension 3 */
	XPrReq.xpr_getptr		= xpr_getptr;			/* Extension 4 */
	XPrReq.xpr_chkmisc	= NULL;					/* brauchen das nicht... */
}
