#include "exec/types.h"
#include "exec/io.h"
#include "exec/memory.h"

#include "graphics/gfx.h"
#include "hardware/dmabits.h"
#include "hardware/custom.h"
#include "hardware/blit.h"
#include "graphics/gfxmacros.h"
#include "graphics/copper.h"
#include "graphics/view.h"
#include "graphics/gels.h"
#include "graphics/regions.h"
#include "graphics/clip.h"
#include "exec/exec.h"
#include "graphics/text.h"
#include "graphics/gfxbase.h"

#include "devices/console.h"
#include "devices/keymap.h"

#include "libraries/dos.h"
#include "graphics/text.h"
#include "libraries/diskfont.h"
#include "intuition/intuition.h"

struct IOStdReq *consoleWriteMsg;   /* I/O request block pointer */
struct MsgPort *consoleWritePort;      /* a port at which to receive */    
char padding[] =
"123456789012345678901234567890123456789012345678901234567890123456789012345678901234";
     
extern struct MsgPort *CreatePort();
extern struct IOStdReq *CreateStdIO();

InitConsole(mywindow)
struct Window *mywindow;
{
int error;


consoleWritePort = CreatePort("my.con.write",0);
if(consoleWritePort == 0)
  {
  CloseConsole(3);
  return(FALSE);
  }

consoleWriteMsg =  CreateStdIO(consoleWritePort);
if(consoleWritePort == 0)
  {
  CloseConsole(2);
  return(FALSE);
  }

error = OpenConsole(consoleWriteMsg,mywindow);
if(error != 0)
  {
  CloseConsole(1);
  return(FALSE);
  }

return(TRUE);
}

/* open the console device */
OpenConsole(writerequest,window)

struct IOStdReq *writerequest;
struct Window *window;
{
int error;

writerequest->io_Data = (APTR) window;
writerequest->io_Length = 0;
error = OpenDevice("console.device", 0, writerequest, 0);
return(error);
}

CloseConsole(i)
int i;
{
switch( i )
   {
   case 1:
     CloseDevice(consoleWriteMsg);
   case 2:
     DeleteStdIO(consoleWriteMsg);
   case 3:
     DeletePort(consoleWritePort);
   }
}
 
/* Output a single character to a specified console */ 
ConPutChar(request,character)
struct IOStdReq *request;
char character;
{
request->io_Command = CMD_WRITE;
request->io_Data = (APTR)&character;
request->io_Length = 1;
DoIO(request);
  /* command works because DoIO blocks until command is
   * done (otherwise pointer to the character could become
   * invalid in the meantime).
   */
return(0);
}
 
/* Output a NULL-terminated string of characters to a console */ 
ConPutStr(request,string)
struct IOStdReq *request;
char *string;
{
request->io_Command = CMD_WRITE;
request->io_Data = (APTR)string;
request->io_Length = -1;  /* tells console to end when it
                          * sees a terminating zero on
                          * the string. */
DoIO(request);
return(0);
     }
 
/* Output a Fixed-length string of characters to a console */ 
ConWrite(string,num)
char string[];
int num;
{
int i;

for (i = 0; i < num; i++)
    {
    if (string[i] == 13)
       string[i]=10;
    else
       if (string[i] == 10)
          string[i]=13;
    }

consoleWriteMsg->io_Command = CMD_WRITE;
consoleWriteMsg->io_Data = (APTR)string;
consoleWriteMsg->io_Length = num;  /* tells console to end when it
                          * sees a terminating zero on
                          * the string. */
DoIO(consoleWriteMsg);
return(0);
}
     
/*************************************************
*  function to output ascii chars to window
*************************************************/

emit(c)
char c;
{
if (c == 10)
   c = 13;
else if (c == 13)
        c = 10;

if (c == 8)
   {
   ConPutChar(consoleWriteMsg,8);
   ConPutChar(consoleWriteMsg,32);
   }

if (c != 14) /* strip out ctrl n's */
   ConPutChar(consoleWriteMsg,c);

return(0);
}

/*************************************************
*  function to print a string
*************************************************/
emits(string)
char string[];
{
ConPutStr(consoleWriteMsg,string);
}

/*************************************************
*  function to take raw key data and convert it 
*  into ascii chars
**************************************************/
toasc(code)
USHORT code;
{
static int ctrl = FALSE;
static int shift = FALSE;
static int capsl = FALSE;
char c;
static char keys[75] = {
'`' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '0' , '-' ,
'=' , '\\' , 0 , '0' , 'q' , 'w' , 'e' , 'r' , 't' , 'y' , 'u' , 'i' , 'o' ,
'p' , '[' , ']' , 0 , '1' , '2' , '3' , 'a' , 's' , 'd' , 'f' , 'g' , 'h' ,
'j' , 'k' , 'l' , ';' , '\'' , 0 , 0 , '4' , '5' , '6' , 0 , 'z' , 'x' , 'c' , 'v' ,
'b' , 'n' , 'm' , 44 , '.' , '/' , 0 , '.' , '7' , '8' , '9' , ' ' , 8 ,
'\t' , 13 , 13 , 27 , 127 , 0 , 0 , 0 , '-' } ;

             switch ( code ) /* I didn't know about the Quilifier field when I write this */
                    {
                    case 98:  capsl = TRUE;  c = 0;  break;
                    case 226: capsl = FALSE; c = 0;  break;
                    case 99:  ctrl = TRUE;   c = 0;  break;
                    case 227: ctrl = FALSE;  c = 0;  break;
                    case 96:
                    case 97:  shift = TRUE;  c = 0;  break;
                    case 224:
                    case 225: shift = FALSE; c = 0;  break;
                   default:
                       if (code < 75)
                          c = keys[code];
                       else
                          c = 0;
                       }
         
/* add modifiers to the keys */

if (c != 0)
   {
   if (ctrl && (c <= 'z') && (c >= 'a'))
      c -= 96;
   else if (shift)
           {
      if ((c <= 'z') && (c >= 'a'))
         c -= 32;
      else
         switch( c )
               {
          case '[':  c = '{';  break;
          case ']':  c = '}';  break;
          case '\\': c = '|';  break;
          case '\'': c = '"';  break;
          case ';':  c = ':';  break;
          case '/':  c = '?';  break;
          case '.':  c = '>';  break;
          case ',':  c = '<';  break;
          case '`':  c = '~';  break;
          case '=':  c = '+';  break;
          case '-':  c = '_';  break;
          case '1':  c = '!';  break;
          case '2':  c = '@';  break;
          case '3':  c = '#';  break;
          case '4':  c = '$';  break;
          case '5':  c = '%';  break;
          case '6':  c = '^';  break;
          case '7':  c = '&';  break;
          case '8':  c = '*';  break;
          case '9':  c = '(';  break;
          case '0':  c = ')';  break;
          default:
          } /* end switch */
      } /* end shift */
   else if (capsl && (c <= 'z') && (c >= 'a'))
           c -= 32;
   } /* end modifiers */
   return(c);
} /* end of routine */

