;/* rawkey.c - Execute me to compile me with SAS C 5.10
LC -b1 -cfistq -v -y -j73 rawkey.c
Blink FROM LIB:c.o,rawkey.o TO rawkey LIBRARY LIB:LC.lib,LIB:Amiga.lib
quit
**
** The following example uses RawKeyConvert() to convert the
** IDCMP_RAWKEY input stream into an ANSI input stream. See the
** "Console Device" chapter in the Amiga ROM Kernel Reference Manual:
** Devices for more information on RawKeyConvert() and the data it
** returns.
**
** rawkey.c - How to correctly convert from RAWKEY to keymapped ASCII
*/
#define INTUI_V36_NAMES_ONLY
#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <devices/inputevent.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/console_protos.h>
#include <stdio.h>
#ifdef LATTICE
int CXBRK(void) { return(0); } /* Disable Lattice CTRL/C handling */
int chkabort(void) { return(0); } /* really */
#endif
/* our function prototypes */
LONG deadKeyConvert(struct IntuiMessage *msg, UBYTE *kbuffer,
LONG kbsize, struct KeyMap *kmap, struct InputEvent *ievent);
VOID print_qualifiers(ULONG qual);
BOOL doKeys(struct IntuiMessage *msg, struct InputEvent *ievent,
UBYTE **buffer, ULONG *bufsize);
VOID process_window(struct Window *win, struct InputEvent *ievent,
UBYTE **buffer, ULONG *bufsize);
/* A buffer is created for RawKeyConvert() to put its output. BUFSIZE is the size of
** the buffer in bytes. NOTE that this program starts out with a buffer size of 2.
** This is only to show how the buffer is automatically increased in size by this
** example! In an application, start with a much larger buffer and you will probably
** never have to increase its size. 128 bytes or so should do the trick, but always
** be able to change the size if required.
*/
#define BUFSIZE (2)
struct Library *IntuitionBase, *ConsoleDevice;
/* main() - set-up everything used by program. */
VOID main(int argc, char **argv)
{
struct Window *win;
struct IOStdReq ioreq;
struct InputEvent *ievent;
UBYTE *buffer;
ULONG bufsize = BUFSIZE;
if(IntuitionBase = OpenLibrary("intuition.library",37)) {
/* Open the console device just to do keymapping. (unit -1 means any unit) */
if (0 == OpenDevice("console.device",-1,(struct IORequest *)&ioreq,0)) {
ConsoleDevice = (struct Library *)ioreq.io_Device;
/* Allocate the initial character buffer used by deadKeyConvert() and RawKeyConvert()
** for returning translated characters. If the characters generated by these routines
** cannot fit into the buffer, the application must pass a larger buffer. This is
** done in this code by freeing the old buffer and allocating a new one.
*/
if (buffer = AllocMem(bufsize,MEMF_CLEAR)) {
if (ievent = AllocMem(sizeof(struct InputEvent),MEMF_CLEAR)) {
if (win = OpenWindowTags(NULL,
WA_Width, 300,
WA_Height, 50,
WA_Flags, WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_ACTIVATE,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
WA_Title, "Raw Key Example",
TAG_END)) {
printf("Press keyboard keys to see ASCII conversion from rawkey\n");
printf("Unprintable characters will be shown as %c\n\n",0x7f);
process_window(win,ievent,&buffer,&bufsize);
CloseWindow(win);
}
FreeMem(ievent,sizeof(struct InputEvent));
}
/* Buffer can be freed elsewhere in the program so test first. */
if (buffer != NULL)
FreeMem(buffer,bufsize);
}
CloseDevice((struct IORequest *)&ioreq);
}
CloseLibrary(IntuitionBase);
}
}
/* Convert RAWKEYs into VANILLAKEYs, also shows special keys like HELP, Cursor Keys,
** FKeys, etc. It returns:
** -2 if not a RAWKEY event.
** -1 if not enough room in the buffer, try again with a bigger buffer.
** otherwise, returns the number of characters placed in the buffer.
*/
LONG deadKeyConvert(struct IntuiMessage *msg, UBYTE *kbuffer,
LONG kbsize, struct KeyMap *kmap, struct InputEvent *ievent)
{
if (msg->Class != IDCMP_RAWKEY) return(-2);
ievent->ie_Class = IECLASS_RAWKEY;
ievent->ie_Code = msg->Code;
ievent->ie_Qualifier = msg->Qualifier;
ievent->ie_position.ie_addr = *((APTR*)msg->IAddress);
return(RawKeyConvert(ievent,kbuffer,kbsize,kmap));
}
/* print_qualifiers() - print out the values found in the qualifier bits of
** the message. This will print out all of the qualifier bits set.
*/
VOID print_qualifiers(ULONG qual)
{
printf("Qual:");
if (qual & IEQUALIFIER_LSHIFT) printf("LShft,");
if (qual & IEQUALIFIER_RSHIFT) printf("RShft,");
if (qual & IEQUALIFIER_CAPSLOCK) printf("CapLok,");
if (qual & IEQUALIFIER_CONTROL) printf("Ctrl,");
if (qual & IEQUALIFIER_LALT) printf("LAlt,");
if (qual & IEQUALIFIER_RALT) printf("RAlt,");
if (qual & IEQUALIFIER_LCOMMAND) printf("LCmd,");
if (qual & IEQUALIFIER_RCOMMAND) printf("RCmd,");
if (qual & IEQUALIFIER_NUMERICPAD) printf("NumPad,");
if (qual & IEQUALIFIER_REPEAT) printf("Rpt,");
if (qual & IEQUALIFIER_INTERRUPT) printf("Intrpt,");
if (qual & IEQUALIFIER_MULTIBROADCAST) printf("Multi Broadcast,");
if (qual & IEQUALIFIER_MIDBUTTON) printf("MidBtn,");
if (qual & IEQUALIFIER_RBUTTON) printf("RBtn,");
if (qual & IEQUALIFIER_LEFTBUTTON) printf("LBtn,");
if (qual & IEQUALIFIER_RELATIVEMOUSE) printf("RelMouse,");
}
/* doKeys() - Show what keys were pressed. */
BOOL doKeys(struct IntuiMessage *msg, struct InputEvent *ievent,
UBYTE **buffer, ULONG *bufsize)
{
USHORT char_pos;
USHORT numchars;
BOOL ret_code = TRUE;
UBYTE realc, c;
/* deadKeyConvert() returns -1 if there was not enough space in the buffer to
** convert the string. Here, the routine increases the size of the buffer on the
** fly...Set the return code to FALSE on failure.
*/
numchars = deadKeyConvert(msg, *buffer, *bufsize - 1, NULL, ievent);
while ((numchars == -1) && (*buffer != NULL)) {
/* conversion failed, buffer too small. try to double the size of the buffer. */
FreeMem(*buffer, *bufsize);
*bufsize = *bufsize << 1;
printf("Increasing buffer size to %d\n", *bufsize);
if (NULL == (*buffer = AllocMem(*bufsize, MEMF_CLEAR))) ret_code = FALSE;
else numchars = deadKeyConvert(msg, *buffer, *bufsize - 1, NULL, ievent);
}
/* numchars contains the number of characters placed within the buffer. Key up events and */
/* key sequences that do not generate any data for the program (like deadkeys) will return */
/* zero. Special keys (like HELP, the cursor keys, FKeys, etc.) return multiple characters */
/* that have to then be parsed by the application. Allocation failed above if buffer is NULL*/
if (*buffer != NULL) {
/* if high bit set, then this is a key up otherwise this is a key down */
if (msg->Code & 0x80)
printf("Key Up: ");
else
printf("Key Down: ");
print_qualifiers(msg->Qualifier);
printf(" rawkey #%d maps to %d ASCII character(s)\n", 0x7F & msg->Code, numchars);
for (char_pos = 0; char_pos < numchars; char_pos++) {
realc = c = (*buffer)[char_pos];
if ((c <= 0x1F)||((c >= 0x80)&&(c < 0xa0)))
c = 0x7f;
printf(" %3d ($%02x) = %c\n", realc, realc, c);
}
}
return(ret_code);
}
/* process_window() - simple event loop. Note that the message is not replied
** to until the end of the loop so that it may be used in the doKeys() call.
*/
VOID process_window(struct Window *win, struct InputEvent *ievent,
UBYTE **buffer, ULONG *bufsize)
{
struct IntuiMessage *msg;
BOOL done;
done = FALSE;
while (done == FALSE) {
Wait((1L<<win->UserPort->mp_SigBit));
while ((done == FALSE) && (msg = (struct IntuiMessage *)GetMsg(win->UserPort))) {
switch (msg->Class) { /* handle our events */
case IDCMP_CLOSEWINDOW:
done = TRUE;
break;
case IDCMP_RAWKEY:
if (FALSE == doKeys(msg,ievent,buffer,bufsize))
done = TRUE;
break;
}
ReplyMsg((struct Message *)msg);
}
}
}