/******************************************************************************

    MODUL
	keycodes.c

    DESCRIPTION
	Lowlevel module for evaluation of keycodes and qualifiers

    NOTES
	highly amiga - specific

    BUGS
	no use of dead-keys

    TODO
	deadkey - checking
	qual2iqual

    EXAMPLES

    SEE ALSO

    INDEX

    HISTORY
	14-Dez-92 b_null created
	14-Jan-93 b_null added UP
	15-Jan-92 b_null added DeadKeyConvert, removed exit_kb - it caused a GURU

******************************************************************************/

/**************************************
		Includes
**************************************/
#include "defs.h"
#include <devices/keymap.h>
#include <devices/console.h>

extern ubyte CtlC;


/**************************************
	    Globale Variable
**************************************/

Prototype int	 get_codequal	(const ubyte * str, ubyte * pcode, ushort * pqual);
Prototype char * cqtoa		(int code, int qual);

Prototype ushort iqual2qual	(unsigned long qual, int blen, char * buf, int code);
Prototype long	 qual2iqual	(ushort qual);

Prototype int	 a2iqual	(char * str, long * piqual);
Prototype char * iqual2a	(long iqual);
Prototype char	 CtoA		(char c);

Prototype void	 keyboard_init	(void);
Prototype void	 init_kb	(void);
Prototype void	 exit_kb	(void);
Prototype struct Library * ConsoleDevice;

/**************************************
      Interne Defines & Strukturen
**************************************/
typedef struct IOStdReq CIO;

/* format of entries in lname[] */
#define LN(a,b,c,d)  ((a<<24)|(b<<16)|(c<<8)|d)

/* important numbers in lname[] */
#define F1_START  0
#define SP_START 10
#define CS_START 20
#define N0_START 24
#define NS_START N0_START+10
#define MB_START 41

/* internal representation for qualifiers */
#define QUAL_SHIFT   0x0001
#define QUAL_CTRL    0x0002
#define QUAL_AMIGA   0x0004
#define QUAL_ALT     0x0008
#define QUAL_LMB     0x0010
#define QUAL_MMB     0x0020
#define QUAL_RMB     0x0040

#define QUAL_UP      0x0080 /* currently this MUST be 0x80 - that value is used in im.Code */

#define QUAL_XTX     0x0100 /* Extended Qualifiers for multi-key strokes */
#define QUAL_XTY     0x0200
#define QUAL_XTZ     0x0400

/* additional pseudo-intuition qualifiers - referring to the Quals above */
#define EXTQUALIFIER_X	0x00100000
#define EXTQUALIFIER_Y	0x00200000
#define EXTQUALIFIER_Z	0x00400000

#define EXTQUALIFIER_UP 0x00800000 /* this one is not used yet */

/* some hardcoded keys on Amiga Keyboard */
#define CSPC  0x40 /* Spacebar	*/
#define CB_S  0x41 /* BackSpace */
#define CENT  0x43 /* Enter	*/
#define CRET  0x44 /* Return	*/


/**************************************
	    Interne Variable
**************************************/
static ubyte ctoa[128];    /* code to ascii  */
static ubyte cstoa[128];   /* code shifted to ascii */

static long lname[] = {
    /* FuncKeys */
    LN('f','1', 0 , 0  ), LN('f','2', 0 , 0  ), LN('f','3', 0 , 0  ),
    LN('f','4', 0 , 0  ), LN('f','5', 0 , 0  ), LN('f','6', 0 , 0  ),
    LN('f','7', 0 , 0  ), LN('f','8', 0 , 0  ), LN('f','9', 0 , 0  ),
    LN('f','1','0', 0  ),
    /* Specials */
    LN('h','e','l', 0  ), LN('e','s','c', 0  ), LN('d','e','l', 0  ),
    LN('b','a','c', 0  ), LN('b','s', 0 , 0  ), LN('t','a','b', 0  ),
    LN('r','e','t',CRET), LN('e','n','t',CENT), LN('s','p','c',CSPC),
    LN('s','p','a',CSPC),
    /* Cursor */
    LN('u','p', 0 , 0  ), LN('d','o','w', 0  ), LN('r','i','g', 0  ),
    LN('l','e','f', 0  ),
    /* Numeric digits */
    LN('n','k','0', 0  ), LN('n','k','1', 0  ), LN('n','k','2', 0  ),
    LN('n','k','3', 0  ), LN('n','k','4', 0  ), LN('n','k','5', 0  ),
    LN('n','k','6', 0  ), LN('n','k','7', 0  ), LN('n','k','8', 0  ),
    LN('n','k','9', 0  ),
    /* Numeric Specials */
    LN('n','k', 0 , 0  ), LN('n','k', 0 , 0  ), LN('n','k','/', 0  ),
    LN('n','k','*', 0  ), LN('n','k','+', 0  ), LN('n','k','-', 0  ),
    LN('n','k','.', 0  ),
    /* Mouse Buttons */
    LN('l','m','b',0x68), LN('m','m','b',0x6A), LN('r','m','b',0x69),
    LN('m','m','o',0x6B)
};


       struct Library * ConsoleDevice;
