+++ /dev/null
-/* darwin-old-keymap.c -- ugly code we need to keep around for now
-
- Copyright (c) 2001-2002 Torrey T. Lyons. All Rights Reserved.
-
- The code to parse the Darwin keymap is derived from dumpkeymap.c
- by Eric Sunshine, which includes the following copyright:
-
- Copyright (C) 1999,2000 by Eric Sunshine <sunshine@sunshineco.com>
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- 3. The name of the author may not be used to endorse or promote products
- derived from this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
- TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-#include "darwin.h"
-#include "darwin-keyboard.h"
-#include <errno.h>
-#include <sys/stat.h>
-#include <drivers/event_status_driver.h>
-#include <IOKit/hidsystem/ev_keymap.h>
-#include <architecture/byte_order.h> // For the NXSwap*
-
-#define XK_TECHNICAL // needed to get XK_Escape
-#define XK_PUBLISHING
-#include "keysym.h"
-
-static FILE *fref = NULL;
-static char *inBuffer = NULL;
-
-// FIXME: It would be nice to support some of the extra keys in XF86keysym.h,
-// at least the volume controls that now ship on every Apple keyboard.
-
-#define UK(a) NoSymbol // unknown symbol
-
-static KeySym const next_to_x[256] = {
- NoSymbol, NoSymbol, NoSymbol, XK_KP_Enter,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- XK_BackSpace, XK_Tab, XK_Linefeed, NoSymbol,
- NoSymbol, XK_Return, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- NoSymbol, NoSymbol, NoSymbol, XK_Escape,
- NoSymbol, NoSymbol, NoSymbol, NoSymbol,
- XK_space, XK_exclam, XK_quotedbl, XK_numbersign,
- XK_dollar, XK_percent, XK_ampersand, XK_apostrophe,
- XK_parenleft, XK_parenright, XK_asterisk, XK_plus,
- XK_comma, XK_minus, XK_period, XK_slash,
- XK_0, XK_1, XK_2, XK_3,
- XK_4, XK_5, XK_6, XK_7,
- XK_8, XK_9, XK_colon, XK_semicolon,
- XK_less, XK_equal, XK_greater, XK_question,
- XK_at, XK_A, XK_B, XK_C,
- XK_D, XK_E, XK_F, XK_G,
- XK_H, XK_I, XK_J, XK_K,
- XK_L, XK_M, XK_N, XK_O,
- XK_P, XK_Q, XK_R, XK_S,
- XK_T, XK_U, XK_V, XK_W,
- XK_X, XK_Y, XK_Z, XK_bracketleft,
- XK_backslash, XK_bracketright,XK_asciicircum, XK_underscore,
- XK_grave, XK_a, XK_b, XK_c,
- XK_d, XK_e, XK_f, XK_g,
- XK_h, XK_i, XK_j, XK_k,
- XK_l, XK_m, XK_n, XK_o,
- XK_p, XK_q, XK_r, XK_s,
- XK_t, XK_u, XK_v, XK_w,
- XK_x, XK_y, XK_z, XK_braceleft,
- XK_bar, XK_braceright, XK_asciitilde, XK_BackSpace,
-// 128
- NoSymbol, XK_Agrave, XK_Aacute, XK_Acircumflex,
- XK_Atilde, XK_Adiaeresis, XK_Aring, XK_Ccedilla,
- XK_Egrave, XK_Eacute, XK_Ecircumflex, XK_Ediaeresis,
- XK_Igrave, XK_Iacute, XK_Icircumflex, XK_Idiaeresis,
-// 144
- XK_ETH, XK_Ntilde, XK_Ograve, XK_Oacute,
- XK_Ocircumflex, XK_Otilde, XK_Odiaeresis, XK_Ugrave,
- XK_Uacute, XK_Ucircumflex, XK_Udiaeresis, XK_Yacute,
- XK_THORN, XK_mu, XK_multiply, XK_division,
-// 160
- XK_copyright, XK_exclamdown, XK_cent, XK_sterling,
- UK(fraction), XK_yen, UK(fhook), XK_section,
- XK_currency, XK_rightsinglequotemark,
- XK_leftdoublequotemark,
- XK_guillemotleft,
- XK_leftanglebracket,
- XK_rightanglebracket,
- UK(filigature), UK(flligature),
-// 176
- XK_registered, XK_endash, XK_dagger, XK_doubledagger,
- XK_periodcentered,XK_brokenbar, XK_paragraph, UK(bullet),
- XK_singlelowquotemark,
- XK_doublelowquotemark,
- XK_rightdoublequotemark,
- XK_guillemotright,
- XK_ellipsis, UK(permille), XK_notsign, XK_questiondown,
-// 192
- XK_onesuperior, XK_dead_grave, XK_dead_acute, XK_dead_circumflex,
- XK_dead_tilde, XK_dead_macron, XK_dead_breve, XK_dead_abovedot,
- XK_dead_diaeresis,
- XK_twosuperior, XK_dead_abovering,
- XK_dead_cedilla,
- XK_threesuperior,
- XK_dead_doubleacute,
- XK_dead_ogonek, XK_dead_caron,
-// 208
- XK_emdash, XK_plusminus, XK_onequarter, XK_onehalf,
- XK_threequarters,
- XK_agrave, XK_aacute, XK_acircumflex,
- XK_atilde, XK_adiaeresis, XK_aring, XK_ccedilla,
- XK_egrave, XK_eacute, XK_ecircumflex, XK_ediaeresis,
-// 224
- XK_igrave, XK_AE, XK_iacute, XK_ordfeminine,
- XK_icircumflex, XK_idiaeresis, XK_eth, XK_ntilde,
- XK_Lstroke, XK_Ooblique, XK_OE, XK_masculine,
- XK_ograve, XK_oacute, XK_ocircumflex, XK_otilde,
-// 240
- XK_odiaeresis, XK_ae, XK_ugrave, XK_uacute,
- XK_ucircumflex, XK_idotless, XK_udiaeresis, XK_ygrave,
- XK_lstroke, XK_ooblique, XK_oe, XK_ssharp,
- XK_thorn, XK_ydiaeresis, NoSymbol, NoSymbol,
- };
-
-#define MIN_SYMBOL 0xAC
-static KeySym const symbol_to_x[] = {
- XK_Left, XK_Up, XK_Right, XK_Down
- };
-int const NUM_SYMBOL = sizeof(symbol_to_x) / sizeof(symbol_to_x[0]);
-
-#define MIN_FUNCKEY 0x20
-static KeySym const funckey_to_x[] = {
- XK_F1, XK_F2, XK_F3, XK_F4,
- XK_F5, XK_F6, XK_F7, XK_F8,
- XK_F9, XK_F10, XK_F11, XK_F12,
- XK_Insert, XK_Delete, XK_Home, XK_End,
- XK_Page_Up, XK_Page_Down, XK_F13, XK_F14,
- XK_F15
- };
-int const NUM_FUNCKEY = sizeof(funckey_to_x) / sizeof(funckey_to_x[0]);
-
-typedef struct {
- KeySym normalSym;
- KeySym keypadSym;
-} darwinKeyPad_t;
-
-static darwinKeyPad_t const normal_to_keypad[] = {
- { XK_0, XK_KP_0 },
- { XK_1, XK_KP_1 },
- { XK_2, XK_KP_2 },
- { XK_3, XK_KP_3 },
- { XK_4, XK_KP_4 },
- { XK_5, XK_KP_5 },
- { XK_6, XK_KP_6 },
- { XK_7, XK_KP_7 },
- { XK_8, XK_KP_8 },
- { XK_9, XK_KP_9 },
- { XK_equal, XK_KP_Equal },
- { XK_asterisk, XK_KP_Multiply },
- { XK_plus, XK_KP_Add },
- { XK_comma, XK_KP_Separator },
- { XK_minus, XK_KP_Subtract },
- { XK_period, XK_KP_Decimal },
- { XK_slash, XK_KP_Divide }
-};
-int const NUM_KEYPAD = sizeof(normal_to_keypad) / sizeof(normal_to_keypad[0]);
-
-
-//-----------------------------------------------------------------------------
-// Data Stream Object
-// Can be configured to treat embedded "numbers" as being composed of
-// either 1, 2, or 4 bytes, apiece.
-//-----------------------------------------------------------------------------
-typedef struct _DataStream
-{
- unsigned char const *data;
- unsigned char const *data_end;
- short number_size; // Size in bytes of a "number" in the stream.
-} DataStream;
-
-static DataStream* new_data_stream( unsigned char const* data, int size )
-{
- DataStream* s = (DataStream*)xalloc( sizeof(DataStream) );
- s->data = data;
- s->data_end = data + size;
- s->number_size = 1; // Default to byte-sized numbers.
- return s;
-}
-
-static void destroy_data_stream( DataStream* s )
-{
- xfree(s);
-}
-
-static unsigned char get_byte( DataStream* s )
-{
- assert(s->data + 1 <= s->data_end);
- return *s->data++;
-}
-
-static short get_word( DataStream* s )
-{
- short hi, lo;
- assert(s->data + 2 <= s->data_end);
- hi = *s->data++;
- lo = *s->data++;
- return ((hi << 8) | lo);
-}
-
-static int get_dword( DataStream* s )
-{
- int b1, b2, b3, b4;
- assert(s->data + 4 <= s->data_end);
- b4 = *s->data++;
- b3 = *s->data++;
- b2 = *s->data++;
- b1 = *s->data++;
- return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1);
-}
-
-static int get_number( DataStream* s )
-{
- switch (s->number_size) {
- case 4: return get_dword(s);
- case 2: return get_word(s);
- default: return get_byte(s);
- }
-}
-
-
-//-----------------------------------------------------------------------------
-// Utility functions to help parse Darwin keymap
-//-----------------------------------------------------------------------------
-
-/*
- * bits_set
- * Calculate number of bits set in the modifier mask.
- */
-static short bits_set( short mask )
-{
- short n = 0;
-
- for ( ; mask != 0; mask >>= 1)
- if ((mask & 0x01) != 0)
- n++;
- return n;
-}
-
-/*
- * parse_next_char_code
- * Read the next character code from the Darwin keymapping
- * and write it to the X keymap.
- */
-static void parse_next_char_code(
- DataStream *s,
- KeySym *k )
-{
- const short charSet = get_number(s);
- const short charCode = get_number(s);
-
- if (charSet == 0) { // ascii character
- if (charCode >= 0 && charCode < 256)
- *k = next_to_x[charCode];
- } else if (charSet == 0x01) { // symbol character
- if (charCode >= MIN_SYMBOL &&
- charCode <= MIN_SYMBOL + NUM_SYMBOL)
- *k = symbol_to_x[charCode - MIN_SYMBOL];
- } else if (charSet == 0xFE) { // function key
- if (charCode >= MIN_FUNCKEY &&
- charCode <= MIN_FUNCKEY + NUM_FUNCKEY)
- *k = funckey_to_x[charCode - MIN_FUNCKEY];
- }
-}
-
-/*
- * DarwinReadKeymapFile
- * Read the appropriate keymapping from a keymapping file.
- */
-static Bool _DarwinReadKeymapFile(
- NXKeyMapping *keyMap)
-{
- struct stat st;
- NXEventSystemDevice info[20];
- int interface = 0, handler_id = 0;
- int map_interface, map_handler_id, map_size = 0;
- unsigned int i, size;
- int *bufferEnd;
- union km_tag {
- int *intP;
- char *charP;
- } km;
- char *filename;
-
- filename = DarwinFindLibraryFile (darwinKeymapFile, "Keyboards");
- if (filename == NULL) {
- FatalError("Could not find keymapping file %s.\n", darwinKeymapFile);
- return FALSE;
- }
-
- fref = fopen( filename, "rb" );
- xfree (filename);
-
- if (fref == NULL) {
- ErrorF("Unable to open keymapping file '%s' (errno %d).\n",
- darwinKeymapFile, errno);
- return FALSE;
- }
- if (fstat(fileno(fref), &st) == -1) {
- ErrorF("Could not stat keymapping file '%s' (errno %d).\n",
- darwinKeymapFile, errno);
- return FALSE;
- }
-
- // check to make sure we don't crash later
- if (st.st_size <= 16*sizeof(int)) {
- ErrorF("Keymapping file '%s' is invalid (too small).\n",
- darwinKeymapFile);
- return FALSE;
- }
-
- inBuffer = (char*) xalloc( st.st_size );
- bufferEnd = (int *) (inBuffer + st.st_size);
- if (fread(inBuffer, st.st_size, 1, fref) != 1) {
- ErrorF("Could not read %qd bytes from keymapping file '%s' (errno %d).\n",
- st.st_size, darwinKeymapFile, errno);
- return FALSE;
- }
-
- if (strncmp( inBuffer, "KYM1", 4 ) == 0) {
- // Magic number OK.
- } else if (strncmp( inBuffer, "KYMP", 4 ) == 0) {
- ErrorF("Keymapping file '%s' is intended for use with the original NeXT keyboards and cannot be used by XDarwin.\n", darwinKeymapFile);
- return FALSE;
- } else {
- ErrorF("Keymapping file '%s' has a bad magic number and cannot be used by XDarwin.\n", darwinKeymapFile);
- return FALSE;
- }
-
- // find the keyboard interface and handler id
- {NXEventHandle hid;
- NXEventSystemInfoType info_type;
-
- size = sizeof( info ) / sizeof( int );
- hid = NXOpenEventStatus ();
- info_type = NXEventSystemInfo (hid, NX_EVS_DEVICE_INFO,
- (int *) info, &size);
- NXCloseEventStatus (hid);
- if (!info_type) {
- ErrorF("Error reading event status driver info.\n");
- return FALSE;
- }}
-
- size = size * sizeof( int ) / sizeof( info[0] );
- for( i = 0; i < size; i++) {
- if (info[i].dev_type == NX_EVS_DEVICE_TYPE_KEYBOARD) {
- Bool hasInterface = FALSE;
- Bool hasMatch = FALSE;
-
- interface = info[i].interface;
- handler_id = info[i].id;
-
- // Find an appropriate keymapping:
- // The first time we try to match both interface and handler_id.
- // If we can't match both, we take the first match for interface.
-
- do {
- km.charP = inBuffer;
- km.intP++;
- while (km.intP+3 < bufferEnd) {
- map_interface = NXSwapBigIntToHost(*(km.intP++));
- map_handler_id = NXSwapBigIntToHost(*(km.intP++));
- map_size = NXSwapBigIntToHost(*(km.intP++));
- if (map_interface == interface) {
- if (map_handler_id == handler_id || hasInterface) {
- hasMatch = TRUE;
- break;
- } else {
- hasInterface = TRUE;
- }
- }
- km.charP += map_size;
- }
- } while (hasInterface && !hasMatch);
-
- if (hasMatch) {
- // fill in NXKeyMapping structure
- keyMap->size = map_size;
- keyMap->mapping = (char*) xalloc(map_size);
- memcpy(keyMap->mapping, km.charP, map_size);
- return TRUE;
- }
- } // if dev_id == keyboard device
- } // foreach info struct
-
- // The keymapping file didn't match any of the info structs
- // returned by NXEventSystemInfo.
- ErrorF("Keymapping file '%s' did not contain appropriate keyboard interface.\n", darwinKeymapFile);
- return FALSE;
-}
-
-static Bool DarwinReadKeymapFile(NXKeyMapping *keyMap)
-{
- Bool ret;
-
- ret = _DarwinReadKeymapFile (keyMap);
-
- if (inBuffer != NULL)
- xfree (inBuffer);
- if (fref != NULL)
- fclose (fref);
-
- return ret;
-}
-
-int DarwinParseKeymapFile (darwin_keyboard_info *info)
-{
- short numMods, numKeys, numPadKeys = 0;
- NXKeyMapping keyMap;
- DataStream *keyMapStream;
- unsigned char const *numPadStart = 0;
- Bool haveKeymap;
- int i;
- KeySym *k;
-
- if (darwinKeymapFile == NULL)
- return FALSE;
-
- haveKeymap = DarwinReadKeymapFile(&keyMap);
- if (!haveKeymap) {
- ErrorF("Reverting to system keymapping.\n");
- return FALSE;
- }
-
- keyMapStream = new_data_stream( (unsigned char const*)keyMap.mapping,
- keyMap.size );
-
- // check the type of map
- if (get_word(keyMapStream)) {
- keyMapStream->number_size = 2;
- ErrorF("Current 16-bit keymapping may not be interpreted correctly.\n");
- }
-
- // Compute the modifier map and
- // insert X modifier KeySyms into keyboard map.
- // Store modifier keycodes in modifierKeycodes.
- numMods = get_number(keyMapStream);
- while (numMods-- > 0) {
- int left = 1; // first keycode is left
- short const charCode = get_number(keyMapStream);
- short numKeyCodes = get_number(keyMapStream);
-
- // This is just a marker, not a real modifier.
- // Store numeric keypad keys for later.
- if (charCode == NX_MODIFIERKEY_NUMERICPAD) {
- numPadStart = keyMapStream->data;
- numPadKeys = numKeyCodes;
- }
-
- while (numKeyCodes-- > 0) {
- const short keyCode = get_number(keyMapStream);
- if (charCode != NX_MODIFIERKEY_NUMERICPAD) {
- switch (charCode) {
- case NX_MODIFIERKEY_ALPHALOCK:
- info->key_map[keyCode * GLYPHS_PER_KEY] = XK_Caps_Lock;
- break;
- case NX_MODIFIERKEY_SHIFT:
- info->key_map[keyCode * GLYPHS_PER_KEY] =
- (left ? XK_Shift_L : XK_Shift_R);
- break;
- case NX_MODIFIERKEY_CONTROL:
- info->key_map[keyCode * GLYPHS_PER_KEY] =
- (left ? XK_Control_L : XK_Control_R);
- break;
- case NX_MODIFIERKEY_ALTERNATE:
- info->key_map[keyCode * GLYPHS_PER_KEY] =
- (left ? XK_Alt_L : XK_Alt_R);
- break;
- case NX_MODIFIERKEY_COMMAND:
- info->key_map[keyCode * GLYPHS_PER_KEY] =
- (left ? XK_Meta_L : XK_Meta_R);
- break;
- case NX_MODIFIERKEY_SECONDARYFN:
- info->key_map[keyCode * GLYPHS_PER_KEY] =
- (left ? XK_Control_L : XK_Control_R);
- break;
- case NX_MODIFIERKEY_HELP:
- info->key_map[keyCode * GLYPHS_PER_KEY] = XK_Help;
- break;
- }
- }
- left = 0;
- }
- }
-
- // Convert the Darwin keyboard map to an X keyboard map.
- // A key can have a different character code for each combination of
- // modifiers. We currently ignore all modifier combinations except
- // those with Shift, AlphaLock, and Alt.
- numKeys = get_number(keyMapStream);
- for (i = 0, k = info->key_map; i < numKeys; i++, k += GLYPHS_PER_KEY) {
- short const charGenMask = get_number(keyMapStream);
- if (charGenMask != 0xFF) { // is key bound?
- short numKeyCodes = 1 << bits_set(charGenMask);
-
- // Record unmodified case
- parse_next_char_code( keyMapStream, k );
- numKeyCodes--;
-
- // If AlphaLock and Shift modifiers produce different codes,
- // we record the Shift case since X handles AlphaLock.
- if (charGenMask & 0x01) { // AlphaLock
- parse_next_char_code( keyMapStream, k+1 );
- numKeyCodes--;
- }
-
- if (charGenMask & 0x02) { // Shift
- parse_next_char_code( keyMapStream, k+1 );
- numKeyCodes--;
-
- if (charGenMask & 0x01) { // Shift-AlphaLock
- get_number(keyMapStream); get_number(keyMapStream);
- numKeyCodes--;
- }
- }
-
- // Skip the Control cases
- if (charGenMask & 0x04) { // Control
- get_number(keyMapStream); get_number(keyMapStream);
- numKeyCodes--;
-
- if (charGenMask & 0x01) { // Control-AlphaLock
- get_number(keyMapStream); get_number(keyMapStream);
- numKeyCodes--;
- }
-
- if (charGenMask & 0x02) { // Control-Shift
- get_number(keyMapStream); get_number(keyMapStream);
- numKeyCodes--;
-
- if (charGenMask & 0x01) { // Shift-Control-AlphaLock
- get_number(keyMapStream); get_number(keyMapStream);
- numKeyCodes--;
- }
- }
- }
-
- // Process Alt cases
- if (charGenMask & 0x08) { // Alt
- parse_next_char_code( keyMapStream, k+2 );
- numKeyCodes--;
-
- if (charGenMask & 0x01) { // Alt-AlphaLock
- parse_next_char_code( keyMapStream, k+3 );
- numKeyCodes--;
- }
-
- if (charGenMask & 0x02) { // Alt-Shift
- parse_next_char_code( keyMapStream, k+3 );
- numKeyCodes--;
-
- if (charGenMask & 0x01) { // Alt-Shift-AlphaLock
- get_number(keyMapStream); get_number(keyMapStream);
- numKeyCodes--;
- }
- }
- }
-
- while (numKeyCodes-- > 0) {
- get_number(keyMapStream); get_number(keyMapStream);
- }
-
- if (k[3] == k[2]) k[3] = NoSymbol;
- if (k[2] == k[1]) k[2] = NoSymbol;
- if (k[1] == k[0]) k[1] = NoSymbol;
- if (k[0] == k[2] && k[1] == k[3]) k[2] = k[3] = NoSymbol;
- }
- }
-
- // Now we have to go back through the list of keycodes that are on the
- // numeric keypad and update the X keymap.
- keyMapStream->data = numPadStart;
- while(numPadKeys-- > 0) {
- const short keyCode = get_number(keyMapStream);
- k = &info->key_map[keyCode * GLYPHS_PER_KEY];
- for (i = 0; i < NUM_KEYPAD; i++) {
- if (*k == normal_to_keypad[i].normalSym) {
- k[0] = normal_to_keypad[i].keypadSym;
- break;
- }
- }
- }
-
- // free Darwin keyboard map
- destroy_data_stream( keyMapStream );
- xfree( keyMap.mapping );
-
- return TRUE;
-}