Blame synfig-osx/launcher/darwin-old-keymap.c

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