;/* 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); } } }