/* Keyboard.c

   by Fabbian G. Dufoe, III
   This is a public domain file.  You may use it any way you wish.

   The functions in this file take an Intuition RAWKEY class message and
   return the value of the key which was pressed.  For standard ASCII
   characters ReadKey() returns the character.  For function keys it returns
   a zero and places a code representing the key in a buffer supplied by the
   calling program.  The codes are defined in Keys.h.
*/

#include "Keyboard.h"


struct Device *ConsoleDevice = NULL;
static struct IOStdReq ConsoleMsg;


void
CloseReadConsole()
/* FUNCTION
      This function closes the Console Device opened by OpenReadConsole().
      If the Console Device was not successfully opened CloseReadConsole()
      will return without doing anything.

   INPUT
      None

   RESULTS
      None
*/
{
   if (ConsoleDevice != NULL)
      CloseDevice(&ConsoleMsg);
}


#ifdef LATTICE
int
DeadKeyConvert(struct IntuiMessage *Message,
               UBYTE *KeyBuffer,
               int BufferSize,
               struct KeyMap *KeyMap)
#else
int
DeadKeyConvert(Message, KeyBuffer, BufferSize, KeyMap)
struct IntuiMessage *Message;
UBYTE *KeyBuffer;
int BufferSize;
struct KeyMap *KeyMap;
#endif
/* FUNCTION
      This function converts an Intuition RAWKEY message to the kind of
      keycodes returned by the Console Device.  It uses the Console Device's
      RawKeyConvert() function.

   INPUT
      Message - a pointer to the intuition message
      KeyBuffer - a pointer to the buffer the user supplied for keycodes
      BufferSize - the size of KeyBuffer
      KeyMap - a pointer to a KeyMap structure to be used for the
               conversion.  A NULL value selects the default KeyMap.

   RESULTS
      The function returns -2 if the message was not a RAWKEY class
      message.  If the number of keycodes produced was greater than
      BufferSize the function returns -1.  Otherwise the function returns
      the number of keycodes it placed in the buffer.
*/
{
   static struct InputEvent InputEvent =
   {
      NULL,             /* struct InputEvent *ie_NextEvent; */
      IECLASS_RAWKEY,   /* UBYTE ie_Class; */
      0,                /* UBYTE ie_SubClass; */
      0,                /* UWORD ie_Code; */
      0                 /* UWORD ie_Qualifier; */
                        /* union */
                        /* { */
                        /*    struct */
                        /*    { */
                        /*       WORD ie_x; */
                        /*       WORD ie_y; */
                        /*    } ie_xy; */
                        /*    APTR ie_addr; */
                        /* } ie_position; */
                        /* struct timeval ie_TimeStamp; */
   };

   if (Message->Class != RAWKEY)
      return(-2);
   /* if (Message->Code & IECODE_UP_PREFIX)
      return(0); */

   InputEvent.ie_Code = Message->Code;
   InputEvent.ie_Qualifier = Message->Qualifier;
   InputEvent.ie_position.ie_addr = (APTR)*(Message->IAddress);

   return(RawKeyConvert(&InputEvent, KeyBuffer, BufferSize, KeyMap));
}


int
OpenReadConsole()
/* FUNCTION
      This function gets a pointer to the Console Device by opening a
      Console Device without attaching it to any window.  Its purpose is to
      make the Console Device function RawKeyConvert() available.

   INPUT
      None

   RESULTS
      The function returns 0 if it succeeds, -1 if it failed to open the
      Console Device.
*/
{
   if (OpenDevice("console.device", -1L, &ConsoleMsg, 0) != 0)
      return(-1);
   ConsoleDevice = (struct Device *)ConsoleMsg.io_Device;
   return(0);
}


#ifdef LATTICE
char
ReadKey(struct IntuiMessage *Message,
        unsigned short int *KeyID,
        struct KeyMap *KeyMap)
