/*
ConsoleIO.c
Contains info and code necessary for opening the console device for
input and output.
Functions in the file include	InitConsoleIO(), CloseConsoleIO(),
											PutChar(), PutString() PutFormat(),
											CheckKey(),GetKey(),
											CursorXY(),PutSequence(),GetLine();
*/

#include <exec/types.h>
#include <stdio.h>
#include <exec/io.h>
#include <intuition/intuition.h>
#include <functions.h>

#define CSI    		'\x9b'  /* Command Sequence Introducer */
#define	PRINTBUFSIZE	130
#define	SQUIRTCHAR		'\xff'
#define	MODEHEX			-1L

extern long scan;
extern char sendstring[];
extern char portname[];
extern char outmessage[];
extern char command[];
extern int connected;
static UBYTE buffer[PRINTBUFSIZE];
static int count;

static UBYTE readbuf[8];

static struct MsgPort *ConPort  = NULL;
static struct MsgPort *ReadPort = NULL;

static struct IOStdReq *WriteMsg = NULL;
static struct IOStdReq *ReadMsg  = NULL;

/*    Set Up the IO Paths:
      Returns pointer to input (keyboard) IOStdReq structure or zero.
      The IOStdReq structure may be used in a wait() command.
     You must have the address of your window structure to open the
     console.
*/


/******************** Close Up the Console *************************/

void CloseConsoleIO()

{
   register struct IOStdReq *r = ReadMsg;
   register struct IOStdReq *w = WriteMsg;

   if ( w != NULL )
     {
        CloseDevice( w );
        DeleteStdIO( w );
        WriteMsg = NULL;
     }
   if ( r != NULL )
     {
        DeleteStdIO( r );
        ReadMsg = NULL;
     }
   if ( ReadPort != NULL )
     {
        DeletePort(ReadPort);
        ReadPort = NULL;
     }
   if ( ConPort != NULL )
     {
        DeletePort( ConPort);
        ConPort = NULL;
     }
 }

/*--------------------------------------------------------*/
/*	GetConsoleSigBit: Return console signal bit	  */
/*--------------------------------------------------------*/

/*
int GetConsoleSigBit()
{
   return ReadMsg->io_Message.mn_ReplyPort->mp_SigBit; 
}
*/

/*--------------------------------------------------------*/
/*	InitConsole: return read request pointer	  */
/*--------------------------------------------------------*/

struct IOStdReq *InitConsoleIO(userwindow, rd, wr)
struct IOStdReq **rd;
struct IOStdReq **wr;
struct Window *userwindow;
{

   register struct IOStdReq *r;
   register struct IOStdReq *w;

   if ( (ConPort = CreatePort("writeport",NULL)) == NULL)
       return(NULL);

   if ( (ReadPort = CreatePort("readport",NULL)) == NULL)
       goto badopen;

   if ( (WriteMsg = CreateStdIO(ConPort)) == NULL)
       goto badopen;

   if ( (ReadMsg = CreateStdIO(ReadPort)) == NULL)
       goto badopen;

   r = ReadMsg;
   w = WriteMsg;
	*rd = r;
	*wr = w;
	printf("write port at %lx\n",w);
   w->io_Data= (APTR) userwindow;
   w->io_Length = sizeof(*userwindow);
   if (OpenDevice("console.device", NULL, w, NULL) )
       goto badopen;

   w->io_Command = CMD_WRITE;

   r->io_Device = w->io_Device;
   r->io_Unit = w->io_Unit;
   r->io_Command = CMD_READ;
   r->io_Data = (APTR)readbuf;
   r->io_Length = 1;

   SendIO(r);  /* ask for keypresses */
   count = 0;
   return( r );/* Ports successfully opened */

badopen:
   CloseConsoleIO();
   return NULL;   

}    /* End of InitConsole(userwindow) */


/************* develop a string, then print it all at once **************/

/*  This function is designed to be used with Manx's format() function  */
/*  Usage: format(PutFormat,format_string...);				*/
/*  Your calls must have one added character at the end			*/
/*  of the format_string-- 255 (-1). Use \xff.				*/
/*  This tells PutFormat to go print the string it has been building.	*/
/*  Make sure your format_string ends with '\xff', otherwise		*/
/*  the string won't print properly.					*/