static struct Library * KC_ConsoleDevice = NULL;      /* obsolete */
static int		KC_Used 	 = 0;	      /* obsolete */

/**************************************
	   Interne Prototypes
**************************************/


/*****************************************************************************

    NAME
	keyboard_init

    PARAMETER
	void

    RESULT
	-/-

    RETURN
	void

    DESCRIPTION
	initializes the variables used in the current Module

    NOTES
	That functon MUST be called before any other call to any
	other functions of the key-modules

    BUGS
	if a dead- and a deadable-key are next to each other,
	tables may be corrupt

    EXAMPLES

    SEE ALSO

    INTERNALS

    HISTORY
	14-Dec-92  b_null included & modified

******************************************************************************/

void keyboard_init (void)
{
    static struct InputEvent ievent = {
	NULL,
	IECLASS_RAWKEY,
	0, 0, 0, NULL,
    };
    ubyte buf[32];
    short i,
	  len;

/* printf ("keyboard_init\n"); */
    for (i = 0; i < 128; ++i) {
	ievent.ie_Code = i;
	ievent.ie_Qualifier = 0;
	ievent.ie_position.ie_addr = NULL;

	len = RawKeyConvert (&ievent, buf, 32, NULL);

	switch(len) {
	case 1:     /*	ESC/DEL/BS/TAB/NKx  */
	    if ((buf[0] & 0x7F) >= 32 && (buf[0] & 0x7F) < 127)
		ctoa[i] = buf[0];

	    switch(buf[0]) {
	    case 0x1B:	lname[SP_START+1] |= i; break;
	    case 0x7F:	lname[SP_START+2] |= i; break;
	    case 0x08:	lname[SP_START+3] |= i;
			lname[SP_START+4] |= i; break;
	    case 0x09:	lname[SP_START+5] |= i; break;
	    case '@':                                                           /* for setmap cdn     */
	    case '[':                                                           /* for setmap d,f,i,n */
	    case '(': if (i > 0x3A) lname[NS_START+0] |= LN(0,0,*buf,i); break; /* for setmap usa/gb  */
	    case '°':                                                           /* for setmap cdn     */
	    case ']':                                                           /* for setmap d,i,f,n */
	    case ')': if (i > 0x3A) lname[NS_START+1] |= LN(0,0,*buf,i); break; /* for setmap usa/gb  */
	    case '/': if (i > 0x3A) lname[NS_START+2] |= i; break;
	    case '*': if (i > 0x3A) lname[NS_START+3] |= i; break;
	    case '+': if (i > 0x3A) lname[NS_START+4] |= i; break;
	    case '-': if (i > 0x3A) lname[NS_START+5] |= i; break;
	    case '.': if (i > 0x3A) lname[NS_START+6] |= i; break;
	    default:
		if (i >= 0x0F && isdigit (buf[0]))
		    lname[N0_START+buf[0]-'0'] |= i;
	    } /* switch */
	    break;

	case 2:     /*	cursor		    */
	    if (buf[0] == 0x9B)
	    {
		switch(buf[1]) {
		case 0x41:  lname[CS_START+0] |= i;  break;
		case 0x42:  lname[CS_START+1] |= i;  break;
		case 0x43:  lname[CS_START+2] |= i;  break;
		case 0x44:  lname[CS_START+3] |= i;  break;
		}
	    }
	    break;

	case 3:     /*	function/help	    */
	    if (buf[0] == 0x9B && buf[2] == 0x7E)
	    {
		if (buf[1] == 0x3F)
		    lname[SP_START+0] |= i;
		if (buf[1] >= 0x30 && buf[1] <= 0x39)
		    lname[buf[1]-0x30+F1_START] |= i;
	    }
	    break;
	} /* switch */
    } /* for */

    for (i = 0; i < 128; ++i)
    {
	ievent.ie_Code = i;
	ievent.ie_Qualifier = IEQUALIFIER_LSHIFT;
	ievent.ie_position.ie_addr = NULL;

	len = RawKeyConvert (&ievent,buf,32,NULL);

	if (len == 1)
	    cstoa[i] = buf[0];
    } /* for */

    {
	ubyte  code;
	ushort qual;

	get_codequal ("c", &code, &qual);

	CtlC = code;
    } /* block */
} /* keyboard_init */



