/* GetKeyCode : Program to get the keycodes used by the Origami-Editor
 * Source Code written by Thomas Hadig in April 1992. This program
 * is public domain, but may only be used in a non commercial way
 *
 * Compile with SAS (Lattice) C 5.10 : lc -L -cusf GetKeyCode
 */
/*{{{  #includes*/
#include "exec/types.h"
#undef FALSE
#undef TRUE
#include <stdio.h>
#include <proto/exec.h>

#define KEYBOARD_C

#include "origami:local/bool.h"
#include "origami:origami/origami.h"

#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>

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

/*{{{  variables*/
struct IntuitionBase *IntuitionBase;
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;

char  general_abort_key=-1;

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

/*{{{  getascnum*/
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)*/
int reset_amiga (void)

 {
  if (ConsoleDevice) CloseDevice (&isr);
  if (wind) CloseWindow (wind);
  if (GfxBase) CloseLibrary (GfxBase);
  if (IntuitionBase) CloseLibrary ((struct Library *)IntuitionBase);
  return NULL;
 }
/*}}}  */
/*{{{  unsigned char **init_amiga (int *, struct WBStartup *)*/
unsigned char **init_amiga (int *argc, struct WBStartup *argv)

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

  /*{{{  Open Library*/
  if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary (
       "intuition.library",NULL))) exit (1);
  if (!(GfxBase = (struct GfxBase *)OpenLibrary ("graphics.library",
       NULL)))
   {
    reset_amiga();
    exit (1);
   }
  /*}}}  */
  /*{{{  Open Window*/
   {
    if (!(wind = (struct Window *) OpenWindow (&nw)))
     {
      reset_amiga();
      exit (1);
     }
   }
  /*}}}  */
  /*{{{  Open ConsoleDevice*/
  isr.io_Data = (APTR)wind;
  if (OpenDevice ("console.device",CONU_LIBRARY,&isr,0))
   {
    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 (void)*/
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&0x00F0) /* ALT or AMIGA */
                                 {
                                  /*{{{  test if amiga/alt code is different to normal code*/
                                  char buffer[20],p;

                                  iev.ie_Qualifier = 0;
                                  iev.ie_Code = code;
                                  if ((p=RawKeyConvert(&iev,buffer,20,NULL))==o)
                                   {
                                    /*{{{  ALT or AMIGA handled ?*/
                                    buffer[p]=buffer_keys[p]=0x00;
                                    if (!strcmp (buffer,buffer_keys))
                                     {
                                      MakeRawKey (code,quali,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 & 0x0100) /* number pad */
                                   {
                                    /*{{{  handle numpad*/
                                    tok = CSI;
                                    MakeRawKey (code,quali,CSI_NUMBER_PAD);
                                    /*}}}  */
                                   }
                                  /*}}}  */
                                 }
                                /*}}}  */
                               }
                              else
                               {
                                /*{{{  handle, if 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;
          /*}}}  */
          /*{{{  SelectDown*/
          case SELECTDOWN:  break;
          /*}}}  */
         }
        /*}}}  */
       }
      else Wait (1L << wind->UserPort->mp_SigBit);
     }
   }
  return tok;
 }
/*}}}  */
/*{{{  TOKEN get_key (void)*/
TOKEN get_key (void)

 {
  return (get_code());
 }
/*}}}  */

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

 {
  TOKEN i;

  init_amiga (NULL,NULL);
  puts ("GetKeyCode : Program to get the keycodes Origiami uses !");
  puts ("Close Origami-Window to quit !");
  do
   {
    i = get_key ();
    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 ();
 }
/*}}}  */
