/*
con.h
Contains info and code necessary for opening the console device for
input and output.
Functions in the file include InitConsole(), CloseConsole(),
PutChar(), PutString() PutFormat(),
CheckKey(),GetKey(),
CursorXY(),PutSequence(),GetLine();
*/

#include <exec/types.h>
#include <stdio.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <exec/memory.h>
#include <exec/io.h>
#include <exec/devices.h>
#include <graphics/gfx.h>
#include <graphics/copper.h>
#include <graphics/text.h>
#include <graphics/gels.h>
#include <graphics/layers.h>
#include <graphics/gfxbase.h>
#include <graphics/regions.h>
#include <devices/keymap.h>
#include <hardware/blit.h>
#include <functions.h>

#define CSI    0x9b                /* Command Sequence Introducer */

UBYTE
   readbuf[2],
   CheckKey(),GetKey();

struct MsgPort *ConPort,*ReadPort;

struct IOStdReq *WriteMsg,*ReadMsg;


/*    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.
*/

  struct IOStdReq *
InitConsole(userwindow)

  struct Window *userwindow;
{


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

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

if (!(WriteMsg= CreateStdIO(ConPort)))
     goto quit4;

if (!(ReadMsg= CreateStdIO(ReadPort)))
     goto quit3;

WriteMsg->io_Data= (APTR) userwindow;
WriteMsg->io_Length = sizeof(*userwindow);
if (OpenDevice("console.device",NULL,WriteMsg,NULL))
     goto quit2;

WriteMsg->io_Command = CMD_WRITE;

ReadMsg->io_Device = WriteMsg->io_Device;
ReadMsg->io_Unit = WriteMsg->io_Unit;
ReadMsg->io_Command = CMD_READ;
ReadMsg->io_Data = readbuf;
ReadMsg->io_Length = 1;


SendIO(ReadMsg);  /* ask for keypresses */
return(ReadMsg);     /* Ports successfully opened */

quit1: CloseDevice(WriteMsg);
quit2: DeleteStdIO(ReadMsg);
quit3: DeleteStdIO(WriteMsg);
quit4: RemPort(ReadPort);
quit5: RemPort(ConPort);
       return((long)FALSE);

}    /* End of InitConsole(userwindow) */

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

CloseConsole()

{
  CloseDevice(WriteMsg);
  DeleteStdIO(ReadMsg);
  DeleteStdIO(WriteMsg);
  RemPort(ReadPort);
  RemPort(ConPort);
 }


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

PutChar(character)
  UBYTE character;
 {                                /* io_Command is always WRITE */
   if (character == 8)
    {
      PutString("\x08\x20\x08");	/* backspace is <bs> <sp> <bs> */
     }
   else
    {
      WriteMsg->io_Data =  &character;
      WriteMsg->io_Length = 1;
      DoIO(WriteMsg);
     }
  }

/************* 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.					*/

#define PRINTBUFSIZE	128
#define squirtchar	(UBYTE)255

PutFormat(character)
UBYTE character;
{  
  extern struct IOStdReq *WriteMsg;

  static UBYTE buffer[PRINTBUFSIZE];
  static int count;

  if (character == squirtchar)		/* then squirt it out	*/
    {
      WriteMsg->io_Data = buffer;
      WriteMsg->io_Length = count;	/* subtract \xff count	*/
      DoIO(WriteMsg);
      count = 0;		/* prepare for the next string */
     }
  else if (count == (PRINTBUFSIZE - 1))	/* then buffer is full	*/
    {
      WriteMsg->io_Data = buffer;
      WriteMsg->io_Length = count;
      DoIO(WriteMsg);
      count = 1;
      buffer[count] = character;	/* start a new string	*/
     }
  else
   { if (character == 8)		/* if backspace */
     { buffer[count++] = 8;
       buffer[count++] = 32;	/* put <BS> <SP> <BS> */
      }
     buffer[count++] = character;
    }
  }

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

PutString(string)
  UBYTE *string;
 {                             /* io_Command is always WRITE */
   extern struct IOStdReq *WriteMsg;
   WriteMsg->io_Data = (APTR) string;
   WriteMsg->io_Length = -1;
   DoIO(WriteMsg);
  }

/********************* Move cursor to x,y ************************/

CursorXY(x,y)     /* note: x,y is column, row */
  int x,y;
 {
    UBYTE *rowbuf[3], *colbuf[3];
   format(PutChar,"\x9b%d;%dH",y,x);
  }


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

PutSequence(string)  /* this routine appends your string onto */
UBYTE *string;                /* 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 ******************/


GetLine(prompt,inputbuf)

 UBYTE *prompt, *inputbuf;

 {
    UBYTE c;
    int i=0;
   if (prompt)
   PutString(prompt);

  inputbuf[i]=0;             
  while ((c=GetKey()) != 13)   /* until c/r */
  switch (c)
   {
     case 3:           /* ^C aborts */
     case 24:          /* ^X aborts */
      return FALSE;
     case 8:           /* backspace */
      if (i>0)
       { inputbuf[--i] = 0;
         PutChar(8);        /* do <BS>,<SP>,<BS> sequence */
         PutChar(32);
         PutChar(8);
        }
      break;
     default:
      if ((c >= ' ') && (c < 127))
       { inputbuf[i++] = c;
         inputbuf[i] = 0;
         PutChar(c);
        }
    }
   PutChar('\n');
   return(TRUE);  /* the name contained herein is valid */
  }