/*****************************************************************************

    NAME
	cqtoa

    PARAMETER
	VAL (int, code)
	VAL (int, qual)

    RESULT
	a ptr to the string that is the readable
	form of that key-stroke (static)

    RETURN
	char *

    DESCRIPTION

    NOTES
	we return a ptr to a static array of char
	for only use of Qualifiers simply use code == -1

    BUGS
	(none known)

    EXAMPLES

    SEE ALSO

    INTERNALS

    HISTORY
	14-Dez-92 b_null created
	14-Jan-93 b_null added UP

******************************************************************************/

char * cqtoa (int code, int qual)
{
    static char buf[32];
    char *	ptr = buf;
    int 	i;

    if (qual & QUAL_SHIFT)
	*ptr++ = 's';
    if (qual & QUAL_CTRL)
	*ptr++ = 'c';
    if (qual & QUAL_ALT)
	*ptr++ = 'a';
    if (qual & QUAL_AMIGA)
	*ptr++ = 'A';
    if (qual & QUAL_LMB)
	*ptr++ = 'L';
    if (qual & QUAL_MMB)
	*ptr++ = 'M';
    if (qual & QUAL_RMB)
	*ptr++ = 'R';

    if (qual & QUAL_XTX)
	*ptr++ = 'x';
    if (qual & QUAL_XTY)
	*ptr++ = 'y';
    if (qual & QUAL_XTZ)
	*ptr++ = 'z';

    if (qual & QUAL_UP)
	*ptr++ = 'u';
/*
**  --- That little fragment was added
**	to be able to get the extended qualifiers with already existing functions
**	U might uncomment it, if U wanna get information about
**	which quals have been set with QUALIFIER
*/
    if (code == (-1)) {
/* printf("U used a wrong undef\n"); */
	*ptr++ = 0;
	return(buf);
    } /* if */

    // if (qual)        /* commented out for better readable keyfiles */
	*ptr++ = '-';
    for (i = 0; i < sizeof(lname)/sizeof(lname[0]); ++i) {
	if ((lname[i]&0xFF) == code) {
	    *ptr++ = (lname[i]>>24);
	    *ptr++ = (lname[i]>>16);
	    *ptr++ = (lname[i]>>8);
	    break;
	}
    }
    if (i == sizeof(lname)/sizeof(lname[0])) {
	*ptr = ctoa[code];

	if (*ptr) {
	    ptr ++;
	/* PATCH_NULL [14 Feb 1993] : direct access to rawcodes ... */
	} else {
	    sprintf (ptr, "0x%02x",code);
	    ptr += 4;
	} /* if */
	/* PATCH_NULL [14 Feb 1993] : ... direct access to rawcodes */
    } /* if no spcname */

    *ptr++ = 0;
    return(buf);
} /* cqtoa */


/*****************************************************************************

    NAME
	get_codequal

    PARAMETER
	VAL (char *, string)
	VAR (ubyte,  pcode)
	VAR (ushort, pqual)

    RESULT
	success: 1 == ok; 0 == error (unknown string)

    RETURN
	int

    DESCRIPTION
	we try to extract Qualifier- and Keycode -information
	from an ascii-String and put the found values into
	pcode and pqual

    NOTES
	for only use of Qualifiers simply use code == -1

    BUGS
	(none known)

    EXAMPLES

    SEE ALSO

    INTERNALS

    HISTORY
	14-Dec-92 b_null included & modified
	14-Jan-93 b_null added UP

******************************************************************************/

