/* consolestuff.c */

/*#include "exec/types.h"
#include "intuition/intuition.h"
#include "exec/memory.h"
#include "functions.h"*/
#include "cwtoy.h"

extern struct IOStdReq *CreateStdIO();
extern struct MsgPort *CreatePort();

struct ConIOBlocks {
	struct IOStdReq *writeReq;	/* I/O write request */
	struct IOStdReq *readReq;	/* I/O read request */
    struct MsgPort *tpr;	/* pointer to ReplyPort */
							/* for the console read */
};

struct ConIOBlocks *
CreateConsole(window)
	struct Window *window;
{
	struct ConIOBlocks *c;
	struct MsgPort *tpw;
	int error;
	
	c = (struct ConIOBlocks *)AllocMem((LONG)sizeof(struct ConIOBlocks),MEMF_CLEAR);
	
	if (c == 0) /* out of RAM */
		goto cleanup1;
		
	tpw = CreatePort(0,0);  /* reply port for write */
	if (tpw == 0) 
		goto cleanup2;
	
	c->tpr = CreatePort(0,0); /* reply port for read */
	if (c->tpr ==0)
		goto cleanup3;
		
	c->writeReq = CreateStdIO(tpw);
	if (c->writeReq == 0)
		goto cleanup4;
	
	c->readReq = CreateStdIO(c->tpr);
	if (c->readReq == 0)
		goto cleanup5;
		
	c->writeReq->io_Data = (APTR)window;
	c->writeReq->io_Length = sizeof(struct Window);
	
	error = OpenDevice("console.device",0,c->writeReq,0);
	if (error != 0)
		goto cleanup6;	/* cannot open the console! */
		
	c->readReq->io_Device = c->writeReq->io_Device;
	c->readReq->io_Unit   = c->writeReq->io_Unit;
	/* Above copies the I/O request block from a */
	/* block initialized from a successful open. */
	/* Means both read and write are talking to the */
	/* same instance of a console.   */
	return(c);	/* pointer to the ConIOBlocks */
				/* containing both read and */
				/* write control blocks. */
cleanup6:
	DeleteStdIO(c->readReq);
cleanup5:
	DeletePort(c->tpr);
cleanup4:
	DeleteStdIO(c->writeReq);
cleanup3:
	DeletePort(tpw);
cleanup2:
	FreeMem(c, sizeof(struct ConIOBlocks));
cleanup1:
	return(NULL);
}

DeleteConsole(c)
	struct ConIOBlocks *c;
{
	struct MsgPort *mp;
	AbortIO(c->readReq);	/* abort any read in progress */
	CloseDevice(c->writeReq);  /*close the console device */
	
	mp = c->writeReq->io_Message.mn_ReplyPort;
	
	DeleteStdIO(c->writeReq);
	DeletePort(mp);
	
	mp = c->readReq->io_Message.mn_ReplyPort;
	
	DeleteStdIO(c->readReq);
	DeletePort(mp);
	
	FreeMem(c, sizeof(struct ConIOBlocks));
	return(0);
}

#define CONREAD c->readReq
#define CONWRITE c->writeReq

/* ask console, asynchronously, to read a character */

EnqueueRead(c, location)
    struct ConIOBlocks *c;
	char *location;
{
	struct IOStdReq *conr;
	conr = c->readReq;
	
	conr->io_Command = CMD_READ;
	conr->io_Length =1;
	conr->io_Data = (APTR) location;
			/* buffer into which to store data read */
	SendIO(conr);
			/* asynchronous posting of a read request */
}

/* write a specified number of characters from a buffer to
 * a particular console device.
 */
WriteConsole(c, data, length)
	struct ConIOBlocks *c;
	char *data;
	WORD length;
{
	struct IOStdReq *conw;
	conw = c->writeReq;
	
	conw->io_Command = CMD_WRITE;	/* what to do */
	conw->io_Length = length;		/* how many characters */
	conw->io_Data = (APTR) data;	/* where it is */
	DoIO(conw);		/* synchronous... wait until console */
					/* task has accepted the data  before */
					/* going on with something else.    */
}

int
CGetCharacter(c, wait)
		/* If wait is TRUE, wait until a character 			*/
		/* is typed.  Return the character as the result. 	*/
		/* If wait is FALSE, return the character value		*/
		/* if a character is ready; otherwise return -1.	*/
		
	struct ConIOBlocks *c;
	BOOL wait;
{
	struct MsgPort *mp;
	struct IOStdReq *conr;
	char *dataAddr;
	int temp;
	
	mp = c->tpr;	/* find the read reply port */
	if(wait)
	{
		WaitPort(mp);
	}
	conr = (struct IOStdReq *) GetMsg(mp);
	if(conr == 0)
	{
		return(-1);
	}
	else
	{
		dataAddr = (char *)conr->io_Data;
		temp = *dataAddr; 	/* get the value */
		EnqueueRead(c, dataAddr);  /* continue the read */
		return(temp);
	}
}	/* end of CGetChar */ 
