[Contents] [Index] [Help] [Retrace] [Browse <] [Browse >]

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