/* GetKeyCode : Program to get the keycodes used by the Origami-Editor
 * Source Code written by Thomas Hadig in April 1992. This program
 * is freeware (read the README.AMIGA file in the src/amiga/docs dir)
 *
 * Compile with SAS C 6.3 : sc link ansi GetKeyCode
 *
 * Version 1.2b
 */
/*{{{}}}*/
/*{{{  #includes*/
/*{{{  standard includes*/
#include <exec/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/*}}}  */
/*{{{  clib includes*/
#include <clib/intuition_protos.h>
#include <clib/console_protos.h>
#include <clib/exec_protos.h>
/*}}}  */
/*{{{  amiga includes*/
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <devices/inputevent.h>
/*}}}  */

#define AMIGA
#define KEYBOARD_C

#include <origami/origami.h>
/*}}}  */
/*{{{  #defines*/
#define CSI 0x9B
#define CONU_LIBRARY -1
/*}}}  */

/*{{{  variables*/
static char version_string_os_2_x[] = "$VER: GetKeyCode 1.2 (" __DATE__ ")";
long __OSlibversion=34;
extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase       *GfxBase;

struct Window        *wind;

struct Library       *ConsoleDevice;
struct IOStdReq      isr;
struct InputEvent    iev = {NULL,0x01,0,0,0,0,0,0,0};
struct Task          *task;

unsigned char  general_abort_key= 255;

unsigned char    buffer_keys[buffer_keys_max];
int     key_buffer = 0,key_buffer_max = 0;
/*}}}  */

/*{{{  getascnum*/
unsigned char *getascnum (char *cptr,short *sptr)

{
  if (!isdigit(cptr[0])) return 0;
  *sptr = atoi (cptr);
  while (isdigit(cptr[0])) cptr++;
  return cptr;
}
/*}}}  */

/*{{{  int reset_amiga*/
void reset_amiga (void)

{
#pragma msg 88 ignore push
  if (ConsoleDevice) CloseDevice (&isr);
#pragma msg 88 pop
  if (wind) CloseWindow (wind);
}
/*}}}  */
/*{{{  void init_amiga*/
void init_amiga (void)

{
  /*{{{  variables*/
    struct NewWindow nw = {0,11,640,100,255,255,
           MENUPICK | CLOSEWINDOW | NEWSIZE | RAWKEY,
           WINDOWSIZING | WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE,
           NULL, NULL, "GetKeyCode : Origami", NULL, NULL, 150, 30, 640, 200,
           WBENCHSCREEN };
  /*}}}  */

  /*{{{  Open Window*/
  if (!(wind = (struct Window *) OpenWindow (&nw))) exit (1);
  /*}}}  */
  /*{{{  Open ConsoleDevice*/
  isr.io_Data = (APTR)wind;
#  pragma msg 88 ignore push
  if (OpenDevice ("console.device",CONU_LIBRARY,&isr,0))
#  pragma msg 88 pop
  {
    reset_amiga();
    exit(1);
  }
  ConsoleDevice = (struct Library *)isr.io_Device;
  /*}}}  */
}
/*}}}  */

/*{{{  MakeRawKey*/
void MakeRawKey (USHORT code, USHORT quali, char init)

{
  char b = 65;

  buffer_keys[0] = init;
  if (quali & 0x0003) b++; /* SHIFT */
  if (quali & 0x0008) b+=2; /* Control */
  if (quali & 0x0030) b+=4; /* ALT */
  if (quali & 0x0040) b+=8; /* left Amiga */
  if (quali & 0x0080) b+=16; /* right Amiga */
  buffer_keys[1] = b;
  buffer_keys[2] = code;
  key_buffer = 0;
  key_buffer_max = 3;
}
/*}}}  */
/*{{{  TOKEN get_code*/
TOKEN get_code (void)

