#include "term.h"

struct NewScreen ns = 
{
	0,0,640,200,2,
	0,1,
	HIRES,
	CUSTOMSCREEN,
	NULL,
	"Term Screen",
	NULL, NULL
};
	
struct NewWindow nw = 
{
	0,0,640,200,
	0,1,
	MENUPICK|VANILLAKEY|REQSET|GADGETUP|GADGETDOWN,
	ACTIVATE|BORDERLESS|NOCAREREFRESH,
	NULL,
	NULL,
	NULL,
	NULL,
	NULL,
	100,50,
	640,200,
	CUSTOMSCREEN
};
	
struct MsgPort  *WritePort, *ReadPort;
struct IOExtSer *WriteReq,  *ReadReq;
struct timerequest  TimerIO;
struct Window *w;
struct Screen *s;
struct RastPort *rp;
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;	
ULONG  ReadSignal, ScreenSignal, TimeSignal;
UBYTE  ReadData[2000];
USHORT BottomLine = (200 - 2);
USHORT Col = 0;
USHORT HDX = 0;
UBYTE  SPC = ' ';

void CleanUp(char *msg)
{
	if (msg)
		printf("%s\n", msg);
		
        CloseDevice((struct IORequest *)&TimerIO);
   	DeletePort(TimerIO.tr_node.io_Message.mn_ReplyPort);
	
	if (WriteReq)
	{
		CloseDevice((struct IORequest *)WriteReq);
		DeleteExtIO((struct IORequest *)WriteReq);
	}
	if (WritePort)
		DeletePort(WritePort);
		
	if (ReadReq)
	{
		CloseDevice((struct IORequest *)ReadReq);
		DeleteExtIO((struct IORequest *)ReadReq);
	}
	if (ReadPort)
		DeletePort(ReadPort);
		
	if (w)
	{
		ClearMenuStrip(w);
		CloseWindow(w);
	}
	if (s)
		CloseScreen(s);
	exit(0);
}

void WriteSerial(char *Msg, int cMsg)
{
	WriteReq->IOSer.io_Data   = (APTR)Msg;
	WriteReq->IOSer.io_Length = cMsg;
	DoIO((struct IORequest *)WriteReq);
}

void ScrollUp(void)
{
	ScrollRaster(rp, 0, 8, 0, 0, 639, 199);
	Move(rp, 0, BottomLine);
	Col = 0;
}

void Print(char c)
{
	c &= 0x7f;
	switch (c)
	{
		case '\b':
		if (Col)
		{
			Col--;
			Move(rp, Col * 8, BottomLine);
			Text(rp, &SPC, 1);
			Move(rp, Col * 8, BottomLine);
		}
		break;
		
		case '\r':
		Col = 0;
		Move(rp, 0, BottomLine);
		break;
	
		case '\n':
		Col = 0;
		ScrollUp();
		break;
		
		default:
		Text(rp, &c, 1);
		if (++Col > 79)
			ScrollUp();
		break;
	}
}

void Prints(char *Msg)
{
	while (*Msg)
		Print(*Msg++);
}


void ProcessMenu(USHORT code)
{
	switch (MENUNUM(code))
	{
		case PROJECTMENU:
		if (ITEMNUM(code) == PROJECTQUIT)
			CleanUp(0);
		else if (ITEMNUM(code) == PROJECTCONFIG)
			Config(w);
		break;
		
		case TRANSFERMENU:
		if (ITEMNUM(code) == TRANSFERDOWN)
			DownLoad();
		if (ITEMNUM(code) == TRANSFERUP)
			UpLoad();
		break;
	}
}

