/* MRBackup Console Routines
 * Filename:	Console.c
 * Date:		11/22/87
 *
 * Console I/O Routines from Rob Peck's "Programmer's Guide to the Amiga".
 */

#include "MRBackup.h"

ConIOBlocks *
CreateConsole(window)
	struct Window *window;
{
	ConIOBlocks *c;
	struct MsgPort *tpw;

	if (!(c = AllocMem((long) sizeof(ConIOBlocks), 
						MEMF_CLEAR | MEMF_PUBLIC)))
		goto cleanup1;

	if (!(tpw = CreatePort(0L, 0L)))
		goto cleanup2;

	if (!(c->tpr = CreatePort(0L, 0L)))
		goto cleanup3;

	if (!(c->writeReq = CreateStdIO(tpw)))
		goto cleanup4;

	if (!(c->readReq = CreateStdIO(c->tpr)))
		goto cleanup5;

	c->writeReq->io_Data = (APTR)window;
	c->writeReq->io_Length = sizeof(struct Window);

	if (OpenDevice("console.device", 0L, c->writeReq, 0L))
		goto cleanup6;

	/* Read and write are both talking to the same instance of a console. */
	c->readReq->io_Device = c->writeReq->io_Device;
	c->readReq->io_Unit   = c->writeReq->io_Unit;
	return c;

cleanup6:
	DeleteStdIO(c->readReq);
cleanup5:
	DeletePort(c->tpr);
cleanup4:
	DeleteStdIO(c->writeReq);
cleanup3:
	DeletePort(tpw);
cleanup2:
	FreeMem(c, (long) sizeof(ConIOBlocks));
cleanup1:
	return NULL;
}

int
DeleteConsole(c)
	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, (long) sizeof(ConIOBlocks));
	return 0;
}

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

void
EnqueueRead(c, location)
	ConIOBlocks *c; char *location;
{
	struct IOStdReq *conr;

	conr = CONREAD;
	conr->io_Command = CMD_READ;
	conr->io_Length = 1;
	conr->io_Data = (APTR) location;
	SendIO(conr);				/* asynchronous read request */
}

/* Write a specified number of characters from a buffer to a particular
 * console device. 
 */

void
ConWrite(c, data, length)
	ConIOBlocks *c; char *data; WORD length;
{
	struct IOStdReq *conw;

	if (length == 0) length = strlen(data);
	conw = CONWRITE;
	conw->io_Command = CMD_WRITE;
	conw->io_Length = length;
	conw->io_Data = (APTR) data;
	DoIO(conw);					/* synchronous write request */
}

/* Get a character from the console, with optional wait.
 * Called with:
 *		c:		console control structure
 *		wait:	0 => asynchronous read (no wait)
 *				1 => synchronous read (wait)
 * Returns:
 *		character or -1 (async and no character)
 */
int
CGetCharacter(c, wait)
	ConIOBlocks *c; BOOL wait;
{
	struct MsgPort *mp;
	struct IOStdReq *conr;
	char *dataAddr;
	int temp;

	mp = c->tpr;
	if (wait) {
		WaitPort(mp);
	}
	conr = (struct IOStdReq *) GetMsg(mp);
	if (conr == NULL)
		return -1;
	else {
		dataAddr = (char *)conr->io_Data;
		temp = *dataAddr;			/* get the value */
		EnqueueRead(c, dataAddr);	/* continue the read */
		return temp;
	}
}

#ifdef DEBUG
DebugWrite(msg)
	char *msg;
{
	ConWrite(debugConsole, msg, strlen(msg));
}
#endif

/* Write string to progress window. */

WriteConsole(msg)
	char *msg;
{
	ConWrite(progressConsole, msg, strlen(msg));
}