int get_codequal (const ubyte * str, ubyte * pcode, ushort * pqual)
{
    const char * base = str;
    ushort	 qual;
    short	 i;

    qual = 0;
    if (strlen(str) > 1) {
	for (; *str && *str != '-'; ++str) {
	    if (*str == 's')
		qual |= QUAL_SHIFT;
	    if (*str == 'c')
		qual |= QUAL_CTRL;
	    if (*str == 'a')
		qual |= QUAL_ALT;
	    if (*str == 'A')
		qual |= QUAL_AMIGA;
	    if (*str == 'L')
		qual |= QUAL_LMB;
	    if (*str == 'M')
		qual |= QUAL_MMB;
	    if (*str == 'R')
		qual |= QUAL_RMB;

	    if (*str == 'x')
		qual |= QUAL_XTX;
	    if (*str == 'y')
		qual |= QUAL_XTY;
	    if (*str == 'z')
		qual |= QUAL_XTZ;

	    if (*str == 'u')
		qual |= QUAL_UP;

	    if (!qual)
		goto notqual;
	}
	if (*str == 0) {
	    qual = 0;
	    str = base;
	} else {
	    ++str;
	}
    }
notqual:
    if (strlen(str) != 1) {           /* long name   */
	short shift = 24;
	long mult = 0;
	ubyte c;
	ubyte * ptr = str; /* PATCH_NULL [14 Feb 1993] : added */

	*pqual = qual;
	while ((c = *str) && shift >= 8) {
	    c = tolower (c);
	    mult |= c << shift;
	    shift -= 8;
	    ++str;
	}
	for (i = 0; lname[i]; ++i) {
	    if (mult == (lname[i] & 0xFFFFFF00)) {
		*pcode = lname[i] & 0xFF;
		return (1);
	    }
	}
	/* PATCH_NULL [14 Feb 1993] : direct access to raw-codes ... */
	/* NOTE 		    : we cannot save that value yet!!! */
/* printf ("testing %s with hex\n", str); */
	if ((*ptr == '0') && ((ptr[1]|0x20) == 'x')) {
	    i = (strtol (ptr, &str, 0x10) & 0xff);
	    if (ptr != (ubyte *)str) {
		*pcode = i;
		return (1);
	    } /* if scanned */
	} /* if */
	/* PATCH_NULL [14 Feb 1993] : ... direct access to raw-codes */
    } else {		    /*	single character keycap */
	for (i = 0; i < sizeof(ctoa); ++i) {
	    if (*str == ctoa[i]) {
		*pcode = i;
		*pqual = qual;
		return (1);
	    }
	}
	for (i = 0; i < sizeof(cstoa); ++i) {
	    if (*str == cstoa[i]) {
		*pcode = i;
		*pqual = qual|QUAL_SHIFT;
		return (1);
	    }
	}
    }
    return (0);
} /* get_codequal */


/*****************************************************************************

    NAME
	iqual2qual

    PARAMETER
	VAL (ulong,  qual)
	VAL (int,    blen)
	VAL (char *, buf)
	VAL (int,    code)

    RESULT
	the [X]DME-internal qualifier referred by the intuition qualifier qual;

    RETURN
	ushort

    DESCRIPTION
	transform the different intuition - Qualifiers to [X]DME-Qualifiers
	(if we have caps-lock and buffer contains
	one lower char, it is used like shift)

    NOTES

    BUGS
	(none known)

    EXAMPLES

    SEE ALSO

    INTERNALS

    HISTORY
	14-Dec-92 b_null included & modified
	14-Jan-93 b_null added UP

******************************************************************************/