#else
char
ReadKey(Message, KeyID, KeyMap)
struct IntuiMessage *Message;
unsigned short int *KeyID;
struct KeyMap *KeyMap;
#endif
/* FUNCTION
      This function converts an Intuition RAWKEY message to an ASCII
      character or an integer code identifying the special key pressed.

   INPUT
      Message - a pointer to the Intuition message
      KeyID - a pointer used to return the ID code of a function key
      KeyMap - a pointer to the keymap structure to be used for the
               conversion.  A NULL pointer specifies the default keymap.

   RETURNS
      If the function converts a RAWKEY message to an ASCII character it
      returns that character.  It returns zero if a special key was pressed
      and it places the key's ID code in the integer pointed to by KeyID.
      If the message was not a RAWKEY class message or if it was a "key up"
      message ReadKey() returns -2.  The calling program can ignore any
      calls which return -2.  If it fails it returns -1.
*/
{
   int actual;
   UBYTE KeyBuffer[10];

   *KeyID = 0;
   if (Message->Class != RAWKEY)
      return(-2);
      /* If it's not a RAWKEY message we'll just ignore it.  We tell the
         caller it can ignore it, too. */
   if (Message->Code & IECODE_UP_PREFIX)
      return(-2);
      /* If it's a key up message we'll ignore it and tell the caller to
         ignore it, too. */
   actual = DeadKeyConvert(Message, KeyBuffer, sizeof(KeyBuffer), KeyMap);
   if (actual == 1)
      return((char)KeyBuffer[0]);
      /* If DeadKeyConvert() converted the message to a single code we can
         return it to the caller. */
   switch (KeyBuffer[0])
   {
   case 0x9b:
      switch (KeyBuffer[1])
      {
      case ' ':
         switch (KeyBuffer[2])
         {
         case '@':
            *KeyID = K_S_RIGHT;
            break;
         case 'A':
            *KeyID = K_S_LEFT;
            break;
         default:
            break;
         }
         break;
      case '?':
         switch (KeyBuffer[2])
         {
         case '~':
            *KeyID = K_HELP;
            break;
         default:
            break;
         }
         break;
      case '0':
         switch (KeyBuffer[2])
         {
         case '~':
            *KeyID = K_F1;
            break;
         default:
            break;
         }
         break;
      case '1':
         switch (KeyBuffer[2])
         {
         case '~':
            *KeyID = K_F2;
            break;
         case '0':
            switch (KeyBuffer[3])
            {
            case '~':
               *KeyID = K_S_F1;
               break;
            default:
               break;
            }
            break;
         case '1':
            switch (KeyBuffer[3])
            {
            case '~':
               *KeyID = K_S_F2;
               break;
            default:
               break;
            }
            break;
         case '2':
            switch (KeyBuffer[3])
            {
            case '~':
               *KeyID = K_S_F3;
               break;
            default:
               break;
            }
            break;
         case '3':
            switch (KeyBuffer[3])
            {
            case '~':
               *KeyID = K_S_F4;
               break;
            default:
               break;
            }
            break;
         case '4':
            switch (KeyBuffer[3])
            {
            case '~':
               *KeyID = K_S_F5;
               break;
            default:
               break;
            }
            break;
         case '5':
            switch (KeyBuffer[3])
            {
            case '~':
               *KeyID = K_S_F6;
               break;
            default:
               break;
            }
            break;
         case '6':
            switch (KeyBuffer[3])
            {
            case '~':
               *KeyID = K_S_F7;
               break;
            default:
               break;
            }
            break;
         case '7':
            switch (KeyBuffer[3])
            {
            case '~':
               *KeyID = K_S_F8;
               break;
            default:
               break;
            }
            break;
         case '8':
            switch (KeyBuffer[3])
            {
            case '~':
               *KeyID = K_S_F9;
               break;
            default:
               break;
            }
            break;
         case '9':
            switch (KeyBuffer[3])
            {
            case '~':
               *KeyID = K_S_F10;
               break;
            default:
               break;
            }
            break;
         default:
            break;
         }
         break;
      case '2':
         switch (KeyBuffer[2])
         {
         case '~':
            *KeyID = K_F3;
            break;
         default:
            break;
         }
         break;
      case '3':
         switch (KeyBuffer[2])
         {
         case '~':
            *KeyID = K_F4;
            break;
         default:
            break;
         }
         break;
      case '4':
         switch (KeyBuffer[2])
         {
         case '~':
            *KeyID = K_F5;
            break;
         default:
            break;
         }
         break;
      case '5':
         switch (KeyBuffer[2])
         {
         case '~':
            *KeyID = K_F6;
            break;
         default:
            break;
         }
         break;
      case '6':
         switch (KeyBuffer[2])
         {
         case '~':
            *KeyID = K_F7;
            break;
         default:
            break;
         }
         break;
      case '7':
         switch (KeyBuffer[2])
         {
         case '~':
            *KeyID = K_F8;
            break;
         default:
            break;
         }
         break;
      case '8':
         switch (KeyBuffer[2])
         {
         case '~':
            *KeyID = K_F9;
            break;
         default:
            break;
         }
         break;
      case '9':
         switch (KeyBuffer[2])
         {
         case '~':
            *KeyID = K_F10;
            break;
         default:
            break;
         }
         break;
      case 'A':
         *KeyID = K_UP;
         break;
      case 'B':
         *KeyID = K_DOWN;
         break;
      case 'C':
         *KeyID = K_RIGHT;
         break;
      case 'D':
         *KeyID = K_LEFT;
         break;
      case 'S':
         *KeyID = K_S_DOWN;
         break;
      case 'T':
         *KeyID = K_S_UP;
         break;
      default:
         break;
      }
      break;
   default:
      break;
   }
   if (*KeyID == 0)
      return(-1);
   else
      return(0);
}
