Copyright (c) Hyperion Entertainment and contributors.
Keymap Library
Contents
- 1 Keymap Library
- 1.1 Keymap Functions
- 1.1.1 Asking for the Default Keymap
- 1.1.2 LoKeyMap and HighKeyMap
- 1.1.3 Setting the Default Keymap
- 1.1.4 Accessing the Keymap for the Current Console
- 1.1.5 Mapping ANSI Strings to Key Codes
- 1.1.6 Mapping Key Codes to ANSI Strings
- 1.1.7 About Qualifiers
- 1.1.8 Keytype Table Entries
- 1.1.9 String-Output Keys
- 1.1.10 Capsable Bit Table
- 1.1.11 Repeatable Bit Table
- 1.1.12 Key Map Standards
- 1.1.13 Dead-Class Keys
- 1.1.14 Double-Dead Keys
- 1.2 Keyboard Layout
- 1.3 Function Reference
- 1.1 Keymap Functions
Keymap Library
Amiga computers are sold internationally with a variety of local keyboards which match the standards of particular countries. All Amigas have keyboards which are physically similar, and keys which output the same low-level raw key code for any particular physical key. However, in different countries, the keycaps of the keys may contain different letters or symbols. Since the physical position of a key determines the raw key code that it generates, raw key codes are not internationally compatible. For instance, on the German keyboard, the Y and Z keys are swapped when compared to the USA keyboard. The second key on the fifth row will generate the same raw key code on all Amiga keyboards, but should be decoded as a Z on a US keyboard and as a Y on a German keyboard.
The Amiga uses the ECMA-94 Latin 1 International 8-bit character set, and can map raw key codes to any desired ANSI character value, string, or escape sequence. This allows national keyboards to be supported by using keymaps. A keymap is a file which describes what character or string is tied to what key code. Generally, the user's startup-sequence will set a system default keymap that is correct for the user's keyboard. The console.device translates the raw key codes into the correct characters based on the installed keymap. This includes the translation of special deadkey sequential key combinations to produce accented international characters.
Programs which perform keyboard input using the console.device, CON:, RAW:, or Intuition VANILLAKEY, will receive custom keymaps, or may need to perform their own translation between raw key codes and ANSI characters. In this chapter, the term ANSI refers to the standard 8-bit character definitions which include printable ASCII characters, special characters, and escape sequences.
Unit V37, keymapping command were only available in the console.device. Keymap.library is a new library in Release 2 (V37). It offers some of the keymap commands of the console.device, enabling applications to inquire after the default keymap and map key codes to ANSI characters. It also provides the ability to map ANSI characters back into raw codes. Unlike the console.device however, it can not be used to select a keymap for only one application, i.e., one console window.
As a prelude to the following material, note that the Amiga keyboard transmits raw key information to the computer in the form of a key position and a transition. Raw key positions range from hexadecimal 00 to 7F. When a key is released, its raw key position, plus hexadecimal 80, is transmitted.
Keymap Functions
Table 34-1: Keymap Library Functions
AskKeyMapDefault() | Ask for a pointer to the current default keymap |
MapANSI() | Encode an ANSI string into key codes |
MapRawKey() | Decode a raw key input event to an ANSI string |
SetKeyMapDefault() | Set the current default keymap |
Table 34-2: Console Device Keymap Commands
CD_ASKKEYMAP | Ask for the current console's keymap |
CD_SETKEYMAP | Set the current console's keymap |
CD_ASKDEFAULTKEYMAP* | Set the current default keymap |
CD_SETDEFAULTKEYMAP** | Ask for a pointer to the current default keymap |
* Obsolete - use AskKeyMapDefault() | |
** Obsolete - use SetKeyMapDefault() |
All of these commands deal with a set of pointers to key translation arrays, known as the KeyMap structure. The KeyMap structure is defined in <devices/keymap.h> and is shown below.
struct KeyMap { UBYTE *km_LoKeyMapTypes; ULONG *km_LoKeyMap; UBYTE *km_LoCapsable; UBYTE *km_LoRepeatable; UBYTE *km_HiKeyMapTypes; ULONG *km_HiKeyMap; UBYTE *km_HiCapsable; UBYTE *km_HiRepeatable; };
The KeyMap structure contains pointers to arrays which define the ANSI character or string that should be produced when a key or a combination of keys are pressed. For example, a keymap might specify that the key with raw value hex 20 should produce the ANSI character "a", and if the Shift key is being held it should produce the character "A".
Asking for the Default Keymap
The AskKeyMapDefault() returns a pointer to the current default keymap. To use the mapping functions in keymap.library it is normally not necessary to call this function. They accept NULL as equivalent to ’use default keymap’ and will call this function for you. You can use this pointer for example to cache the system default in order to temporarily change the keymap your applications uses, or find the keymap in the keymap.resource list of loaded keymaps. You should never change the system wide default keymap unless the user asks you to do so; since the Amiga is a multitasking system, changing the keymap could interfere with the behaviour of other applications.
LoKeyMap and HighKeyMap
[h] High Key Map Hex Values
<thead> </thead> <tbody> </tbody>Key Number | Keycap Legend or Function |
---|---|
40 | Space |
41 | Backspace |
42 | Tab |
43 | Enter |
44 | Return |
45 | Escape |
46 | Delete |
4A | Numeric Pad - character |
4C | Cursor Up |
4D | Cursor Down |
4E | Cursor Forward |
4F | Cursor Backward |
50-59 | Function keys F1-F10 |
5A-5E | Numeric Pad characters (except A1000) |
5F | Help |
60 | Left Shift |
61 | Right Shift |
62 | Caps Lock |
63 | Control |
64 | Left Alt |
65 | Right Alt |
66 | Left Amiga |
67 | Right Amiga |
The keymap table for the low and high keymaps consists of 4-byte entries, one per hex key code.
These entries are interpreted in one of two possible ways:
- As four separate bytes, specifying how the key is to be interpreted when pressed alone, with one qualifier, with another qualifier, or with both qualifiers (where a qualifier is one of three possible keys: Ctrl, Alt, or Shift).
- As a long word containing the address of a string descriptor, where a string of hex digits is to be output when this key is pressed. If a string is to be output, any combination of qualifiers can affect the string that may be transmitted.
- As a longword containing the address of a dead-key descriptor, where additional data describe the character to be output when this key is pressed alone or with another dead key.
boxThe keymap table must be word aligned.The keymap table must begin aligned on a word boundary. Each entry is four bytes long, thereby maintaining word alignment throughout the table. This is necessary because some of the entries may be longword addresses and must be aligned properly for the 68000.
Setting the Default Keymap
The system wide default keymap can be set with the SetKeyMapDefault() function. This function takes a pointer to a loaded keymap. When making a keymap the default you first check whether the keymap has been loaded previously by checking the keymap list of they keymap.resource. If it has not been loaded already, it can be loaded from “devs:Keymaps”. You should add a keymap you loaded to the the keymap list of keymap.resource, This will ensure that other applications which may want to load that keymap will not load a second instance. Once made default, the keymap can never be safely removed from memory, even after if it no longer the default, since other applications may still have and use a pointer to it. Only if you use the keymap for your application only can it be removed from memory once your are done with it.
The following example shows how to set the default keymap. Note that applications (like Shells) will still use the old default keymap.
/*********************************************************************** * * * COPYRIGHTS * * * * Copyright (c) 1991 Commodore-Amiga, Inc. All Rights Reserved. * * * *********************************************************************** * * SetKeyMap.c RKM keymap.library/SetKeyMapDefault() example. * * Monday, 22-Jul-91 12:23:55, Ewout * Thursday, 24-Oct-91 09:48:41, DavidM * * Compiled with SAS/C 5.10a: * lc -cfis -v -d0 -b0 SetKeyMap.c * blink from SetKeyMap.o to SetKeyMap lib lib:amiga.lib */ #include <exec/memory.h> #include <dos/dos.h> #include <dos/rdargs.h> #include <devices/keymap.h> #include <clib/exec_protos.h> #include <clib/dos_protos.h> #include <clib/keymap_protos.h> #include <clib/utility_protos.h> #ifdef PRAGMAS #include <pragmas/exec.h> #include <pragmas/dos.h> #include <pragmas/keymap.h> #include <pragmas/utility.h> #endif struct ExecBase *SysBase; struct DosLibrary *DOSBase; struct Library *UtilityBase; struct Library *KeymapBase; struct KeyMapResource *KMRes; UBYTE *KMPath; LONG main(void); int openall(void); int closeall(int); void exit(int); LONG main(void) { struct RDArgs *readargs; LONG rargs[2]; struct KeyMap *keymap = NULL; struct KeyMapNode *kmnode; UBYTE *kmname; BPTR kmsegment; COUNT i; LONG error = 0; #ifndef PRAGMAS SysBase = (*((struct Library **) 4)); #endif if (openall() != RETURN_OK) return RETURN_FAIL; if (!(readargs = ReadArgs("KEYMAP/A", rargs, NULL))) { error = IoErr(); PrintFault(error, NULL); return closeall(RETURN_FAIL); } kmname = (UBYTE *)rargs[0]; for (i = 0; kmname[i]; i++) kmname[i] = ToLower(kmname[i]); Forbid(); kmnode = (struct KeyMapNode *)FindName(&KMRes->kr_List, kmname); if (kmnode) { /* Found it, already loaded */ keymap = &(kmnode->kn_KeyMap); } Permit(); if (!keymap) { AddPart(KMPath, "DEVS:Keymaps", 32); if (!AddPart(KMPath, kmname, 32)) { error = ERROR_OBJECT_TOO_LARGE; PrintFault(error, kmname); return closeall(RETURN_FAIL); } /* Note: Since there is no arbitration, there is no safe * way to unload a keymap. */ if (!(kmsegment = LoadSeg(KMPath))) { error = IoErr(); PrintFault(error, KMPath); return closeall(RETURN_FAIL); } /* Make sure the keymap didn't get loaded by another * application in the small window we left open. */ Forbid(); kmnode = (struct KeyMapNode *)FindName(&KMRes->kr_List, kmname); if (kmnode) { /* Found it, must just have been loaded */ keymap = &(kmnode->kn_KeyMap); } else { /* Turn this BPTR into a CPTR and point to the node */ kmnode = (struct KeyMapNode *)((((ULONG)kmsegment) << 2) + sizeof(BPTR)); keymap = &(kmnode->kn_KeyMap); /* Add it to the keymap resource list */ AddHead(&(KMRes->kr_List), (struct Node *)kmnode); } Permit(); } if (keymap) { /* Just being informative */ if (keymap == AskKeyMapDefault()) { VFPrintf(Output(), "%s: Keymap already default\n", rargs); return closeall(RETURN_WARN); } else SetKeyMapDefault(keymap); } return closeall(RETURN_OK); } int openall(void) { DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 33); if (DOSBase == NULL) return closeall(RETURN_FAIL); UtilityBase = DOSBase->dl_UtilityBase; KeymapBase = OpenLibrary("keymap.library", 36); if (KeymapBase == NULL) { Write(Output(), "Kickstart 2.0 required\n", 23); return closeall(RETURN_FAIL); } KMRes = (struct KeyMapResource *)OpenResource("keymap.resource"); if (KMRes == NULL) return closeall(RETURN_FAIL); KMPath = AllocMem(32, MEMF_CLEAR); if (KMPath == NULL) { PrintFault(ERROR_NO_FREE_STORE, NULL); return closeall(RETURN_FAIL); } return RETURN_OK; } int closeall(int rc) { if (KMPath) FreeMem(KMPath, 32); /* ** KMRes: There is no closure for resources */ if (KeymapBase) CloseLibrary((struct Library *)KeymapBase); if (DOSBase) CloseLibrary((struct Library *)DOSBase); return rc; }
Accessing the Keymap for the Current Console
The function AskKeyMap() shown below does not return a pointer to a table of pointers to currently assigned key mapping. Instead, it copies the current set of pointers to a user-designated area of memory. AskKeyMap() returns a TRUE or FALSE value that says whether or not the function succeeded.
The function SetKeyMap(), also shown below, copies the designated key map data structure to the console device. Thus this routine is complementary to AskKeymap() in that it can restore an original key mapping as well as establish a new one.
/* These functions require that you have set up a port and * io request, and have opened the console device as shown * earlier in the chapter. * They also require this additional include file. */ #include <devices/keymap.h> BOOL AskKeyMap(struct IOStdReq *request, struct KeyMap *keymap) { request->io_Command = CD_ASKKEYMAP; request->io_Length = sizeof(struct KeyMap); request->io_Data = (APTR)keymap; /* where to put it */ DoIO(request); if(request->io_Error) return(FALSE); else return(TRUE); /* if no error, it worked. */ } BOOL SetKeyMap(struct IOStdReq *request,struct KeyMap *keymap) { request->io_Command = CD_SETKEYMAP; request->io_Length = sizeof(struct KeyMap); request->io_Data = (APTR)keymap; /* where to get it */ DoIO(request); if(request->io_Error) return(FALSE); else return(TRUE); /* if no error, it worked. */ }
Mapping ANSI Strings to Key Codes
ANSI strings can be translated to key codes, complete with qualifiers and (double) dead keys with the MapANSI() function.
LONG MapANSI(STRPTR string, LONG stringlength, STRPTR buffer, LONG bufferlength, struct KeyMap *keymap);
The string argument is a pointer to an ANSI string, of length stringlength. The buffer argument is a pointer to the memory block where the translated key codes will be placed. The length of this buffer must be indicated in WORDs since each translation will occupy one byte for the key code and one for the qualifier. Since one ANSI character can be translated to two dead keys and one key, the buffer must be at least 3 WORDs per character in the string to be translated. The keymap argument can be set to NULL if the default keymap is to be used, or can be a pointer to a KeyMap structure. Upon return, the function will indicate how many key code/qualifier combinations are placed in the buffer or a negative number in case an error occured. If zero is returned, the character could not be translated.
The following example shows the usage of MapANSI() and demonstrates how returned key codes can be processed.
/*********************************************************************** * * * COPYRIGHTS * * * * Copyright (c) 1991 Commodore-Amiga, Inc. All Rights Reserved. * * * *********************************************************************** * * MapANSI.c RKM keymap.library/MapANSI() example. * * Tuesday, 23-Jul-91 12:56:46, Ewout * Tuesday, 29-Oct-91 16:17:32, DavidM * * Compiled with SAS/C 5.10a: * lc -cfis -v -d0 -b0 MapANSI.c * blink from MapANSI.o to MapANSI * lib lib:amiga.lib ; if you don't have pragmas */ # include <exec/memory.h> # include <exec/ports.h> # include <exec/io.h> # include <dos/dos.h> # include <dos/rdargs.h> # include <devices/input.h> # include <devices/inputevent.h> # include <clib/exec_protos.h> # include <clib/dos_protos.h> # include <clib/keymap_protos.h> #ifdef PRAGMAS # include <pragmas/exec_pragmas.h> # include <pragmas/dos_pragmas.h> # include <pragmas/keymap_pragmas.h> #endif struct ExecBase *SysBase = NULL; struct DosLibrary *DOSBase = NULL; struct Library *KeymapBase = NULL; struct MsgPort *ReplyPort = NULL; struct IOStdReq *IORequest = NULL; struct InputEvent *InputEvent = NULL; LONG main(VOID); LONG openall(VOID); LONG closeall(LONG); LONG main(VOID) { struct RDArgs *readargs; LONG rargs[1]; UBYTE *string; UBYTE *tmp1; UBYTE *tmp2; UBYTE iebuffer[6]; /* Space for two dead keys */ /* + 1 key + qualifiers */ COUNT i; LONG rc = 0; LONG error = 0; #ifndef PRAGMAS /* set up SysBase */ SysBase = (*((struct Library **) 4)); #endif if (openall() != RETURN_OK) return RETURN_FAIL; if (!(readargs = ReadArgs("STRING/A/F", rargs, NULL))) { error = IoErr(); PrintFault(error, NULL); return closeall(RETURN_FAIL); } string = (UBYTE *)rargs[0]; InputEvent->ie_Class = IECLASS_RAWKEY; IORequest->io_Data = (APTR)InputEvent; IORequest->io_Command = IND_WRITEEVENT; IORequest->io_Flags = 0; IORequest->io_Length = sizeof(struct InputEvent); /* Turn each character into an InputEvent */ tmp1 = string; while (*tmp1) { /* Convert one character, use default key map */ i = MapANSI(tmp1, 1, iebuffer, 3, NULL); /* Make sure we start without deadkeys */ InputEvent->ie_Prev1DownCode = InputEvent->ie_Prev1DownQual = 0; InputEvent->ie_Prev2DownCode = InputEvent->ie_Prev2DownQual = 0; tmp2 = iebuffer; switch (i) { case -2: VFPrintf(Output(), "Internal error\n", NULL); rc = RETURN_FAIL; break; case -1: VFPrintf(Output(), "Overflow\n", NULL); rc = RETURN_FAIL; break; case 0: VFPrintf(Output(), "Can't generate code\n", NULL); break; case 3: InputEvent->ie_Prev2DownCode = *tmp2++; InputEvent->ie_Prev2DownQual = *tmp2++; /* FALL THROUGH */ case 2: InputEvent->ie_Prev1DownCode = *tmp2++; InputEvent->ie_Prev1DownQual = *tmp2++; /* FALL THROUGH */ case 1: InputEvent->ie_Code = *tmp2++; InputEvent->ie_Qualifier = *tmp2; break; } if (rc == RETURN_OK) { if (DoIO((struct IORequest *)IORequest)) { VFPrintf(Output(), "IO Failed\n", NULL); rc = RETURN_FAIL; } } if (rc != RETURN_OK) break; tmp1++; } FreeArgs(readargs); return closeall(rc); } LONG DeviceError = -1; int openall(void) { DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 33); if (DOSBase == NULL) return closeall(RETURN_FAIL); KeymapBase = OpenLibrary("keymap.library", 36); if (KeymapBase == NULL) { Write(Output(), "Kickstart 2.0 required\n", 23); return closeall(RETURN_FAIL); } /* Open input.device */ ReplyPort = CreateMsgPort(); if (ReplyPort == NULL) { PrintFault(IoErr(), NULL); return closeall(RETURN_FAIL); } IORequest = CreateIORequest(ReplyPort, sizeof(struct IOStdReq)); if (IORequest == NULL) { PrintFault(IoErr(), NULL); return closeall(RETURN_FAIL); } DeviceError = OpenDevice("input.device", NULL, (struct IORequest *)IORequest, NULL); if (DeviceError) { PrintFault(IoErr(), NULL); return closeall(RETURN_FAIL); } InputEvent = AllocMem(sizeof(struct InputEvent), MEMF_CLEAR); if (InputEvent == NULL) closeall(RETURN_FAIL); return RETURN_OK; } LONG closeall(LONG rc) { if (InputEvent) FreeMem(InputEvent, sizeof(struct InputEvent)); if (DeviceError) CloseDevice((struct IORequest *)IORequest); if (IORequest) DeleteIORequest((struct IORequest *)IORequest); if (ReplyPort) DeleteMsgPort(ReplyPort); if (KeymapBase) CloseLibrary((struct Library *)KeymapBase); if (DOSBase) CloseLibrary((struct Library *)DOSBase); return rc; }
Mapping Key Codes to ANSI Strings
MapRawKey()
is the opposite function of MapANSI(). It converts the key codes in input events to an ANSI character or string.
WORD MapRawKey(struct InputEvent *inputevent, STRPTR buffer, WORD bufferlength, struct Keymap *keymap);
MapRawKey()
takes an IECLASS_RAWKEY inputevent, which may be chained, and converts the key codes to ANSI characters which are placed in the specified buffer. If the buffer would overflow, for example because a longer string is attached to a key, -1 will be returned. If no error occured, MapRawKey() will return the number of bytes written in the buffer. Like MapANSI(), the keymap argument can be set to NULL if the default keymap is to be used for translation, or can be a pointer to a specific KeyMap structure.
The following example shows how to implement the MapRawKey() function.
/*********************************************************************** * * * COPYRIGHTS * * * * Copyright (c) 1991 Commodore-Amiga, Inc. All Rights Reserved. * * * *********************************************************************** * * MapRawKey.c * * Monday, 03-Nov-91 11:52:06, DavidM * Monday, 22-Jul-91 16:02:30, Ewout * * Compiled with SAS/C 5.10a: * lc -cfis -v -d0 -b0 MapRawKey.c * blink from MapRawKey.o to MapRawKey * lib lib:amiga.lib ; if you don't have pragmas * */ #include <exec/memory.h> #include <dos/dos.h> #include <intuition/intuition.h> #include <devices/inputevent.h> #include <clib/exec_protos.h> #include <clib/dos_protos.h> #include <clib/keymap_protos.h> #include <clib/intuition_protos.h> #ifdef PRAGMAS #include <pragmas/exec_pragmas.h> #include <pragmas/dos_pragmas.h> #include <pragmas/keymap_pragmas.h> #include <pragmas/intuition_pragmas.h> #endif struct ExecBase *SysBase = NULL; struct DosLibrary *DOSBase = NULL; struct IntuitionBase *IntuitionBase = NULL; struct Library *KeymapBase = NULL; BPTR fh = (BPTR)0; LONG main(VOID); BOOL GetInfoDataFromFH(BPTR, struct InfoData *); LONG openall(VOID); LONG closeall(LONG); LONG main(VOID) { struct InfoData infodata; struct Window *window; struct IntuiMessage *imsg; APTR *eventptr; struct InputEvent inputevent; LONG signal; LONG windowsignal; UBYTE buffer[8]; COUNT i; BOOL ABORT = FALSE; LONG rc = 0; LONG error = 0; #ifndef PRAGMAS /* set up SysBase */ SysBase = (*((struct Library **) 4)); #endif if (openall() != RETURN_OK) return RETURN_FAIL; if (GetInfoDataFromFH(fh, &infodata)) { window = (struct Window *)infodata.id_VolumeNode; /* Let Intuition create a IDCMP port for us */ if (ModifyIDCMP(window, IDCMP_CLOSEWINDOW|IDCMP_RAWKEY)) { windowsignal = 1L << window->UserPort->mp_SigBit; /* Initialize InputEvent we're gonna use */ inputevent.ie_Class = IECLASS_RAWKEY; inputevent.ie_SubClass = 0; do { signal = Wait(windowsignal|SIGBREAKF_CTRL_C); if (signal & SIGBREAKF_CTRL_C) ABORT = TRUE; while (imsg = (struct IntuiMessage *)GetMsg(window->UserPort)) { switch(imsg->Class) { case IDCMP_CLOSEWINDOW: ABORT = TRUE; break; case IDCMP_RAWKEY: inputevent.ie_Code = imsg->Code; inputevent.ie_Qualifier = imsg->Qualifier; /* Make sure deadkeys and qualifiers are taken * into account. */ eventptr = imsg->IAddress; inputevent.ie_EventAddress = *eventptr; i = MapRawKey(&inputevent, buffer, 8, NULL); if (i == -1) Write(fh, "Overflow", 8); else if (i) Write(fh, buffer, i); break; } ReplyMsg((struct Message *)imsg); } } while (ABORT == FALSE); /* Remove the IDCMP port we used */ ModifyIDCMP(window, 0); } else { rc = RETURN_FAIL; Write(Output(), "Can't modify IDCMP\n", 19); } } else error = ERROR_NO_FREE_STORE; SetIoErr(error); if (error) { rc = RETURN_FAIL; PrintFault(error, NULL); } return closeall(rc); } /* Get InfoData on Filehandle. */ BOOL GetInfoDataFromFH(BPTR fh, struct InfoData *infodata) { struct MsgPort *packetport; struct MsgPort *replyport; struct StandardPacket *packet; BOOL result = FALSE; packetport = (struct MsgPort *)(((struct FileHandle *)(fh << 2))->fh_Type); if (packet = AllocMem(sizeof(struct StandardPacket), MEMF_CLEAR)) { if (replyport = CreateMsgPort()) { /* initialize packet */ packet->sp_Msg.mn_Node.ln_Name = (UBYTE *)&(packet->sp_Pkt); packet->sp_Pkt.dp_Link = &(packet->sp_Msg); packet->sp_Pkt.dp_Port = replyport; packet->sp_Pkt.dp_Type = ACTION_DISK_INFO; packet->sp_Pkt.dp_Arg1 = ((ULONG)infodata >> 2); PutMsg(packetport, (struct Message *)packet); WaitPort(replyport); while(GetMsg(replyport)); result = (BOOL)packet->sp_Pkt.dp_Res1; DeleteMsgPort(replyport); } FreeMem(packet, sizeof(struct StandardPacket)); } return((result) ? TRUE : FALSE); } LONG openall(VOID) { DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 33); if (DOSBase == NULL) return closeall(RETURN_FAIL); KeymapBase = OpenLibrary("keymap.library", 36); if (KeymapBase == NULL) { Write(Output(), "Kickstart 2.0 required\n", 23); return closeall(RETURN_FAIL); } IntuitionBase = OpenLibrary("intuition.library", 33); if (IntuitionBase == NULL) return closeall(RETURN_FAIL); fh = Open("RAW:0/0/640/100/MapRawKey/CLOSE", MODE_NEWFILE); if (fh == NULL) { PrintFault(IoErr(), NULL); closeall(RETURN_FAIL); } return RETURN_OK; } LONG closeall ( LONG rc ) { if (fh) Close(fh); if (IntuitionBase) CloseLibrary(IntuitionBase); if (KeymapBase) CloseLibrary(KeymapBase); if (DOSBase) CloseLibrary((struct Library *)DOSBase); return rc; }
About Qualifiers
As you may have noticed, there are three possible qualifiers, but only a 4-byte space in the table for each key. This does not allow space to describe what the computer should output for all possible combinations of qualifiers. A solution exists, however, for “vanilla” keys, such as the alphabetic keys. Here is how that works.
Keys of type KC_VANILLA use the 4 bytes to represent the data output for the key alone, Shifted key, Alt’ed key, and Shifted-and-Alt’ed key. Then for the Ctrl-key-plus-vanilla-key, use the code for the key alone with bits 6 and 5 set to 0.
For other keys, such as the Return key or Esc key, the qualifiers specified in the keytypes table (up to two) are the qualifiers used to establish the response to the key. This is done as follows. In the keytypes table, the values listed for the key types are those listed for the qualifiers in <devices/keymap.h> and <devices/keymap.i>.
Specifically, these qualifier equates are:
<tbody> </tbody>KC_NOQUAL | 0x00 |
KCF_SHIFT | 0x01 |
KCF_ALT | 0x02 |
KCF_CONTROL | 0x04 |
KC_VANILLA | 0x07 |
KCF_DOWNUP | 0x08 |
KCF_STRING | 0x40 |
As shown above, the qualifiers for the various types of keys occupy specific bit positions in the key types control byte.
boxThe Vanilla Qualifier Does Not Mean Plain.The qualifier KC_VANILLA is equivalent to KCF_SHIFT+KCF_ALT+KCF_CONTROL.
In assembly code, a keymap table entry looks like this:
SOME_KEY: DC.B VALUE_1, VALUE_2, VALUE_3, VALUE_4
This table shows how to interpret the keymap for various combinations of the qualifier bits:
[h] Keymap Qualifier Bits
lllll
& 4lThen data at this position in the keytable is
If Keytype is: & 4loutput when the key is pressed along with:
KC_NOQUAL & – & – & – & alone
KCF_SHIFT & – & – & Shift & alone
KCF_ALT & – & – & Alt & alone
KCF_CONTROL & – & – & Ctrl & alone
KCF_ALT+KCF_SHIFT & Shift+Alt & Alt & Shift & alone
KCF_CONTROL+KCF_ALT & Ctrl+Alt & Ctrl & Alt & alone
KCF_CONTROL+KCF_SHIFT & Ctrl+Shift & Ctrl & Shift & alone
KC_VANILLA & Shift+Alt & Alt & Shift & alone<math>^\star</math>
<math>^\star</math>Special case – Ctrl key, when pressed with one of the alphabet keys and certain others, is to output key-alone value with the bits 6 and 5 set to zero.
Keytype Table Entries
The vectors named km_LoKeyTypes and km_HiKeyTypes contain one byte per raw key code. This byte defines the entry type that is made in the key table by a set of bit positions.
Possible key types are:
Any of the qualifier groupings noted above
KCF_STRING
+ any combination of KCF_SHIFT, KCF_ALT, KCF_CONTROL (or KC_NOQUAL) if the result of pressing the key is to be a stream of bytes (and key-with-one-or-more-qualifiers is to be one or more alternate streams of bytes).
Any
key can be made to output up to eight unique byte streams if KCF_STRING is set in its keytype. The only limitation is that the total length of all of the strings assigned to a key must be within the “jump range” of a single byte increment. See the “String-Output Keys” section below for more information.
KCF_DEAD
+ any combination of KCF_SHIFT, KCF_ALT, KCF_CONTROL (or KC_NOQUAL) if the key is a dead-class key and can thus modify or be modified by another dead-class key. See the “Dead-Class Keys” section below for more information.
The low keytype table covers the raw key codes from hex 00-3F and contains one byte per key code. Therefore this table contains 64 (decimal) bytes. The high keytype table covers the raw key codes from hex 40-67 and contains 38 (decimal) bytes.
String-Output Keys
When a key is to output a string, the keymap table contains the address of a string descriptor in place of a 4-byte mapping of a key as shown above. Here is a partial table for a new high keymap table that contains only three entries thus far. The first two are for the space bar and the backspace key; the third is for the tab key, which is to output a string that says “[TAB]”. An alternate string, “[SHIFTED-TAB]”, is also to be output when a shifted Tab key is pressed.
newHiMapTypes: DC.B KCF_ALT,KC_NOQUAL, ;key 41 DC.B KCF_STRING+KCF_SHIFT, ;key 42 ... ;(more) newHiMap: DC.B 0,0,$A0,$20 ;key 40: space bar, and Alt-space bar DC.B 0,0,0,$08 ;key 41: Back Space key only DC.L newkey42 ;key 42: new definition for string to output for Tab key ... ;(more) newkey42: DC.B new42ue - new42us ;length of the unshifted string DC.B new42us - newkey42 ;number of bytes from start of ;string descriptor to start of this string DC.B new42se - new42ss ;length of the shifted string DC.B new42ss - newkey42 ;number of bytes from start of ;string descriptor to start of this string new42us: DC.B '[TAB]' new42ue: new42ss: DC.B '[SHIFTED-TAB]' new42se:
The new high map table points to the string descriptor at address newkey42. The new high map types table says that there is one qualifier, which means that there are two strings in the key string descriptor.
Each string in the descriptor takes two bytes in this part of the table: the first byte is the length of the string, and the second byte is the distance from the start of the descriptor to the start of the string. Therefore, a single string (KCF_STRING + KC_NOQUAL) takes 2 bytes of string descriptor. If there is one qualifier, 4 bytes of descriptor are used. If there are two qualifiers, 8 bytes of descriptor are used. If there are 3 qualifiers, 16 bytes of descriptor are used. All strings start immediately following the string descriptor in that they are accessed as single-byte offsets from the start of the descriptor itself. Therefore, the distance from the start of the descriptor to the last string in the set (the one that uses the entire set of specified qualifiers) must start within 255 bytes of the descriptor address.
Because the length of the string is contained in a single byte, the length of any single string must be 255 bytes or less while also meeting the “reach” requirement. However, the console input buffer size limits the string output from any individual key to 32 bytes maximum.
The length of a keymap containing string descriptors and strings is variable and depends on the number and size of the strings that you provide.
Capsable Bit Table
The vectors called km_LoCapsable and km_HiCapsable point to the first byte in an 8-byte table that contains more information about the keytable entries. Specifically, if the Caps Lock key has been pressed (the Caps Lock LED is on) and if there is a bit on in that position in the capsable map, then this key will be treated as though the Shift key is now currently pressed. For example, in the default key mapping, the alphabetic keys are “capsable” but the punctuation keys are not. This allows you to set the Caps Lock key, just as on a normal typewriter, and get all capital letters. However, unlike a normal typewriter, you need not go out of Caps Lock to correctly type the punctuation symbols or numeric keys.
In the table, the bits that control this feature are numbered from the lowest bit in the byte, and from the lowest memory byte address to the highest. For example, the bit representing capsable status for the key that transmits raw code 00 is bit 0 in byte 0; for the key that transmits raw code 08 it is bit 0 in byte 1, and so on.
There are 64 bits (8-bytes) in each of the two capsable tables.
Repeatable Bit Table
For both the low and high key maps there is an 8-byte table that provides one bit per possible raw key code. This bit indicates whether or not the specified key should repeat at the rate set by the Preferences program. The bit positions correspond to those specified in the capsable bit table.
If there is a 1 in a specific position, the key can repeat. The vectors that point to these tables are called km_LoRepeatable and km_HiRepeatable.
Key Map Standards
Users and programs depend on certain predictable behaviors from all keyboards and keymaps. With the exception of dead-class keys (see “Dead-Class Keys” section), mapping of keys in the low key map should follow these general rules:
- When pressed alone, keys should transmit the ASCII equivalent of the unshifted letter or lower symbol on the keycap.
- When Shifted, keys should transmit the ASCII equivalent of the shifted letter or upper symbol printed on the keycap.
- When Alt’ed, keys should generally transmit the same character (or act as the same deadkey) as the Alt’ed key in the usa1 keymap.
- When pressed with CTRL alone, alphabetic keys should generally transmit their unshifted value but with bits 5 and 6 cleared. This allows keyboard typing of “control characters.” For example, the C key (normally value $63) should transmit value $03 (Ctrl-C) when Ctrl and C are pressed together.
The keys in the high key map (keys with raw key values $40 and higher) are generally non-alphanumeric keys such as those used for editing (backspace, delete, cursor keys, etc.), and special Amiga keys such as the function and help keys. Keymaps should translate these keys as to the same values or strings as those shown in the table labeled “ROM Default Key Mapping”.
In addition to their normal unshifted and shifted values, the following translations are standard for particular qualified high keymap keys:
[h]
<tbody> </tbody>If Used with Qualifier | ||
Key | Generates This Value | Generates This Value |
Space | $20 | $A0 with qualifier KCF_ALT |
Return | $0D | $0A with qualifier KCF_CONTROL |
Esc | $1B | $9B with qualifier KCF_ALT |
Dead-Class Keys
All of the national keymaps, including USA, contain dead-class keys. This term refers to keys that either modify or can themselves be modified by other dead-class keys. There are two types of dead-class keys: dead and deadable. A dead key is one which can modify certain keys pressed immediately following. For example, on the German keyboard there is a dead key marked with the grave accent (`). The dead key produces no console output, but when followed by (for instance) the A key, the combination will produce the a-grave (à) character (National Character Code $E0). On the U.S. keyboard, Alt-G is the deadkey used to add the grave accent (`) to the next appropriate character typed. A deadable key is one that can be prefixed by a dead key. The A key in the previous example is a deadable key. Thus, a dead key can only affect the output of a deadable key.
For any key that is to have a dead-class function, whether dead or deadable, the qualifier KCF_DEAD flag must be included in the entry for the key in the KeyMapTypes table. The KCF_DEAD type may also be used in conjunction with the other qualifiers. Furthermore, the key’s keymap table entry must contain the longword address of the key’s dead-key descriptor data area in place of the usual 4 ASCII character mapping.
Below is an excerpt from the Amiga 1000 German key map which is referred to in the following discussion.
KMLowMapType: DC.B KCF_DEAD+KC_VANILLA ; aA (Key 20) ... ; (more...) DC.B KCF_DEAD+KC_VANILLA ; hH (Key 20) ... ; (more...) KMLowMap: DC.L key20 ; a, A, ae, AE ... ; (more...) DC.L key25 ; h, H, dead ^ ... ; (more...) ;------ possible dead keys key25: DC.B 0,'h',0,'H' ; h, H DC.B DPF_DEAD,3,DPF_DEAD,3 ; dead ^, dead ^ DC.B 0,$08,0,$08,0,$88,0,$88 ; control translation ... ; (more...) ;------ deadable keys (modified by dead keys) key20: ; a, A, ae, AE DC.B DPF_MOD,key20u-key20 ; deadable flag, number of ; bytes from start of key20 ; descriptor to start of un- ; shifted data DC.B DPF_MOD,key20s-key20 ; deadable flag, number of ; bytes from start of key20 ; descriptor to start of shift- ; ed data DC.B 0,$E6,0,$C6 ; null flags followed by rest DC.B 0,$01,0,$01,0,$81,0,$81 ; of values (ALT, CTRL...) key20u: DC.B 'a',$E1,$E0,$E2,$E3,$E4 ; 'a' alone and characters to ; output when key alone is ; prefixed by a dead key DC.B $E1,$E1,$E2,$E1,$E1,$E1 ; most recent is ' DC.B $E0,$E2,$E0,$E0,$E0,$E0 ; most recent is ` key20s: DC.B 'A',$C1,$C0,$C2,$C3,$C4 ; SHIFTed 'a' and characters to ; output when SHIFTed key is ; prefixed by a dead key DC.B $C1,$C1,$C2,$C1,$C1,$C1 ; most recent is ' DC.B $C0,$C2,$C0,$C0,$C0,$C0 ; most recent is `
In the example, key 25 (the H key) is a dead key and key 20 (the A key) is a deadable key. Both keys use the addresses of their descriptor data areas as entries in the LoKeyMap table. The LoKeyMapTypes table says that there are four qualifiers for both: the requisite KCF_DEAD, as well as KCF_SHIFT, KCF_ALT, and KCF_CONTROL. The number of qualifiers determine length and arrangement of the descriptor data areas for each key. The next table shows how to interpret the KeyMapTypes for various combinations of the qualifier bits. For each possible position a pair of bytes is needed. The first byte in each pair tells how to interpret the second byte (more about this below).
[h] Dead Key Qualifier Bits
|l|l|l|l|l|l|l|l|l|
& 8lThen the pair of bytes in this position in the dead-class key
If type is: & 8ldescriptor data is output when the key is pressed along with:
NOQUAL & alone & – & – & – & – & – & – & –
A & alone & A & – & – & – & – & – & –
C & alone & C & – & – & – & – & – & –
S & alone & S & – & – & – & – & – & –
A+C & alone & A & C & A+C & – & – & – & –
A+S & alone & S & A & A+S & – & – & – & –
C+S & alone & S & C & C+S & – & – & – & –
S+A+C (VANILLA) & alone & S & A & S+A & C & C+S & C+A & C+S+A
The abbreviations A, C, S stand for KCF_ALT, KCF_CONTROL, and KCF_SHIFT, respectively. Also note that the ordering is reversed from that in the normal KeyMap table.
Because keys 20 and 25 each use three qualifier bits (not including KCF_DEAD), according to the table there must be 8 pairs of data, arranged as shown. Had only KCF_ALT been set, for instance, (not including KCF_DEAD), just two pairs would have been needed.
As mentioned earlier, the first byte of each data pair in the descriptor data area specifies how to interpret the second byte. There are three possible values: 0, DPF_DEAD and DPF_MOD. In the Amiga 1000 German keymap listed above, DPF_DEAD appears in the data for key 25, while DPF_MOD is used for key 20. It is the use of these flags that determines whether a dead-class key has dead or deadable function. A value of zero causes the unrestricted output of the following byte.
If the flag byte is DPF_DEAD, then that particular key combination (determined by the placement of the pair of bytes in the data table) is dead and will modify the output of the next key pressed (if deadable). How it modifies is controlled by the second byte of the pair which is used as an index into part(s) of the data area for ALL the deadable (DPF_MOD set) keys.
Before going further, an understanding of the structure of a descriptor data area wherein DPF_MOD is set for one (or more) of its members is necessary. Referring to the example, we see that DPF_MOD is set for the first and second pairs of bytes. According to its LoKeyMapTypes entry, and using the table labeled “Dead Key Qualifier Bits” as a guide, these pairs represent the alone and SHIFTed values for the key. When DPF_MOD is set, the byte immediately following the flag must be the offset from the start of the key’s descriptor data area to the start of a table of bytes describing the characters to output when this key combination is preceded by any dead keys. This is where the index mentioned above comes in. The value of the index from a prefixing dead key is used to determine which of the bytes from the deadable keys special table to output. The byte in the index+1 position is sent out. (The very first byte is the value to output if the key was not prefixed by a dead key.) Thus, if Alt-H is pressed (dead) and then Shift-A, an ‘a’ with a circumflex (^) accent will be output. This is because:
- The byte pair for the ALT position of the H key (key 25) is DPF_DEAD,3 so the index is 3.
- The byte pair for the SHIFT position of the A key (key 20) is DPF_MOD, key20s-key20, so we refer to the table-of-bytes at key20s.
- The third+1 byte of the table-of-bytes is $C2, an ‘a’ character.
boxA Note About Table Size.The number of bytes in the table-of-bytes for all deadable keys must be equal to the highest index value of all dead keys plus 1.
Double-Dead Keys
Double-dead keys are an extension of the dead-class keys explained above. Unlike normal dead keys wherein one dead key of type DPF_DEAD can modify a second of type DPF_MOD, double-dead keys employ two consecutive keys of type DPF_DEAD to together modify a third of type DPF_MOD.
For example, the key on the German keyboard labeled with single quotes (`') is a double-dead key. When this key is pressed alone and then pressed again shifted, there is no output. But when followed by an appropriate third key, for example the A key, the three keypresses combine to produce an ‘a’ with a circumflex (^) accent (character code $E2). Thus the double-dead pair qualify the output of the A key.
The system always keeps the last two down key codes for possible further translation. If they are both of type DPF_DEAD and the key immediately following is DPF_MOD then the two are used to form an index into the (third) key’s translation table as follows:
In addition to the index found after the DPF_DEAD qualifier in a normal dead key, a second factor is included in the high nibble of double-dead keys (it is shifted into place with DP_2DFACSHIFT). Its value equals the total number of dead key types + 1 in the keymap. This second index also serves as an identifying flag to the system that two dead keys can be significant.
When a key of type DPF_MOD is pressed, the system checks the two key codes which preceded the current one. If they were both DPF_DEAD then the most recent of the two is checked for the double-dead index/flag. If it is found then a new index is formed by multiplying the value in lower nibble with that in the upper. Then, the lower nibble of the least recent DPF_DEAD key is added in to form the final offset.
Finally, this last value is used as an index into the translation table of the current, DPF_MOD, key.
The translation table of all deadable (DPF_MOD) keys has (number of dead key types + 1)<math>\times</math>(number of double dead key types + 1) entries, arranged in (number of double dead key types + 1) rows of (number of dead key types + 1) entries.
This is because as indices are assigned for dead keys in the keymap, those that are double dead keys are assigned the lower numbers.
Following is a code fragment from the German (d) keymap source:
key0C: DC.B DPF_DEAD,1+(6<<DP_2DFACSHIFT) ; dead ' DC.B DPF_DEAD,2+(6<<DP_2DFACSHIFT) ; dead ` DC.B 0,'=',0,'+' ; =, + key20: ; a, A, ae, AE DC.B DPF_MOD,key20u-key20,DPF_MOD,key20s-key20 DC.B 0,$E6,0,$C6 DC.B 0,$01,0,$01,0,$81,0,$81 ; control translation key20u: DC.B 'a',$E1,$E0,$E2,$E3,$E4 DC.B $E1,$E1,$E2,$E1,$E1,$E1 ; most recent is ' DC.B $E0,$E2,$E0,$E0,$E0,$E0 ; most recent is ` key20s: DC.B 'A',$C1,$C0,$C2,$C3,$C4 DC.B $C1,$C1,$C2,$C1,$C1,$C1 ; most recent is ' DC.B $C0,$C2,$C0,$C0,$C0,$C0 ; most recent is `
Raw key0C, the German single quotes (`') key, is a double dead key. Pressing this key alone, then again while the shift key is down will produce no output but will form a double-dead qualifier. The output of key20 (A), a deadable key, will consequently be modified, producing an “a” with a circumflex (^) accent. The mechanics are as follows:
- When key0C is pressed alone the DPF_DEAD of the first byte pair in the key’s table indicates that the key as dead. The second byte is then held by the system.
- Next, when key0C is pressed again, this time with the Shift key down, the DPF_DEAD of the second byte pair (recall that the second pair is used because of the SHIFT qualifier) again indicates the key is a dead key. The second byte of this pair is also held by the system.
- Finally, when the A key is pressed the system recalls the latter of the two bytes it has saved. The upper nibble, $6, is multiplied by the lower nibble, $2. The result, $0C, is then added to the lower nibble of the earlier of the two saved bytes, $1. This new value, $0D, is used as an index into the (unshifted) translation table of key20. The character at position $0D is character $E2, an ‘a’ with a circumflex (^) accent.
boxNote About Double Dead Keys.If only one double-dead key is pressed before a deadable key then the output is the same as if the double-dead were a normal dead key. If shifted key0C is pressed on the German keyboard and then immediately followed by key20, the output produced is character $E0, ‘à’. As before, the upper nibble is multiplied with the lower, resulting in $0C. But because there was no second dead-key, this product is used as the final index.
Keyboard Layout
The keys with key codes $2B and $30 in the following keyboard diagrams are keys which are present on some national Amiga keyboards.
Figure 34-1: Amiga 1000 Keyboard Showing Key Codes in Hex
Figure 34-2: Amiga 500/2000 Keyboard Showing Key Codes in Hex
The default values given above correspond to the values the console device will return when these keys are pressed with the keycaps as shipped with the standard American keyboard.
ROM Default (USA0) and USA1 Console Key Mapping
|l|l|l|l|
Raw & & Unshifted & Shifted
Key & Keycap & Default & Default
Number & Legend & Value & Value
00 & ` ~ & ` (Accent grave) & ~ (tilde)
01 & 1 ! & 1 & !
02 & 2 @ & 2 & @
03 & 3 # & 3 & #
04 & 4 $ & 4 & $
05 & 5 % & 5 & %
06 & 6 ^ & 6 & ^
07 & 7 & & 7 & &
08 & 8 * & 8 &
09 & 9 ( & 9 & (
0A & 0 ) & 0 & )
0B & - _ & - (Hyphen) & _ (Underscore)
0C & = + & = & +
0D & <math>\backslash</math> | & <math>\backslash</math> & |
0E & 3l(undefined)
0F & 0 & 0 (Zero) & 0 (Numeric pad)
10 & Q & q & Q
11 & W & w & W
12 & E & e & E
13 & R & r & R
14 & T & t & T
15 & Y & y & Y
16 & U & u & U
17 & I & i & I
18 & O & o & O
19 & P & p & P
1A & [ { & [ & {
1B & ] } & ] & }
1C & 3l(undefined)
1D & 1 & 1 & 1 (Numeric pad)
1E & 2 & 2 & 2 (Numeric pad)
1F & 3 & 3 & 3 (Numeric pad)
20 & A & a & A
21 & S & s & S
22 & D & d & D
23 & F & f & F
24 & G & g & G
25 & H & h & H
26 & J & j & J
27 & K & k & K
28 & L & l & L
29 & ; : & ; & :
2A & ' " & ' (single quote) & "
2B & 3l(not on U.S. keyboards)
2C & 3l(undefined)
2D & 4 & 4 & 4 (Numeric pad)
2E & 5 & 5 & 5 (Numeric pad)
2F & 6 & 6 & 6 (Numeric pad)
30 & 3l(not on U.S. keyboards)
ROM Default (USA0) and USA1 Console Key Mapping (continued)
|l|l|l|l|
Raw & & Unshifted & Shifted
Key & Keycap & Default & Default
Number & Legend & Value & Value
31 & Z & z & Z
32 & X & x & X
33 & C & c & C
34 & V & v & V
35 & B & b & B
36 & N & n & N
37 & M & m & M
38 & , < & , (comma) & <
39 & . > & . (period) & >
3A & / ? & / & ?
3B & 3l(undefined)
3C & . & . (period) & . (Numeric pad)
3D & 7 & 7 & 7 (Numeric pad)
3E & 8 & 8 & 8 (Numeric pad)
3F & 9 & 9 & 9 (Numeric pad)
40 & Space bar & (ASCII code 0x20) & (ASCII code 0x20)
41 & Back Space & (ASCII code 0x08) & (ASCII code 0x08)
42 & Tab & (ASCII code 0x09) & (ASCII code 0x09)
43 & Enter & (ASCII code 0x0D) & (ASCII code 0x0D)
44 & Return & (ASCII code 0x0D) & (ASCII code 0x0D; Numeric pad)
45 & Esc & (ASCII code 0x1B) & (ASCII code 0x1B)
46 & Del & (ASCII code 0x7F) & (ASCII code 0x7F)
47 & 3l(undefined)
48 & 3l(undefined)
49 & 3l(undefined)
4A & - & - (Hyphen) & - (Numeric Pad)
4B & 3l(undefined)
4C & Up arrow & <CSI>A & <CSI>T
4D & Down arrow & <CSI>B & <CSI>S
4E & Forward arrow & <CSI>C & <CSI> A (note blank space after <CSI>)
4F & Backward arrow & <CSI>D & <CSI> @ (note blank space after <CSI>)
50 & F1 & <CSI>0~ & <CSI>10 
51 & F2 & <CSI>1~ & <CSI>11 
52 & F3 & <CSI>2~ & <CSI>12 
53 & F4 & <CSI>3~ & <CSI>13 
54 & F5 & <CSI>4~ & <CSI>14 
55 & F6 & <CSI>5~ & <CSI>15 
56 & F7 & <CSI>6~ & <CSI>16 
57 & F8 & <CSI>7~ & <CSI>17 
58 & F9 & <CSI>8~ & <CSI>18 
59 & F10 & <CSI>9~ & <CSI>19 
5A & ( & ( & ( (usa1 Numeric pad)
5B & ) & ) & ) (usa1 Numeric pad)
5C & / & / & / (usa1 Numeric pad)
5D & & & (usa1 Numeric pad)
5E & + & + & + (usa1 Numeric pad)
5F & Help & <CSI>?  & <CSI>? 
ROM Default (USA0) and USA1 Console Key Mapping (continued)
Raw | Function or |
Key | Keycap |
Number | Legend |
60 | Shift (left of space bar) |
61 | Shift (right of space bar) |
62 | Caps Lock |
63 | Ctrl |
64 | (Left) Alt |
65 | (Right) Alt |
66 | Amiga (left of space bar; “Left Amiga”) |
67 | Amiga (right of space bar; “Right Amiga”) |
68 | Left mouse button (not converted; inputs only for mouse connected to Intuition) |
69 | Right mouse button (not converted; inputs only for mouse connected to Intuition) |
6A | Middle mouse button (not converted; inputs only for mouse connected to Intuition) |
6B | (undefined) |
6C | (undefined) |
6D | (undefined) |
6E | (undefined) |
6F | (undefined) |
70-7F | (undefined) |
80-F8 | Up transition (release or unpress key of one of the above keys; |
80 for 00, F8 for 7F) | |
F9 | Last key code was bad (was sent in order to resynchronize) |
FA | Keyboard buffer overflow |
FB | (undefined, reserved for keyboard processor catastrophe) |
FC | Keyboard selftest failed |
FD | Power-up key stream start. Keys pressed or stuck at power-up |
will be sent between FD and FE. | |
FE | Power-up key stream end |
FF | (undefined, reserved) |
FF | Mouse event, movement only, no button change (not converted) |
Notes about the preceding table:
(undefined)
indicates that the current keyboard design should not generate this number. If you are using SetKeyMap() to change the key map, the entries for these numbers must still be included.
(not converted)
refers to mouse button events. You must use the sequence <CSI>2{ to inform the console driver that you wish to receive mouse events; otherwise these will not be transmitted.
(reserved)
indicates that these key codes have been reserved for national keyboards. The $2B code key will be between the double-quote (") and Return keys. The $30 code key will be between the Shift and Z keys.
Figure 34-3: ECMA-94 Latin 1 International 8-Bit Character Set
Complete Keymap Source Example
The following example is the complete Amiga assembler source for the d (German) keymap. Comments in the source code illustrate the key layout of the German keyboard, and the standard U.S. keyboard layout for comparison.
********************************************************************** * * d (GERMAN) A2000 key map * Assemble and then link without startup code or linker libs * * Copyright (c) 1988 Commodore-Amiga, Inc. All Rights Reserved * ********************************************************************** *------ Included Files ----------------------------------------------- INCLUDE "exec/types.i" INCLUDE "devices/keymap.i" *--------------------------------------------------------------------- DC.L 0,0 ; ln_Succ, ln_Pred DC.B 0,0 ; ln_Type, ln_Pri DC.L KMName ; ln_Name DC.L KMLowMapType DC.L KMLowMap DC.L KMLCapsable DC.L KMLRepeatable DC.L KMHighMapType DC.L KMHighMap DC.L KMHCapsable DC.L KMHRepeatable *------ Key Translation Table ---------------------------------------- * Raw key codes * * 45 50 51 52 53 54 55 56 57 58 59 * 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 41 46 5F 5A 5B 5C 5D * 42 10 11 12 13 14 15 16 17 18 19 1A 1B 44 3D 3E 3F 4A * 63 62 20 21 22 23 24 25 26 27 28 29 2A 2B 4C 2D 2E 2F 5E * 60 30 31 32 33 34 35 36 37 38 39 3A 61 4F 4D 4E 1D 1E 1F 43 * 64 66 40 67 65 0F 3C * *--------------------------------------------------------------------- * German (D) mapping * * ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 * `~ 1! 2" 3S 4$ 5% 6& 7/ 8( 9) 0= B? '` \| BS DEL HELP [{ ]} / * * TAB qQ wW eE rR tT zZ uU iI oO pP uU +* RET 7 8 9 - * CT CL aA sS dD fF gG hH jJ kK lL oO aA #^ UC 4 5 6 + * SH <> yY xX cC vV bB nN mM ,; .: -_ SH LC DC RC 1 2 3 ENT * ALT AM SPACE AM ALT 0 . * *--------------------------------------------------------------------- * For comparison, here's the USA1 mapping * * ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 * `~ 1! 2@ 3# 4$ 5% 6^ 7& 8* 9( 0) -_ =+ \| BS DEL HELP (( )) // ** * TAB qQ wW eE rR tT yY uU iI oO pP [{ ]} RET 77 88 99 -- * CT CL aA sS dD fF gG hH jJ kK lL ;: '" [2B] UC 44 55 66 ++ * SH [30] zZ xX cC vV bB nN mM ,< .> /? SH LC DC RC 11 22 33 ENT * ALT AM SPACE AM ALT 00 .. * *-------------------------------------------------------------------------- * * 40 Space * 41 Backspace * 42 Tab * 43 Enter * 44 Return * 45 Escape * 46 Delete * 4A Numeric Pad - * 4C Cursor Up * 4D Cursor Down * 4E Cursor Forward * 4F Cursor Backward * * 50-59 Function keys F1-F10 * 5A Numeric Pad [{ (A2000) * 5B Numeric Pad ]} (A2000) * 5C Numeric Pad / (A2000) * 5D Numeric Pad * (A2000) * 5E Numeric Pad + (A2000) * 5F Help * * 60 Left Shift * 61 Right Shift * 62 Caps Lock * 63 Control * 64 Left Alt * 65 Right Alt * 66 Left Amiga * 67 Right Amiga * * 68 Left Mouse Button (not converted) * 69 Right Mouse Button (not converted) * 6A Middle Mouse Button (not converted) * *--------------------------------------------------------------------- KMLCapsable: ; NL means NULL (undefined) and RE means RESERVED DC.B %00000000 ; 7\ 6& 5% 4$ 3s 2" 1! [] 07 - 00 DC.B %00000000 ; 0N NL \| '` B? 0= 9) 8( 0F - 08 DC.B %11111111 ; iI uU zZ tT rR eE wW qQ 17 - 10 DC.B %00000111 ; 3N 2N 1N NL +* UU pP oO 1F - 18 DC.B %11111111 ; kK jJ hH gG fF dD sS aA 27 - 20 DC.B %00000111 ; 6N 5N 4N NL #' AA OO lL 2F - 28 DC.B %11111110 ; mM nN bB vV cC xX yY <> 37 - 30 DC.B %00000000 ; 9N 8N 7N .N NL -_ .: ,; 3F - 38 KMHCapsable: DC.B %00000000 ; 47 - 40 DC.B %00000000 ; 4F - 48 DC.B %00000000 ; 57 - 50 DC.B %00000000 ; 5F - 58 DC.B %00000000 ; 67 - 60 DC.B %00000000 ; 6F - 68 DC.B %00000000 ; 77 - 70 KMLRepeatable: DC.B %11111111 ; 7\ 6& 5% 4$ 3s 2" 1! [] 07 - 00 DC.B %10111111 ; 0N NL \| '` B? 0= 9) 8( 0F - 08 DC.B %11111111 ; iI uU zZ tT rR eE wW qQ 17 - 10 DC.B %11101111 ; 3N 2N 1N NL +* UU pP oO 1F - 18 DC.B %11111111 ; kK jJ hH gG fF dD sS aA 27 - 20 DC.B %11101111 ; 6N 5N 4N NL #' AA OO lL 2F - 28 DC.B %11111111 ; mM nN bB vV cC xX yY <> 37 - 30 DC.B %11110111 ; 9N 8N 7N .N NL -_ .: ,; 3F - 38 KMHRepeatable: DC.B %01000111 ; 47 - 40 DC.B %11110100 ; 4F - 48 DC.B %11111111 ; 57 - 50 DC.B %01111111 ; 5F - 58 DC.B %00000000 ; 67 - 60 DC.B %00000000 ; 6F - 68 DC.B %00000000 ; 77 - 70 KMLowMapType: DC.B KC_VANILLA ; [] $00 DC.B KCF_SHIFT+KCF_ALT ; 1! DC.B KCF_SHIFT+KCF_ALT ; 2" DC.B KCF_SHIFT+KCF_ALT ; 3s DC.B KCF_SHIFT+KCF_ALT ; 4$ DC.B KCF_SHIFT+KCF_ALT ; 5% DC.B KC_VANILLA ; 6& DC.B KCF_SHIFT+KCF_ALT ; 7/ DC.B KCF_SHIFT+KCF_ALT ; 8( $08 DC.B KCF_SHIFT+KCF_ALT ; 9) DC.B KCF_SHIFT+KCF_ALT ; 0= DC.B KC_VANILLA ; B? DC.B KCF_DEAD+KCF_SHIFT+KCF_ALT ; '` DC.B KC_VANILLA ; \| DC.B KCF_NOP ;NL DC.B KC_NOQUAL ; 0N DC.B KC_VANILLA ; qQ $10 DC.B KC_VANILLA ; wW DC.B KCF_DEAD+KC_VANILLA ; eE DC.B KC_VANILLA ; rR DC.B KC_VANILLA ; tT DC.B KC_VANILLA ; zZ DC.B KCF_DEAD+KC_VANILLA ; uU DC.B KCF_DEAD+KC_VANILLA ; iI DC.B KCF_DEAD+KC_VANILLA ; oO $18 DC.B KC_VANILLA ; pP DC.B KC_VANILLA ; omlatuU DC.B KC_VANILLA ; +* DC.B KCF_NOP ; NL DC.B KC_NOQUAL ; 1N DC.B KC_NOQUAL ; 2N DC.B KC_NOQUAL ; 3N DC.B KCF_DEAD+KC_VANILLA ; aA $20 DC.B KC_VANILLA ; sS DC.B KC_VANILLA ; dD DC.B KCF_DEAD+KC_VANILLA ; fF DC.B KCF_DEAD+KC_VANILLA ; gG DC.B KCF_DEAD+KC_VANILLA ; hH DC.B KCF_DEAD+KC_VANILLA ; jJ DC.B KCF_DEAD+KC_VANILLA ; kK DC.B KC_VANILLA ; lL $28 DC.B KCF_SHIFT+KCF_ALT ; umlotoO DC.B KCF_SHIFT+KCF_ALT ; umlotaA DC.B KC_VANILLA ; #^ DC.B KCF_NOP ; NL DC.B KC_NOQUAL ; 4N DC.B KC_NOQUAL ; 5N DC.B KC_NOQUAL ; 6N DC.B KCF_SHIFT ; <> $30 DC.B KCF_DEAD+KC_VANILLA ; yY DC.B KC_VANILLA ; xX DC.B KC_VANILLA ; cC DC.B KC_VANILLA ; vV DC.B KC_VANILLA ; bB DC.B KCF_DEAD+KC_VANILLA ; nN DC.B KC_VANILLA ; mM DC.B KCF_SHIFT+KCF_ALT ; ,; $38 DC.B KCF_SHIFT+KCF_ALT ; .: DC.B KC_VANILLA ; -_ DC.B KCF_NOP ; NL DC.B KC_NOQUAL ; .N DC.B KC_NOQUAL ; 7N DC.B KC_NOQUAL ; 8N DC.B KC_NOQUAL ; 9N KMHighMapType: DC.B KCF_DEAD+KCF_ALT ; SPACE $40 DC.B KC_NOQUAL ; BACKSPACE DC.B KCF_STRING+KCF_SHIFT ; TAB DC.B KC_NOQUAL ; ENTER DC.B KCF_CONTROL ; RETURN DC.B KCF_ALT ; ESCAPE DC.B KC_NOQUAL ; DELETE DC.B KCF_NOP DC.B KCF_NOP ; $48 DC.B KCF_NOP DC.B KC_NOQUAL ; -N DC.B KCF_NOP DC.B KCF_STRING+KCF_SHIFT ; CURSOR UP DC.B KCF_STRING+KCF_SHIFT ; CURSOR DOWN DC.B KCF_STRING+KCF_SHIFT ; CURSOR FORWARD DC.B KCF_STRING+KCF_SHIFT ; CURSOR BACKWARD DC.B KCF_STRING+KCF_SHIFT ; FKEY 1 $50 DC.B KCF_STRING+KCF_SHIFT ; FKEY 2 DC.B KCF_STRING+KCF_SHIFT ; FKEY 3 DC.B KCF_STRING+KCF_SHIFT ; FKEY 4 DC.B KCF_STRING+KCF_SHIFT ; FKEY 5 DC.B KCF_STRING+KCF_SHIFT ; FKEY 6 DC.B KCF_STRING+KCF_SHIFT ; FKEY 7 DC.B KCF_STRING+KCF_SHIFT ; FKEY 8 DC.B KCF_STRING+KCF_SHIFT ; FKEY 9 $58 DC.B KCF_STRING+KCF_SHIFT ; FKEY 10 DC.B KCF_SHIFT+KCF_CONTROL ; Numeric Pad [{ DC.B KCF_SHIFT+KCF_CONTROL ; Numeric Pad ]} DC.B KC_NOQUAL ; Numeric Pad / DC.B KC_NOQUAL ; Numeric Pad * DC.B KC_NOQUAL ; Numeric Pad + DC.B KCF_STRING ; Help DC.B KCF_NOP ; Left Shift $60 DC.B KCF_NOP ; Right Shift DC.B KCF_NOP ; Caps Lock DC.B KCF_NOP ; Control DC.B KCF_NOP ; Left Alt DC.B KCF_NOP ; Right Alt DC.B KCF_NOP ; Left Amiga DC.B KCF_NOP ; Right Amiga DC.B KCF_NOP ; Left Mouse Button $68 DC.B KCF_NOP ; Right Mouse Button DC.B KCF_NOP ; Middle Mouse Button DC.B KCF_NOP DC.B KCF_NOP DC.B KCF_NOP DC.B KCF_NOP DC.B KCF_NOP DC.B KCF_NOP ; $70 DC.B KCF_NOP DC.B KCF_NOP DC.B KCF_NOP DC.B KCF_NOP DC.B KCF_NOP DC.B KCF_NOP DC.B KCF_NOP KMLowMap: DC.B '~','`','~','`' ; `, ~, `, ~ $00 DC.B '!',$B9,'!','1' ; 1, !, super 1, ! DC.B $B2,'@','"','2' ; 2, ", @, super 2 DC.B '#',$B3,$A7,'3' ; 3, section, super 3, # DC.B $A2,$B0,'$','4' ; 4, $, degree, cents DC.B '%',$BC,'%','5' ; 5, %, 1/4, % DC.B '^',$BD,'&','6' ; 6, &, 1/2, ^ DC.B '&',$BE,'/','7' ; 7, /, 3/4, & DC.B '*',$B7,'(','8' ; 8, (, bullet, * $08 DC.B '(',$AB,')','9' ; 9, ), <<, ( DC.B ')',$BB,'=','0' ; 0, =, >>, ) DC.B '_','-','?',$DF ; sharp s, ?, -, _ DC.L key0C ; dead ', dead `, =, + DC.B '|','\','|','\' ; \, |, \, | DC.L 0 ; NOP DC.B 0,0,0,'0' ; numeric pad 0 (0N) DC.B $C5,$E5,'Q','q' ; q, Q, dot a, dot A $10 DC.B $B0,$B0,'W','w' ; w, W, dot, dot DC.L key12 ; e, E, (c), (c) DC.B $AE,$AE,'R','r' ; r, R, (r), (r) DC.B $DE,$FE,'T','t' ; t, T, thorn, THORN DC.B $A5,$A4,'Z','z' ; z, Z, IMS, Yen DC.L key16 ; u, U, micro, micro DC.L key17 ; i, I, inverted !, broken | DC.L key18 ; o, O, slash o, slash O $18 DC.B $B6,$B6,'P','p' ; p, P, paragraph, paragraph DC.B '{','[',$DC,$FC ; umlaut u, umlaut U, [, { DC.B '}',']','*','+' ; +, *, ], } DC.L 0 ; NOP DC.B 0,0,0,'1' ; numeric pad 1 (1N) DC.B 0,0,0,'2' ; numeric pad 2 (2N) DC.B 0,0,0,'3' ; numeric pad 3 (3N) DC.L key20 ; a, A, ae, AE $20 DC.B $A7,$DF,'S','s' ; s, S, sharp s, section DC.B $D0,$F0,'D','d' ; d, D, bar d, bar D DC.L key23 ; f, F, dead ' DC.L key24 ; g, G, dead ` DC.L key25 ; h, H, dead ^ DC.L key26 ; j, J, dead ~ DC.L key27 ; k, K, dead " DC.B $A3,$A3,'L','l' ; l, L, pound, pound $28 DC.B ':',';',$D6,$F6 ; umlaut o, umlaut O, ;, : DC.B '"',$27,$C4,$E4 ; umlaut a, umlaut A, ', " DC.B '^','#','^','#' ; #, ^, #, ^ DC.L 0 ; NOP DC.B 0,0,0,'4' ; numeric pad 4 (4N) DC.B 0,0,0,'5' ; numeric pad 5 (5N) DC.B 0,0,0,'6' ; numeric pad 6 (6N) DC.B 0,0,'>','<' ; <, > $30 DC.L key31 ; y, Y, +/-, not DC.B $F7,$D7,'X','x' ; x, X, times, divide DC.B $C7,$E7,'C','c' ; c, C, c cedilla, C cedilla DC.B $AA,$AA,'V','v' ; v, V, female ordinal DC.B $BA,$BA,'B','b' ; b, B, male ordinal DC.L key36 ; n, N, SHY, overbar DC.B $BF,$B8,'M','m' ; m, M, cedilla, inverted ? DC.B '<',',',';',',' ; ,, ;, ,, < $38 DC.B '>','.',':','.' ; ., :, ., > DC.B '?','/','_','-' ; -, _, /, ? DC.L 0 ; NOP DC.B 0,0,0,'.' ; numeric pad . (.N) DC.B 0,0,0,'7' ; numeric pad 7 (7N) DC.B 0,0,0,'8' ; numeric pad 8 (8N) DC.B 0,0,0,'9' ; numeric pad 9 (9N) KMHighMap: DC.L key40 $40 DC.B 0,0,0,$08 DC.L key42 DC.B 0,0,0,$0D DC.B 0,0,$0A,$0D DC.B 0,0,$9B,$1B DC.B 0,0,0,$7F DC.L 0 DC.L 0 $48 DC.L 0 DC.B 0,0,0,'-' DC.L 0 DC.L key4C DC.L key4D DC.L key4E DC.L key4F DC.L key50 $50 DC.L key51 DC.L key52 DC.L key53 DC.L key54 DC.L key55 DC.L key56 DC.L key57 DC.L key58 $58 DC.L key59 DC.B $1B,$1B,'{','[' ; numeric pad [, { DC.B $1D,$1D,'}',']' ; numeric pad ], } DC.B 0,0,0,'/' ; numeric pad / DC.B 0,0,0,'*' ; numeric pad * DC.B 0,0,0,'+' ; numeric pad + DC.L key5F DC.L 0 $60 DC.L 0 DC.L 0 DC.L 0 DC.L 0 DC.L 0 DC.L 0 DC.L 0 DC.L 0 $68 DC.L 0 DC.L 0 DC.L 0 DC.L 0 DC.L 0 DC.L 0 DC.L 0 DC.L 0 $70 DC.L 0 DC.L 0 DC.L 0 DC.L 0 DC.L 0 DC.L 0 DC.L 0 ;------ possible dead keys key0C: DC.B DPF_DEAD,1+(6<<DP_2DFACSHIFT) ; dead ' DC.B DPF_DEAD,2+(6<<DP_2DFACSHIFT) ; dead ` DC.B 0,'=',0,'+' ; =, + key23: DC.B 0,'f',0,'F' ; f, F DC.B DPF_DEAD,1+(6<<DP_2DFACSHIFT) ; dead ' DC.B DPF_DEAD,1+(6<<DP_2DFACSHIFT) ; dead ' DC.B 0,$06,0,$06,0,$86,0,$86 ; control translation key24: DC.B 0,'g',0,'G' ; g, G DC.B DPF_DEAD,2+(6<<DP_2DFACSHIFT) ; dead ` DC.B DPF_DEAD,2+(6<<DP_2DFACSHIFT) ; dead ` DC.B 0,$07,0,$07,0,$87,0,$87 ; control translation key25: DC.B 0,'h',0,'H' ; h, H DC.B DPF_DEAD,3,DPF_DEAD,3 ; dead ^, dead ^ DC.B 0,$08,0,$08,0,$88,0,$88 ; control translation key26: DC.B 0,'j',0,'J' ; j, J DC.B DPF_DEAD,4,DPF_DEAD,4 ; dead ~, dead ~ DC.B 0,$0A,0,$0A,0,$8A,0,$8A ; control translation key27: DC.B 0,'k',0,'K' ; k, K DC.B DPF_DEAD,5,DPF_DEAD,5 ; dead ", dead " DC.B 0,$0B,0,$0B,0,$8B,0,$8B ; control translation ;------ deadable keys (modified by dead keys) key12: ; e, E, (c), (c) DC.B DPF_MOD,key12u-key12,DPF_MOD,key12s-key12 DC.B 0,$A9,0,$A9 DC.B 0,$05,0,$05,0,$85,0,$85 ; control translation key12u: DC.B 'e',$E9,$E8,$EA,'e',$EB DC.B $E9,$E9,$EA,$E9,$E9,$E9 DC.B $E8,$EA,$E8,$E8,$E8,$E8 key12s: DC.B 'E',$C9,$C8,$CA,'E',$CB DC.B $C9,$C9,$CA,$C9,$C9,$C9 DC.B $C8,$CA,$C8,$C8,$C8,$C8 key16: ; u, U, micro, micro DC.B DPF_MOD,key16u-key16,DPF_MOD,key16s-key16 DC.B 0,$B5,0,$B5 DC.B 0,$15,0,$15,0,$95,0,$95 ; control translation key16u: DC.B 'u',$FA,$F9,$FB,'u',$FC DC.B $FA,$FA,$FB,$FA,$FA,$FA DC.B $F9,$FB,$F9,$F9,$F9,$F9 key16s: DC.B 'U',$DA,$D9,$DB,'U',$DC DC.B $DA,$DA,$DB,$DA,$DA,$DA DC.B $D9,$DB,$D9,$D9,$D9,$D9 key17: ; i, I, inverted !, broken | DC.B DPF_MOD,key17u-key17,DPF_MOD,key17s-key17 DC.B 0,$A1,0,$A6 DC.B 0,$09,0,$09,0,$89,0,$89 ; control translation key17u: DC.B 'i',$ED,$EC,$EE,'i',$EF DC.B $ED,$ED,$EE,$ED,$ED,$ED DC.B $EC,$EE,$EC,$EC,$EC,$EC key17s: DC.B 'I',$CD,$CC,$CE,'I',$CF DC.B $CD,$CD,$CE,$CD,$CD,$CD DC.B $CC,$CE,$CC,$CC,$CC,$CC key18: ; o, O, bar o, bar O DC.B DPF_MOD,key18u-key18,DPF_MOD,key18s-key18 DC.B 0,$F8,0,$D8 DC.B 0,$0F,0,$0F,0,$8F,0,$8F ; control translation key18u: DC.B 'o',$F3,$F2,$F4,$F5,$F6 DC.B $F3,$F3,$F4,$F3,$F3,$F3 DC.B $F2,$F4,$F2,$F2,$F2,$F2 key18s: DC.B 'O',$D3,$D2,$D4,$D5,$D6 DC.B $D3,$D3,$D4,$D3,$D3,$D3 DC.B $D2,$D4,$D2,$D2,$D2,$D2 key20: ; a, A, ae, AE DC.B DPF_MOD,key20u-key20,DPF_MOD,key20s-key20 DC.B 0,$E6,0,$C6 DC.B 0,$01,0,$01,0,$81,0,$81 ; control translation key20u: DC.B 'a',$E1,$E0,$E2,$E3,$E4 DC.B $E1,$E1,$E2,$E1,$E1,$E1 ; most recent is ' DC.B $E0,$E2,$E0,$E0,$E0,$E0 ; most recent is ` key20s: DC.B 'A',$C1,$C0,$C2,$C3,$C4 DC.B $C1,$C1,$C2,$C1,$C1,$C1 ; most recent is ' DC.B $C0,$C2,$C0,$C0,$C0,$C0 ; most recent is ` key36: ; n, N, SHY, overbar DC.B DPF_MOD,key36u-key36,DPF_MOD,key36s-key36 DC.B 0,$AD,0,$AF DC.B 0,$0E,0,$0E,0,$8E,0,$8E ; control translation key36u: DC.B 'n','n','n','n',$F1,'n' DC.B 'n','n','n','n','n','n' DC.B 'n','n','n','n','n','n' key36s: DC.B 'N','N','N','N',$D1,'N' DC.B 'N','N','N','N','N','N' DC.B 'N','N','N','N','N','N' key31: ; y, Y, +/-, not DC.B DPF_MOD,key31u-key31,DPF_MOD,key31s-key31 DC.B 0,$B1,0,$AC DC.B 0,$19,0,$19,0,$99,0,$99 ; control translation key31u: DC.B 'y',$FD,'y','y','y',$FF DC.B $FD,$FD,$FD,$FD,$FD,$FD DC.B 'y','y','y','y','y','y' key31s: DC.B 'Y',$DD,'Y','Y','Y','Y' DC.B $DD,$DD,$DD,$DD,$DD,$DD DC.B 'Y','Y','Y','Y','Y','Y' key40: ; space,,NBSP, and accents DC.B DPF_MOD,key40d-key40,0,$A0 key40d: DC.B ' ',$B4,'`','^','~',$A8 DC.B $B4,'^',$B4,$B4,$B4,$B4 DC.B '`','`','^','`','`','`' ;------ string keys key42: DC.B key42ue-key42us,key42us-key42 DC.B key42se-key42ss,key42ss-key42 key42us: DC.B $09 key42ue: key42ss: DC.B $9B,'Z' key42se: key4C: DC.B key4Cue-key4Cus,key4Cus-key4C DC.B key4Cse-key4Css,key4Css-key4C key4Cus: DC.B $9B,'A' key4Cue: key4Css: DC.B $9B,'T' key4Cse: key4D: DC.B key4Due-key4Dus,key4Dus-key4D DC.B key4Dse-key4Dss,key4Dss-key4D key4Dus: DC.B $9B,'B' key4Due: key4Dss: DC.B $9B,'S' key4Dse: key4E: DC.B key4Eue-key4Eus,key4Eus-key4E DC.B key4Ese-key4Ess,key4Ess-key4E key4Eus: DC.B $9B,'C' key4Eue: key4Ess: DC.B $9B,' ','@' key4Ese: key4F: DC.B key4Fue-key4Fus,key4Fus-key4F DC.B key4Fse-key4Fss,key4Fss-key4F key4Fus: DC.B $9B,'D' key4Fue: key4Fss: DC.B $9B,' ','A' key4Fse: key50: DC.B key50ue-key50us,key50us-key50 DC.B key50se-key50ss,key50ss-key50 key50us: DC.B $9B,'0~' key50ue: key50ss: DC.B $9B,'10~' key50se: key51: DC.B key51ue-key51us,key51us-key51 DC.B key51se-key51ss,key51ss-key51 key51us: DC.B $9B,'1~' key51ue: key51ss: DC.B $9B,'11~' key51se: key52: DC.B key52ue-key52us,key52us-key52 DC.B key52se-key52ss,key52ss-key52 key52us: DC.B $9B,'2~' key52ue: key52ss: DC.B $9B,'12~' key52se: key53: DC.B key53ue-key53us,key53us-key53 DC.B key53se-key53ss,key53ss-key53 key53us: DC.B $9B,'3~' key53ue: key53ss: DC.B $9B,'13~' key53se: key54: DC.B key54ue-key54us,key54us-key54 DC.B key54se-key54ss,key54ss-key54 key54us: DC.B $9B,'4~' key54ue: key54ss: DC.B $9B,'14~' key54se: key55: DC.B key55ue-key55us,key55us-key55 DC.B key55se-key55ss,key55ss-key55 key55us: DC.B $9B,'5~' key55ue: key55ss: DC.B $9B,'15~' key55se: key56: DC.B key56ue-key56us,key56us-key56 DC.B key56se-key56ss,key56ss-key56 key56us: DC.B $9B,'6~' key56ue: key56ss: DC.B $9B,'16~' key56se: key57: DC.B key57ue-key57us,key57us-key57 DC.B key57se-key57ss,key57ss-key57 key57us: DC.B $9B,'7~' key57ue: key57ss: DC.B $9B,'17~' key57se: key58: DC.B key58ue-key58us,key58us-key58 DC.B key58se-key58ss,key58ss-key58 key58us: DC.B $9B,'8~' key58ue: key58ss: DC.B $9B,'18~' key58se: key59: DC.B key59ue-key59us,key59us-key59 DC.B key59se-key59ss,key59ss-key59 key59us: DC.B $9B,'9~' key59ue: key59ss: DC.B $9B,'19~' key59se: key5F: DC.B key5Fe-key5Fs,key5Fs-key5F key5Fs: DC.B $9B,'?~' key5Fe: KMName: DC.B 'd',0 kmEnd END
Function Reference
The following are brief descriptions of the functions covered in this chapter. See the Amiga ROM Kernel Reference Manual: Includes and Autodocs for details on each function call.
[h] Keymap Library Functions
<thead> </thead> <tbody> </tbody>Function | Description |
---|---|
AskKeyMapDefault() | Ask for a pointer to the current default keymap |
MapANSI() | Encode an ANSI string into key codes |
MapRawKey() | Decode a raw key input event to an ANSI string |
SetKeyMapDefault() | Set the current default keymap |