{
  TOKEN tok = 0;
  struct IntuiMessage *msg;
  ULONG  class;
  USHORT code,quali;

  if (key_buffer_max > key_buffer)
    tok = buffer_keys[key_buffer++];
  else
  {
    while (!tok)
    {
      if ((msg = (struct IntuiMessage *)GetMsg (wind->UserPort)))
      {
        /*{{{  Message Handling*/
        class = msg->Class;
        code  = msg->Code;
        quali = msg->Qualifier;
        ReplyMsg ((struct Message *)msg);
        switch (class)
        {
          /*{{{  CloseWindow*/
          case CLOSEWINDOW:
            tok = O_QUIT;
            break;
          /*}}}  */
          /*{{{  RawKey*/
          case RAWKEY:
          {
            int o;

            iev.ie_Code = code;
            iev.ie_Qualifier = quali;
            if ((!(code&0x80))&&((code&0x60)!=0x60))
            {
              if (o = RawKeyConvert(&iev,buffer_keys,buffer_keys_max,NULL))
              {
                /*{{{  Vanilla exists*/
                if (quali&0x00FF) /* any qualifier */
                {
                  /*{{{  test if qualifier code is different to normal code*/
                  unsigned char buffer[20],p;

                  iev.ie_Qualifier = 0;
                  iev.ie_Code = code;
                  if ((p=RawKeyConvert(&iev,buffer,20,NULL))==o)
                  {
                    /*{{{  qualifier handled ?*/
                    buffer[p]=buffer_keys[p]=0x00;
                    if (!strcmp (buffer,buffer_keys))
                    {
                      MakeRawKey (code,quali,
                        quali&IEQUALIFIER_NUMERICPAD ?
                          CSI_NUMBER_PAD : CSI_RAW_KEY); /* no */
                      tok = CSI;
                    }
                    else
                    {
                      key_buffer = 1;
                      key_buffer_max = o;
                      tok = buffer_keys[0];
                    }
                    /*}}}  */
                  }
                  else
                  {
                    /*{{{  code different*/
                    key_buffer = 1;
                    key_buffer_max = o;
                    tok = buffer_keys[0];
                    /*}}}  */
                  }
                  /*}}}  */
                }
                else
                {
                  tok = buffer_keys[0];
                  /*{{{  handle numberpad and keysequences*/
                  if (o>1)
                  {
                    /*{{{  handle vanilla keysequence*/
                    key_buffer = 1;
                    key_buffer_max = o;
                    /*}}}  */
                  }
                  else if (quali & IEQUALIFIER_NUMERICPAD) /* number pad */
                  {
                    /*{{{  handle numpad*/
                    tok = CSI;
                    MakeRawKey (code,quali,CSI_NUMBER_PAD);
                    /*}}}  */
                  }
                  /*}}}  */
                }
                /*}}}  */
              }
              else
              {
                /*{{{  handle as RAWKEY_CODE*/
                tok = CSI;
                MakeRawKey (code,quali,CSI_RAW_KEY);
                /*}}}  */
              }
            }
            break;
          }
          /*}}}  */
          /*{{{  NewSize*/
          case NEWSIZE:
            tok = O_REFRESH;
            while ((tok != O_QUIT) &&
                   ((wind->Width<270)|| (wind->Height<60)))
            {
              Wait (1L << wind->UserPort->mp_SigBit);
              while (msg=(struct IntuiMessage *)GetMsg (wind->UserPort))
              {
                if (msg->Class == CLOSEWINDOW) tok = O_QUIT;
                ReplyMsg ((struct Message *)msg);
              }
            }
            break;
          /*}}}  */
          /*{{{  MenuPick*/
          case MENUPICK:
            if (code!=MENUNULL)
            {
              tok = CSI;
              buffer_keys[0] = CSI_MENU_PICK;
              buffer_keys[1] = 48 + MENUNUM(code);
              buffer_keys[2] = 48 + ITEMNUM(code);
              key_buffer_max = 3;
              key_buffer = 0;
            }
            break;
          /*}}}  */
        }
        /*}}}  */
      }
      else Wait (1L << wind->UserPort->mp_SigBit);
    }
  }
  return tok;
}
/*}}}  */

/*{{{  main*/
void main (void)

{
  TOKEN i;

  init_amiga ();
  puts ("GetKeyCode : Program to get the keycodes Origiami uses !");
  puts ("Close Origami-Window to quit !");
  do
  {
    i = get_code ();
    if (i>=256)
    {
      if (i==O_QUIT) puts ("O_QUIT ! Bye !");
      else if (i==O_REFRESH) puts ("O_REFRESH ! (new size)");
      else puts ("Unknown Command !?");
    }
    else if (i<32)
    {
      if (i!=27) printf ("%d = 0x%x = C-%c\n",i,i,i+64);
      else puts ("27 = 0x1B = $esc = Meta (M-)");
    }
    else if (i==32) puts ("32 = 0x20 = <SPACE>");
    else if (i==127) puts ("127 = 0x7F = <DEL> (!= $del)");
    else if (i==155) puts ("155 = 0x9B = $csi");
    else printf ("%d = 0x%x = %c\n",i,i,i);
  } while (i!=O_QUIT);
  reset_amiga ();
}
/*}}}  */