ushort iqual2qual (unsigned long qual, int blen, char * buf, int code)
{
    ushort q2 = 0;

    if (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
	q2 |= QUAL_SHIFT;
    if (qual & (IEQUALIFIER_CONTROL))
	q2 |= QUAL_CTRL;
    if (qual & (IEQUALIFIER_LCOMMAND|IEQUALIFIER_RCOMMAND))
	q2 |= QUAL_AMIGA;
    if (qual & (IEQUALIFIER_LALT|IEQUALIFIER_RALT))
	q2 |= QUAL_ALT;
    if ((qual & IEQUALIFIER_CAPSLOCK) && blen == 1 && islower (buf[1]))
	q2 |= QUAL_SHIFT;
    if (qual & IEQUALIFIER_LEFTBUTTON)
	q2 |= QUAL_LMB;
    if (qual & IEQUALIFIER_MIDBUTTON)
	q2 |= QUAL_MMB;
    if (qual & (IEQUALIFIER_RBUTTON))
	q2 |= QUAL_RMB;

    if (qual & (EXTQUALIFIER_X))
	q2 |= QUAL_XTX;
    if (qual & (EXTQUALIFIER_Y))
	q2 |= QUAL_XTY;
    if (qual & (EXTQUALIFIER_Z))
	q2 |= QUAL_XTZ;

    if (qual & (EXTQUALIFIER_UP))
	q2 |= QUAL_XTZ;
    q2 |= (QUAL_UP & code);

    return(q2);
} /* iqual2qual */


/*****************************************************************************

    NAME
	qual2iqual

    PARAMETER
	VAL (ushort, qual)

    RESULT
	Intuition Qualifiers, which represent the [X]DME - qualifiers

    RETURN
	long

    DESCRIPTION
	simple transformation of internal representation for
	Qualifiers to a possible Amiga-representation

    NOTES
	very slow
	!ATTN!	there is currently no possibility to
		transform the UP-Qualifier

    BUGS
	(none known)

    EXAMPLES

    SEE ALSO
	iqual2qual

    INTERNALS

    HISTORY
	14-Dez-92 b_null created
	14-Jan-93 b_null added UP

******************************************************************************/

long qual2iqual (ushort qual)
{
    long q2 = 0;

    if (qual & QUAL_XTX)
	q2 |= EXTQUALIFIER_X;
    if (qual & QUAL_XTY)
	q2 |= EXTQUALIFIER_Y;
    if (qual & QUAL_XTZ)
	q2 |= EXTQUALIFIER_Z;

    if (qual & QUAL_UP)
	q2 |= EXTQUALIFIER_UP;

    if (qual & QUAL_SHIFT)
	q2 |= IEQUALIFIER_LSHIFT;
    if (qual & QUAL_CTRL)
	q2 |= IEQUALIFIER_CONTROL;
    if (qual & QUAL_AMIGA)
	q2 |= IEQUALIFIER_LCOMMAND;
    if (qual & QUAL_ALT)
	q2 |= IEQUALIFIER_LALT;
    if (qual & QUAL_LMB)
	q2 |= IEQUALIFIER_LEFTBUTTON;
    if (qual & QUAL_MMB)
	q2 |= IEQUALIFIER_MIDBUTTON;
    if (qual & QUAL_RMB)
	q2 |= IEQUALIFIER_RBUTTON;

    return (q2);
} /* qual2iqual */

/*****************************************************************************

    NAME
	a2iqual

    PARAMETER
	VAL (char *, str)
	VAR (long,   piqual)

    RESULT
	success: 1 == ok; 0 == any error

    RETURN
	int

    DESCRIPTION
	convert an ascii string into Input-Qualifiers
	we check each char of the string and set the according bit
	the string may be NULL-terminated or "-"-terminated
	any unknown char causes "return (0)"

    NOTES

    BUGS
	(none known)

    EXAMPLES

    SEE ALSO

    INTERNALS

    HISTORY
	14-Dez-92 null created
	14-Jan-93 b_null added UP

******************************************************************************/

int a2iqual (char * str, long * piqual)
{
    *piqual = 0;
    for (; *str; str++) {
	switch (*str) {
	case 'a':   *piqual |= IEQUALIFIER_LALT;        break;
	case 'A':   *piqual |= IEQUALIFIER_LCOMMAND;    break;
	case 's':   *piqual |= IEQUALIFIER_LSHIFT;      break;
	case 'L':   *piqual |= IEQUALIFIER_LEFTBUTTON;  break;
	case 'M':   *piqual |= IEQUALIFIER_MIDBUTTON;   break;
	case 'R':   *piqual |= IEQUALIFIER_RBUTTON;     break;

	case 'u':   *piqual |= EXTQUALIFIER_UP;         break;

	case 'x':   *piqual |= EXTQUALIFIER_X;          break;
	case 'y':   *piqual |= EXTQUALIFIER_Y;          break;
	case 'z':   *piqual |= EXTQUALIFIER_Z;          break;

	case '-':   return (1);
	default:    return (0);
	} /* switch */
    } /* for */
    return (1);
} /* a2iqual */

/*****************************************************************************

    NAME
	iqual2a

    PARAMETER
	VAL (long, iqual)

    RESULT
	the string that corresponds to iqual  (static)

    RETURN
	char *

    DESCRIPTION
	create a string representing the readble form of Intuition Qualifiers

    NOTES
	this is a slow routine, as we do not
	immediately evaluated the string, but
	use iqual2qual and cqtoa (but it works :-)

    BUGS
	(none known)

    EXAMPLES

    SEE ALSO
	iqual2qual(), cqtoa

    INTERNALS

    HISTORY
	14-Dez-92 null created

******************************************************************************/

char * iqual2a (long iqual)
{
    return (cqtoa (-1, iqual2qual (iqual, 0, NULL, 0)));
} /* iqual2a */


/*****************************************************************************

    NAME
	init_kb
	(exit_kb - obsolete)

    PARAMETER
	void

    RESULT
	-/-

    RETURN
	void

    DESCRIPTION
	entry and exit- code for Keyboard Control

    NOTES
	this is the lowest level on Amiga Software, we use
	exit_kb is obsolete, so user cannot call it any more
	init_kb is "__AUTOINIT" so user need not call it
	(he must indeed, if his compiler does not support __autoinit)

    BUGS
	for unknown reasons, we must not close ConsoleDevice

    EXAMPLES

    SEE ALSO

    INTERNALS

    HISTORY
	15-Dez-92  b_null created
	15-Jan-93  b_null removed exit_kb

******************************************************************************/

/* Das war teil von reset_hash... */
/* es ist extremer Amiga - lowlevel - wohin?? */
/*
** Achtung: keine Ahnung wieso,
**  aber wir DUERFEN ConsoleDevice nicht schliessen
**    es ist jedenfalls so, dass wir sonst ziemlich abkacken
**  zwischenspeichern nuetzt nix ...
**  daher koennen wir diesen ganzen kram mit KC_... weglassen
*/


__autoinit
void init_kb (void)
{
    struct IOStdReq cio;

/* printf ("init_kb\n"); */

    if (!KC_Used) {
	OpenDevice ("console.device", -1, (struct IORequest *)&cio, 0);
	ConsoleDevice = (struct Library *)cio.io_Device;
	keyboard_init ();
    } /* if */
    KC_Used = 1;
} /* init_kb */


/*****************************************************************************

    NAME
	CtoA

    PARAMETER
	char c

    RESULT
	ctoa[c]

    RETURN
	char

    DESCRIPTION
	this function was created to hide the stucture ctoa

	ctoa is designed to check, IF a code c represents a
	single ascii character and WHICH one

    NOTES
	a macro might be possible, too;
	but then You have to declare ctoa non-static

	ctoa is initialized by keyboard_init(), so
	any call to CtoA before keyboard initialisation is undefined

    BUGS
	none known

    EXAMPLES

    SEE ALSO
	ctoa

    INTERNALS

    HISTORY
	30-Dez-92 b_null created
	15-Jan-93 b_null documented

******************************************************************************/

char CtoA (char c)
{
    return (ctoa[c]);
} /* CtoA */

/*****************************************************************************

    NAME
	DeadKeyConvert

    PARAMETER
	struct IntuiMessage * msg
	UBYTE * 	      buf
	int		      bufsize
	struct KeyMap *       keymap

    RESULT
	actual - the number of characters in the buffer, -2 if no
	RawKey was given or -1 if a buffer overflow was about to occur.

    RETURN
	int

    DESCRIPTION
	convert any RawKey-Code to (VanillaKey) an ASCII-String

    NOTES
	this function is only used by keycontrol.keyctl
	but it for itself uses ConsoleDevice, so I could not
	decide where to pu it.

    BUGS

    EXAMPLES

    SEE ALSO
	console.device/RawKeyConvert

    INTERNALS
	ereuge eine iorequest mit den allernotwendigsten eintraegen
	und lasse sie auswerten

    HISTORY
	15-Dez-92 b_null moved to keycontrol.c
	16.Dez.92 b_null documented
	15-Jan-93 b_null moved to keycodes.c

******************************************************************************/

Prototype int	 DeadKeyConvert (struct IntuiMessage * msg, UBYTE * buf, int bufsize, struct KeyMap * keymap);

int DeadKeyConvert (struct IntuiMessage * msg, UBYTE * buf, int bufsize, struct KeyMap * keymap)
{
    static struct InputEvent ievent = {
	NULL, IECLASS_RAWKEY
    };

    if (msg->Class != RAWKEY)
	return(-2);

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

    return (RawKeyConvert (&ievent, (char *)buf, bufsize, keymap));
} /* DeadKeyConvert */


/******************************************************************************
*****  ENDE keycodes.c
******************************************************************************/