void main(void)
{
	struct IntuiMessage *message;
	ULONG  class;
	USHORT code;
	UBYTE  c;

   	if (OpenDevice( TIMERNAME
	              , (long)UNIT_VBLANK
	              , (struct IORequest *)&TimerIO
		      , 0L
		      ) != 0)
	{
		printf("Cannot open timer device\n");
		return;
	}
   	TimerIO.tr_node.io_Message.mn_ReplyPort = CreatePort("timer", 0);
	TimeSignal = 1L << 
	 	TimerIO.tr_node.io_Message.mn_ReplyPort->mp_SigBit;
		
	/****************************************************/
		
	WritePort = CreatePort("SerWrite", 0);
	if (WritePort == NULL)
		exit(100);
	WriteReq = (struct IOExtSer *)CreateExtIO(WritePort,
	                               sizeof(struct IOExtSer));
	if (WriteReq == NULL)
		CleanUp("Cannot open Write Request");
	WriteReq->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
	if (OpenDevice( SERIALNAME
	              , 0
		      , (struct IORequest *)WriteReq
		      , 0
		      ))
		CleanUp("Cannot Open serial device for Write");
	WriteReq->IOSer.io_Command = CMD_WRITE;
	WriteReq->io_SerFlags = SERF_SHARED|SERF_XDISABLED;
		
	/****************************************************/
		
	ReadPort = CreatePort("SerRead", 0);
	if (ReadPort == NULL)
		exit(100);
	ReadReq = (struct IOExtSer *)CreateExtIO(ReadPort,
	                               sizeof(struct IOExtSer));
	if (ReadReq == NULL)
		CleanUp("Cannot open Read Request");
	ReadReq->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
	if (OpenDevice( SERIALNAME
	              , 0
		      , (struct IORequest *)ReadReq
		      , 0
		      ))
		CleanUp("Cannot Open serial device for Read");
	ReadSignal = 1L << ReadPort->mp_SigBit;
		
    	ReadReq->io_SerFlags       = SERF_SHARED | SERF_XDISABLED;
    	ReadReq->IOSer.io_Length   = 1;
    	ReadReq->IOSer.io_Data     = (APTR) &ReadData[0];
        ReadReq->io_Baud           = 1200;
        ReadReq->io_ReadLen        = 8;
        ReadReq->io_WriteLen       = 8;
        ReadReq->io_CtlChar        = 0x11130000L;
        ReadReq->io_RBufLen        = 1024;
        ReadReq->IOSer.io_Command  = SDCMD_SETPARAMS;

        DoIO((struct IORequest *)ReadReq);
        ReadReq->IOSer.io_Command  = CMD_READ;
	SendIO((struct IORequest *)ReadReq);
	
	/****************************************************/
		
	GfxBase = OpenLibrary("graphics.library",0);
	if (GfxBase == NULL)
		CleanUp("Cannot open graphics lib");
	IntuitionBase = OpenLibrary("intuition.library",0);
	if (IntuitionBase == NULL)
		CleanUp("Cannot open intuition lib");
		
	s = OpenScreen(&ns);
	if (s == NULL)
		CleanUp("Cannot open screen");
	nw.Screen = s;
	w = OpenWindow(&nw);
	if (w == NULL)
		CleanUp("Cannot Open Window");
	ScreenSignal = 1L << w->UserPort->mp_SigBit;
		
	SetMenuStrip(w, &Menus[0]);
	rp = w->RPort;
	Move(rp, 0, BottomLine);
	SetAPen(rp, 1);
		
	for (;;)
	{
		Wait(ScreenSignal|ReadSignal);
		while (CheckIO((struct IORequest *)ReadReq))
		{
			WaitIO((struct IORequest *)ReadReq);
			c = ReadData[0] & 0x7f;
			Print(c);
			SendIO((struct IORequest *)ReadReq);
		}
		     
		while (message = (struct IntuiMessage *)
		                 GetMsg(w->UserPort))
		{
			class = message->Class;
			code  = message->Code;
			ReplyMsg((struct Message *)message);
			if (class == VANILLAKEY)
			{
				c = code & 0x7f;
				if (HDX)
					Print(c);
				if (c == '\n')
					c = '\r';
				WriteSerial(&c, 1);
			}
			if (class == MENUPICK)
				ProcessMenu(code);
		}
	}			

}		