void PutFormat(character)
register UBYTE character;
{  
  register struct IOStdReq *w = WriteMsg;

	if ( (character == SQUIRTCHAR) || (count >= PRINTBUFSIZE - 3) ) {
		w->io_Data = (APTR)buffer;
		w->io_Length = count;	/* subtract \xff count	*/
		buffer[count] = '\0';
		if( connected ) {
			send_rexx_msg(portname, command, buffer );
			}
		else
			DoIO( w );
		count = 0;
		}
  if ( character != SQUIRTCHAR )
     {    
	buffer[count++] = character;
	if (character == '\b')		/* if backspace */
	  {
	    buffer[count++] = ' ';	/* put <BS> <SP> <BS> */
	    buffer[count++] = character;
	  }
     }
 }

/***************** Put a character to screen *********************/

void PutChar(character)
  UBYTE character;
 {
   register struct IOStdReq *w = WriteMsg;
                                /* io_Command is always WRITE */
   if ( count )
      PutFormat( SQUIRTCHAR );

   if (character == '\b')
    {
      w->io_Data = (APTR) "\b \b";
      w->io_Length = 3;
      DoIO( w );
     }
   else
    {
      w->io_Data = (APTR) &character;
      w->io_Length = 1;
      DoIO( w );
     }
  }

/*********** Put a null-terminated string to screen ****************/

void PutString(string)
  UBYTE *string;
 {
  register struct IOStdReq *w = WriteMsg;
                             /* io_Command is always WRITE */
   if ( count )
      PutFormat( SQUIRTCHAR );

   w->io_Data = (APTR) string;
   w->io_Length = -1;
   DoIO( w );
  }

/********************* Move cursor to column,row **************/

void CursorXY(x, y)     /*  note: x,y is column, row */
int x, y;
{
	char curstring[8];
	struct parm {
		int row;
		int col;
		}	 parms;

	parms.row = y;
	parms.col = x;

	if ( !( (1 <= y && y <= 22)
			&&(1 <= x && x <= 79) ))
		{
		printf("Bad Cursor x=%d, y= %d\n\xFF", parms.row, parms.col );
		parms.row = 1;
		parms.col = 1;
		}

	sprintf(curstring, "\x9B%d;%dH", parms.row, parms.col);
	PutString(curstring);
}

/**************** Print an escape sequence ********************

void PutSequence(string)  / *comment this routine appends your string onto * /
UBYTE *string;            / *comment a CSI, and prints it to console * /
 {
   PutChar(CSI);
   PutString(string);
  }
  *************/

/***************** If key pressed, get it: else return **************/

UBYTE CheckKey()

 {
    UBYTE temp;
   if (GetMsg(ReadPort) == NULL)
       return 0;
   temp = readbuf[0];
   SendIO( ReadMsg );
   return(temp);
  }

/************** Wait as long as necessary for keypress **************/

UBYTE GetKey()

 {
   UBYTE temp;

   while (GetMsg(ReadPort) == NULL)
      WaitPort(ReadPort);
   temp = readbuf[0];
   SendIO( ReadMsg );
   return temp;
  }

/*************** Get a line of input from keyboard ****************/


BOOL GetLine(prompt,inputbuf)

 UBYTE *prompt;
 register UBYTE *inputbuf;

 {
   UBYTE c;
   int i=0;

   if (prompt)
      PutString(prompt);

   inputbuf[ i ] = '\0';             
   while ( (c=GetKey()) != '\r')   /* until c/r */
     switch (c)
       {
         case 3:           /* ^C aborts */
         case 24:          /* ^X aborts */
             return FALSE;
         case '\b':           /* backspace */
             if (i>0)
               {
                 inputbuf[--i] = '\0';
                 PutString( "\b \b" );
               }
             break;
         default:
             if ((c >= ' ') && (c < '\x7f'))
               {
 		 inputbuf[i++] = c;
		 inputbuf[i] = '\0';
		 PutChar(c);
	       }
        }
   PutChar('\n');
   return ( inputbuf[0] != '\0' );
  }
/*************************************/
