diff options
author | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2011-10-10 17:43:39 +0200 |
commit | f4092abdf94af6a99aff944d6264bc1284e8bdd4 (patch) | |
tree | 2ac1c9cc16ceb93edb2c4382c088dac5aeafdf0f /nx-X11/programs/Xserver/hw/darwin/utils | |
parent | a840692edc9c6d19cd7c057f68e39c7d95eb767d (diff) | |
download | nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.gz nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.tar.bz2 nx-libs-f4092abdf94af6a99aff944d6264bc1284e8bdd4.zip |
Imported nx-X11-3.1.0-1.tar.gznx-X11/3.1.0-1
Summary: Imported nx-X11-3.1.0-1.tar.gz
Keywords:
Imported nx-X11-3.1.0-1.tar.gz
into Git repository
Diffstat (limited to 'nx-X11/programs/Xserver/hw/darwin/utils')
-rw-r--r-- | nx-X11/programs/Xserver/hw/darwin/utils/Imakefile | 10 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/hw/darwin/utils/README.txt | 111 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/hw/darwin/utils/dumpkeymap.c | 1454 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/hw/darwin/utils/dumpkeymap.man | 1004 |
4 files changed, 2579 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/hw/darwin/utils/Imakefile b/nx-X11/programs/Xserver/hw/darwin/utils/Imakefile new file mode 100644 index 000000000..b6ad53d8b --- /dev/null +++ b/nx-X11/programs/Xserver/hw/darwin/utils/Imakefile @@ -0,0 +1,10 @@ +XCOMM $XFree86: xc/programs/Xserver/hw/darwin/utils/Imakefile,v 1.2 2000/11/16 03:22:18 dawes Exp $ + + SRCS = dumpkeymap.c + OBJS = dumpkeymap.o +EXTRA_LOAD_FLAGS = -framework IOKit + +AllTarget(ProgramTargetName(dumpkeymap)) + +SimpleProgramTarget(dumpkeymap) + diff --git a/nx-X11/programs/Xserver/hw/darwin/utils/README.txt b/nx-X11/programs/Xserver/hw/darwin/utils/README.txt new file mode 100644 index 000000000..fb6d4399e --- /dev/null +++ b/nx-X11/programs/Xserver/hw/darwin/utils/README.txt @@ -0,0 +1,111 @@ +dumpkeymap - Diagnostic dump and detailed description of .keymapping files +Version 4 + +Copyright (C)1999,2000 by Eric Sunshine <sunshine@sunshineco.com> +Eric Sunshine, 1 December 2000 + +OVERVIEW +======== +This package contains the diagnostic utility dumpkeymap, as well as highly +detailed documentation describing the internal layout of the Apple/NeXT +.keymapping file. + +The dumpkeymap utility displays detailed information about each .keymapping +file mentioned on the command-line. On Apple and NeXT platforms, if no +.keymapping files are mentioned on the command-line, then it will instead +dissect the key mapping currently in use by the WindowServer and AppKit. + +Documentation includes a thorough and detailed description of the internal +layout of the .keymapping file, as well as an explanation of how to interpret +the output of dumpkeymap. + +The complete set of documentation is available for perusal via dumpkeymap's +manual page (dumpkeymap.1), as well as via the command-line options described +below. + + --help + Usage summary. + --help-keymapping + Detailed discussion of the internal format of a .keymapping file. + --help-output + Explanation of dumpkeymap's output. + --help-files + List of key mapping-related files and directories. + --help-diagnostics + Explanation of diagnostic messages. + +Once the manual page is been installed, documentation can also be accessed +with the Unix `man' command: + + % man dumpkeymap + + +COMPILATION +=========== +MacOS/X, Darwin + + cc -Wall -o dumpkeymap dumpkeymap.c -framework IOKit + +MacOS/X DP4 (Developer Preview 4) + + cc -Wall -o dumpkeymap dumpkeymap.c -FKernel -framework IOKit + +MacOS/X Server, OpenStep, NextStep + + cc -Wall -o dumpkeymap dumpkeymap.c + +By default, dumpkeymap is configured to interface with the HID driver (Apple) +or event-status driver (NeXT), thus allowing it to dump the key mapping which +is currently in use by the WindowServer and AppKit. However, these facilities +are specific to Apple/NeXT. In order to build dumpkeymap for non-Apple/NeXT +platforms, you must define the DUMPKEYMAP_FILE_ONLY flag when compiling the +program. This flag inhibits use of the HID and event-status drivers and +configures dumpkeymap to work strictly with raw key mapping files. + +For example, to compile for Linux: + + gcc -Wall -DDUMPKEYMAP_FILE_ONLY -o dumpkeymap dumpkeymap.c + + +INSTALLATION +============ +Install the dumpkeymap executable image in a location mentioned in the PATH +environment variable. Typicall locations for executable files are: + + /usr/local/bin + $(HOME)/bin + +Install the manual page, dumpkeymap.1, in the `man1' subdirectory one of the +standard manual page locations or in any other location mentioned by the +MANPATH environment variable. + +Typical locations for manual pages on most Unix platforms are: + + /usr/local/man/man1 + +Typical locations for manual pages on MacOS/X, Darwin, and MacOS/X Server are: + + /usr/local/man/man1 + /Local/Documentation/ManPages/man1 + /Network/Documentation/ManPages/man1 + +Typical locations for manual pages on OpenStep and NextStep are: + + /usr/local/man/man1 + /LocalLibrary/Documentation/ManPages/man1 + /LocalDeveloper/Documentation/ManPages/man1 + + +CONCLUSION +========== +This program and its accompanying documentation were written by Eric Sunshine +and are copyright (C)1999,2000 by Eric Sunshine <sunshine@sunshineco.com>. + +The implementation of dumpkeymap is based upon information gathered on +September 3, 1997 by Eric Sunshine <sunshine@sunshineco.com> and Paul S. +McCarthy <zarnuk@zarnuk.com> during an effort to reverse engineer the format +of the NeXT .keymapping file. + + + +$XFree86: xc/programs/Xserver/hw/darwin/utils/README.txt,v 1.1 2000/12/01 19:47:39 dawes Exp $ diff --git a/nx-X11/programs/Xserver/hw/darwin/utils/dumpkeymap.c b/nx-X11/programs/Xserver/hw/darwin/utils/dumpkeymap.c new file mode 100644 index 000000000..8f3340b15 --- /dev/null +++ b/nx-X11/programs/Xserver/hw/darwin/utils/dumpkeymap.c @@ -0,0 +1,1454 @@ +// $XFree86: dumpkeymap.c,v 1.3 2000/12/05 21:18:34 dawes Exp $ +//============================================================================= +// +// 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. +// +//============================================================================= +//----------------------------------------------------------------------------- +// dumpkeymap.c +// +// Prints a textual representation of each Apple/NeXT .keymapping file +// mentioned on the command-line. If no files are mentioned and if the +// local machine is an Apple or NeXT installation, then the key mapping +// currently in use by the WindowServer and the AppKit is printed +// instead. +// +// Invoke dumpkeymap with one of the options listed below in order to +// view detailed documentation about .keymapping files and the use of +// this program. +// +// --help: Usage summary. +// --help-keymapping: Detailed discussion of the internal format of a +// .keymapping file. +// --help-output: Explanation of dumpkeymap's output. +// --help-files: List of key mapping-related files and directories. +// --help-diagnostics: Explanation of diagnostic messages. +// +// COMPILATION INSTRUCTIONS +// +// MacOS/X, Darwin +// cc -Wall -o dumpkeymap dumpkeymap.c -framework IOKit +// +// MacOS/X DP4 (Developer Preview 4) +// cc -Wall -o dumpkeymap dumpkeymap.c -FKernel -framework IOKit +// +// MacOS/X Server, OpenStep, NextStep +// cc -Wall -o dumpkeymap dumpkeymap.c +// +// By default, dumpkeymap is configured to interface with the HID driver +// (Apple) or event-status driver (NeXT), thus allowing it to dump the +// key mapping which is currently in use by the WindowServer and AppKit. +// However, these facilities are specific to Apple/NeXT. In order to +// build dumpkeymap for non-Apple/NeXT platforms, you must define the +// DUMPKEYMAP_FILE_ONLY flag when compiling the program. This flag +// inhibits use of the HID and event-status drivers and configures +// dumpkeymap to work strictly with raw key mapping files. +// +// For example, to compile for Linux: +// gcc -Wall -DDUMPKEYMAP_FILE_ONLY -o dumpkeymap dumpkeymap.c +// +// CONCLUSION +// +// This program and its accompanying documentation were written by Eric +// Sunshine and are copyright (C)1999,2000 by Eric Sunshine +// <sunshine@sunshineco.com>. +// +// The implementation of dumpkeymap is based upon information gathered +// on September 3, 1997 by Eric Sunshine <sunshine@sunshineco.com> and +// Paul S. McCarthy <zarnuk@zarnuk.com> during an effort to reverse +// engineer the format of the NeXT .keymapping file. +// +// HISTORY +// +// v4 2000/12/01 Eric Sunshine <sunshine@sunshineco.com> +// Updated manual page to work with `rman', the `man' to `HTML' +// translator. Unfortunately, however, rman is missing important +// roff features such as diversions, indentation, and tab stops, +// and is also hideously buggy, so getting the manual to work with +// rman required quite a few work-arounds. +// The manual page has now been tested with nroff (plain text), troff +// (PostScript, etc.), groff (PostScript), and rman (HTML, etc.) +// +// v3 2000/11/28 Eric Sunshine <sunshine@sunshineco.com> +// Considerably expanded the documentation. +// Augmented the existing description of .keymapping internals. +// Added these new documentation topics: +// - Output: Very important section describing how to interpret +// the output of dumpkeymap. +// - Files: Lists files and directories related to key mappings. +// - Diagnostics: Explains diagnostic messages issued by +// dumpkeymap. +// Created a manual page (dumpkeymap.1) which contains the complete +// set of documentation for key mapping files and dumpkeymap. +// Added command-line options (--help, --help-keymapping, +// --help-output, --help-files, --help-diagnostics) which allow +// access to all key mapping documentation. Previously the +// description of the internal layout of a .keymapping file was +// only available as source code comments. +// Added --version option. +// Ported to non-Apple/NeXT platforms. Defining the pre-processor +// flag DUMPKEYMAP_FILE_ONLY at compilation time inhibits use of +// Apple/NeXT-specific API. +// Added a README file. +// +// v2 2000/11/13 Eric Sunshine <sunshine@sunshineco.com> +// Converted from C++ to plain-C. +// Now parses and takes into account the "number-size" flag stored +// with each key map. This flag indicates the size, in bytes, of +// all remaining numeric values in the mapping. Updated all code +// to respect this flag. (Previously, the purpose of this field +// was unknown, and it was thus denoted as +// `KeyMapping::fill[2]'.) +// Updated all documentation; especially the "KEY MAPPING +// DESCRIPTION" section. Added discussion of the "number-size" +// flag and revamped all structure definitions to use the generic +// data type `number' instead of `uchar' or 'byte'. Clarified +// several sections of the documentation and added missing +// discussions about type definitions and the relationship of +// `interface' and `handler_id' to .keymapping and .keyboard +// files. +// Updated compilation instructions to include directions for all +// platforms on which this program might be built. +// Now published under the formal BSD license rather than a +// home-grown license. +// +// v1 1999/09/08 Eric Sunshine <sunshine@sunshineco.com> +// Created. +//----------------------------------------------------------------------------- +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#if !defined(DUMPKEYMAP_FILE_ONLY) +#include <drivers/event_status_driver.h> +#endif + +#define PROG_NAME "dumpkeymap" +#define PROG_VERSION "4" +#define AUTHOR_NAME "Eric Sunshine" +#define AUTHOR_EMAIL "sunshine@sunshineco.com" +#define AUTHOR_INFO AUTHOR_NAME " <" AUTHOR_EMAIL ">" +#define COPYRIGHT "Copyright (C) 1999,2000 by " AUTHOR_INFO + +typedef unsigned char byte; +typedef unsigned short word; +typedef unsigned int natural; +typedef unsigned long dword; +typedef dword number; + +#define ASCII_SET 0x00 +#define BIND_FUNCTION 0xfe +#define BIND_SPECIAL 0xff + +#define OPT_SWITCH(X) { char const* switched_str__=(X); if (0) { +#define OPT_CASE(X,Y) } else if (strcmp(switched_str__,(#X)) == 0 || \ + strcmp(switched_str__,(#Y)) == 0) { +#define OPT_DEFAULT } else { +#define OPT_SWITCH_END }} + +//----------------------------------------------------------------------------- +// Translation Tables +//----------------------------------------------------------------------------- +static char const* const SPECIAL_CODE[] = + { + "sound-up", + "sound-down", + "brightness-up", + "brightness-down", + "alpha-lock", + "help", + "power", + "secondary-up-arrow", + "secondary-down-arrow" + }; +#define N_SPECIAL_CODE (sizeof(SPECIAL_CODE) / sizeof(SPECIAL_CODE[0])) + +static char const* const MODIFIER_CODE[] = + { + "alpha-lock", + "shift", + "control", + "alternate", + "command", + "keypad", + "help" + }; +#define N_MODIFIER_CODE (sizeof(MODIFIER_CODE) / sizeof(MODIFIER_CODE[0])) + +static char const* const MODIFIER_MASK[] = + { + "-----", // R = carriage-return + "----L", // A = alternate + "---S-", // C = control + "---SL", // S = shift + "--C--", // L = alpha-lock + "--C-L", + "--CS-", + "--CSL", + "-A---", + "-A--L", + "-A-S-", + "-A-SL", + "-AC--", + "-AC-L", + "-ACS-", + "-ACSL", + "R----", + "R---L", + "R--S-", + "R--SL", + "R-C--", + "R-C-L", + "R-CS-", + "R-CSL", + "RA---", + "RA--L", + "RA-S-", + "RA-SL", + "RAC--", + "RAC-L", + "RACS-", + "RACSL", + }; +#define N_MODIFIER_MASK (sizeof(MODIFIER_MASK) / sizeof(MODIFIER_MASK[0])) + +#define FUNCTION_KEY_FIRST 0x20 +static char const* const FUNCTION_KEY[] = + { + "F1", // 0x20 + "F2", // 0x21 + "F3", // 0x22 + "F4", // 0x23 + "F5", // 0x24 + "F6", // 0x25 + "F7", // 0x26 + "F8", // 0x27 + "F9", // 0x28 + "F10", // 0x29 + "F11", // 0x2a + "F12", // 0x2b + "insert", // 0x2c + "delete", // 0x2d + "home", // 0x2e + "end", // 0x2f + "page up", // 0x30 + "page down", // 0x31 + "print screen", // 0x32 + "scroll lock", // 0x33 + "pause", // 0x34 + "sys-request", // 0x35 + "break", // 0x36 + "reset (HIL)", // 0x37 + "stop (HIL)", // 0x38 + "menu (HIL)", // 0x39 + "user (HIL)", // 0x3a + "system (HIL)", // 0x3b + "print (HIL)", // 0x3c + "clear line (HIL)", // 0x3d + "clear display (HIL)", // 0x3e + "insert line (HIL)", // 0x3f + "delete line (HIL)", // 0x40 + "insert char (HIL)", // 0x41 + "delete char (HIL)", // 0x42 + "prev (HIL)", // 0x43 + "next (HIL)", // 0x44 + "select (HIL)", // 0x45 + }; +#define N_FUNCTION_KEY (sizeof(FUNCTION_KEY) / sizeof(FUNCTION_KEY[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 + { + byte const* data; + byte const* data_end; + natural number_size; // Size in bytes of a "number" in the stream. + } DataStream; + +static DataStream* new_data_stream( byte const* data, int size ) + { + DataStream* s = (DataStream*)malloc( 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 ) + { + free(s); + } + +static int end_of_stream( DataStream* s ) + { + return (s->data >= s->data_end); + } + +static void expect_nbytes( DataStream* s, int nbytes ) + { + if (s->data + nbytes > s->data_end) + { + fputs( "Insufficient data in keymapping data stream.\n", stderr ); + exit(-1); + } + } + +static byte get_byte( DataStream* s ) + { + expect_nbytes( s, 1 ); + return *s->data++; + } + +static word get_word( DataStream* s ) + { + word hi, lo; + expect_nbytes( s, 2 ); + hi = *s->data++; + lo = *s->data++; + return ((hi << 8) | lo); + } + +static dword get_dword( DataStream* s ) + { + dword b1, b2, b3, b4; + expect_nbytes( s, 4 ); + b4 = *s->data++; + b3 = *s->data++; + b2 = *s->data++; + b1 = *s->data++; + return ((b4 << 24) | (b3 << 16) | (b2 << 8) | b1); + } + +static number 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); + } + } + + +//----------------------------------------------------------------------------- +// Translation Utility Functions +//----------------------------------------------------------------------------- +static char const* special_code_desc( number n ) + { + if (n < N_SPECIAL_CODE) + return SPECIAL_CODE[n]; + else + return "invalid"; + } + +static char const* modifier_code_desc( number n ) + { + if (n < N_MODIFIER_CODE) + return MODIFIER_CODE[n]; + else + return "invalid"; + } + +static char const* modifier_mask_desc( number n ) + { + if (n < N_MODIFIER_MASK) + return MODIFIER_MASK[n]; + else + return "?????"; + } + +static char const* function_key_desc( number n ) + { + if (n >= FUNCTION_KEY_FIRST && n < N_FUNCTION_KEY + FUNCTION_KEY_FIRST) + return FUNCTION_KEY[ n - FUNCTION_KEY_FIRST ]; + else + return "unknown"; + } + +static number bits_set( number mask ) + { + number n = 0; + for ( ; mask != 0; mask >>= 1) + if ((mask & 0x01) != 0) + n++; + return n; + } + + +//----------------------------------------------------------------------------- +// Unparse a list of Modifier records. +//----------------------------------------------------------------------------- +static void unparse_modifiers( DataStream* s ) + { + number nmod = get_number(s); // Modifier count + printf( "MODIFIERS [%lu]\n", nmod ); + while (nmod-- > 0) + { + number nscan; + number const code = get_number(s); + printf( "%s:", modifier_code_desc(code) ); + nscan = get_number(s); + while (nscan-- > 0) + printf( " 0x%02x", (natural)get_number(s) ); + putchar( '\n' ); + } + putchar( '\n' ); + } + + +//----------------------------------------------------------------------------- +// Unparse a list of Character records. +//----------------------------------------------------------------------------- +typedef void (*UnparseSpecialFunc)( number code ); + +static void unparse_char_codes( + DataStream* s, number ncodes, UnparseSpecialFunc unparse_special ) + { + if (ncodes != 0) + { + while (ncodes-- > 0) + { + number const char_set = get_number(s); + number const code = get_number(s); + putchar(' '); + switch (char_set) + { + case ASCII_SET: + { + int const c = (int)code; + if (isprint(c)) + printf( "\"%c\"", c ); + else if (code < ' ') + printf( "\"^%c\"", c + '@' ); + else + printf( "%02x", c ); + break; + } + case BIND_FUNCTION: + printf( "[%s]", function_key_desc(code) ); + break; + case BIND_SPECIAL: + unparse_special( code ); + break; + default: + printf( "%02x/%02x", (natural)char_set, (natural)code ); + break; + } + } + } + } + + +//----------------------------------------------------------------------------- +// Unparse a list of scan code bindings. +//----------------------------------------------------------------------------- +static void unparse_key_special( number code ) + { + printf( "{seq#%lu}", code ); + } + +static void unparse_characters( DataStream* s ) + { + number const NOT_BOUND = 0xff; + number const nscans = get_number(s); + number scan; + printf( "CHARACTERS [%lu]\n", nscans ); + for (scan = 0; scan < nscans; scan++) + { + number const mask = get_number(s); + printf( "scan 0x%02x: ", (natural)scan ); + if (mask == NOT_BOUND) + fputs( "not-bound\n", stdout ); + else + { + number const bits = bits_set( mask ); + number const codes = 1 << bits; + printf( "%s ", modifier_mask_desc(mask) ); + unparse_char_codes( s, codes, unparse_key_special ); + putchar( '\n' ); + } + } + putchar( '\n' ); + } + + +//----------------------------------------------------------------------------- +// Unparse a list of key sequences. +//----------------------------------------------------------------------------- +static void unparse_sequence_special( number code ) + { + printf( "{%s}", (code == 0 ? "unmodify" : modifier_code_desc(code)) ); + } + +static void unparse_sequences( DataStream* s ) + { + number const nseqs = get_number(s); + number seq; + printf( "SEQUENCES [%lu]\n", nseqs ); + for (seq = 0; seq < nseqs; seq++) + { + number const nchars = get_number(s); + printf( "sequence %lu:", seq ); + unparse_char_codes( s, nchars, unparse_sequence_special ); + putchar( '\n' ); + } + putchar( '\n' ); + } + + +//----------------------------------------------------------------------------- +// Unparse a list of special keys. +//----------------------------------------------------------------------------- +static void unparse_specials( DataStream* s ) + { + number nspecials = get_number(s); + printf( "SPECIALS [%lu]\n", nspecials ); + while (nspecials-- > 0) + { + number const special = get_number(s); + number const scan = get_number(s); + printf( "%s: 0x%02x\n", special_code_desc(special), (natural)scan ); + } + putchar( '\n' ); + } + + +//----------------------------------------------------------------------------- +// Unparse the number-size flag. +//----------------------------------------------------------------------------- +static void unparse_numeric_size( DataStream* s ) + { + word const numbers_are_shorts = get_word(s); + s->number_size = numbers_are_shorts ? 2 : 1; + } + + +//----------------------------------------------------------------------------- +// Unparse an entire key map. +//----------------------------------------------------------------------------- +static void unparse_keymap_data( DataStream* s ) + { + unparse_numeric_size(s); + unparse_modifiers(s); + unparse_characters(s); + unparse_sequences(s); + unparse_specials(s); + } + + +//----------------------------------------------------------------------------- +// Unparse the active key map. +//----------------------------------------------------------------------------- +#if !defined(DUMPKEYMAP_FILE_ONLY) +static int unparse_active_keymap( void ) + { + int rc = 1; + NXEventHandle const h = NXOpenEventStatus(); + if (h == 0) + fputs( "Unable to open event status driver.\n", stderr ); + else + { + NXKeyMapping km; + km.size = NXKeyMappingLength(h); + if (km.size <= 0) + fprintf( stderr, "Bad key mapping length (%d).\n", km.size ); + else + { + km.mapping = (char*)malloc( km.size ); + if (NXGetKeyMapping( h, &km ) == 0) + fputs( "Unable to get current key mapping.\n", stderr ); + else + { + DataStream* stream = + new_data_stream( (byte const*)km.mapping, km.size ); + fputs( "=============\nACTIVE KEYMAP\n=============\n\n", + stdout); + unparse_keymap_data( stream ); + destroy_data_stream( stream ); + rc = 0; + } + free( km.mapping ); + } + NXCloseEventStatus(h); + } + return rc; + } +#endif + + +//----------------------------------------------------------------------------- +// Unparse one key map from a keymapping file. +//----------------------------------------------------------------------------- +static void unparse_keymap( DataStream* s ) + { + dword const interface = get_dword(s); + dword const handler_id = get_dword(s); + dword const map_size = get_dword(s); + printf( "interface: 0x%02lx\nhandler_id: 0x%02lx\nmap_size: %lu bytes\n\n", + interface, handler_id, map_size ); + unparse_keymap_data(s); + } + + +//----------------------------------------------------------------------------- +// Check the magic number of a keymapping file. +//----------------------------------------------------------------------------- +static int check_magic_number( DataStream* s ) + { + return (get_byte(s) == 'K' && + get_byte(s) == 'Y' && + get_byte(s) == 'M' && + get_byte(s) == '1'); + } + + +//----------------------------------------------------------------------------- +// Unparse all key maps within a keymapping file. +//----------------------------------------------------------------------------- +static int unparse_keymaps( DataStream* s ) + { + int rc = 0; + if (check_magic_number(s)) + { + int n = 1; + while (!end_of_stream(s)) + { + printf( "---------\nKEYMAP #%d\n---------\n", n++ ); + unparse_keymap(s); + } + } + else + { + fputs( "Bad magic number.\n", stderr ); + rc = 1; + } + return rc; + } + + +//----------------------------------------------------------------------------- +// Unparse a keymapping file. +//----------------------------------------------------------------------------- +static int unparse_keymap_file( char const* const path ) + { + int rc = 1; + FILE* file; + printf( "===========\nKEYMAP FILE\n===========\n%s\n\n", path ); + file = fopen( path, "rb" ); + if (file == 0) + perror( "Unable to open key mapping file" ); + else + { + struct stat st; + if (fstat( fileno(file), &st ) != 0) + perror( "Unable to determine key mapping file size" ); + else + { + byte* buffer = (byte*)malloc( st.st_size ); + if (fread( buffer, st.st_size, 1, file ) != 1) + perror( "Unable to read key mapping file" ); + else + { + DataStream* stream = new_data_stream(buffer, (int)st.st_size); + fclose( file ); file = 0; + rc = unparse_keymaps( stream ); + destroy_data_stream( stream ); + } + free( buffer ); + } + if (file != 0) + fclose( file ); + } + return rc; + } + + +//----------------------------------------------------------------------------- +// Handle the case when no documents are mentioned on the command-line. For +// Apple/NeXT platforms, dump the currently active key mapping; else display +// an error message. +//----------------------------------------------------------------------------- +static int handle_empty_document_list( void ) + { +#if !defined(DUMPKEYMAP_FILE_ONLY) + return unparse_active_keymap(); +#else + fputs( "ERROR: Must specify at least one .keymapping file.\n\n", stderr ); + return 1; +#endif + } + + +//----------------------------------------------------------------------------- +// Print a detailed description of the internal layout of a key mapping. +//----------------------------------------------------------------------------- +static void print_internal_layout_info( FILE* f ) + { + fputs( +"What follows is a detailed descriptions of the internal layout of an\n" +"Apple/NeXT .keymapping file.\n" +"\n" +"Types and Data\n" +"--------------\n" +"The following type definitions are employed throughout this discussion:\n" +"\n" +" typedef unsigned char byte;\n" +" typedef unsigned short word;\n" +" typedef unsigned long dword;\n" +"\n" +"Additionally, the type definition `number' is used generically to indicate\n" +"a numeric value. The actual size of the `number' type may be one or two\n" +"bytes depending upon how the data is stored in the key map. Although most\n" +"key maps use byte-sized numeric values, word-sized values are also allowed.\n" +"\n" +"Multi-byte values in a key mapping file are stored in big-endian byte\n" +"order.\n" +"\n" +"Key Mapping File and Device Mapping\n" +"-----------------------------------\n" +"A key mapping file begins with a magic-number and continues with a variable\n" +"number of device-specific key mappings.\n" +"\n" +" struct KeyMappingFile {\n" +" char magic_number[4]; // `KYM1'\n" +" DeviceMapping maps[...]; // Variable number of maps\n" +" };\n" +"\n" +" struct DeviceMapping {\n" +" dword interface; // Interface type\n" +" dword handler_id; // Interface subtype\n" +" dword map_size; // Byte count of `map' (below)\n" +" KeyMapping map;\n" +" };\n" +"\n" +"The value of `interface' represents a family of keyboard device types\n" +"(such as Intel PC, ADB, NeXT, Sun Type5, etc.), and is generally\n" +"specified as one of the constant values NX_EVS_DEVICE_INTERFACE_ADB,\n" +"NX_EVS_DEVICE_INTERFACE_ACE, etc., which are are defined in IOHIDTypes.h on\n" +"MacOS/X and Darwin, and in ev_types.h on MacOS/X Server, OpenStep, and\n" +"NextStep.\n" +"\n" +"The value of `handler_id' represents a specific keyboard layout within the\n" +"much broader `interface' family. For instance, for a 101-key Intel PC\n" +"keyboard (of type NX_EVS_DEVICE_INTERFACE_ACE) the `handler_id' is '0',\n" +"whereas for a 102-key keyboard it is `1'.\n" +"\n" +"Together, `interface' and `handler_id' identify the exact keyboard hardware\n" +"to which this mapping applies. Programs which display a visual\n" +"representation of a keyboard layout, match `interface' and `handler_id'\n" +"from the .keymapping file against the `interface' and `handler_id' values\n" +"found in each .keyboard file.\n" +"\n" +"Key Mapping\n" +"-----------\n" +"A key mapping completely defines the relationship of all scan codes with\n" +"their associated functionality. A KeyMapping structure is embedded within\n" +"the DeviceMapping structure in a KeyMappingFile. The key mapping currently\n" +"in use by the WindowServer and AppKit is also represented by a KeyMapping\n" +"structure, and can be referred to directly by calling NXGetKeyMapping() and\n" +"accessing the `mapping' data member of the returned NXKeyMapping structure.\n" +"\n" +" struct KeyMapping {\n" +" word number_size; // 0=1 byte, non-zero=2 bytes\n" +" number num_modifier_groups; // Modifier groups\n" +" ModifierGroup modifier_groups[...];\n" +" number num_scan_codes; // Scan groups\n" +" ScanGroup scan_table[...];\n" +" number num_sequence_lists; // Sequence lists\n" +" Sequence sequence_lists[...];\n" +" number num_special_keys; // Special keys\n" +" SpecialKey special_key[...];\n" +" };\n" +"\n" +"The `number_size' flag determines the size, in bytes, of all remaining\n" +"numeric values (denoted by the type definition `number') within the key\n" +"mapping. If its value is zero, then numbers are represented by a single\n" +"byte. If it is non-zero, then numbers are represented by a word (two\n" +"bytes).\n" +"\n" +"Modifier Group\n" +"--------------\n" +"A modifier group defines all scan codes which map to a particular type of\n" +"modifier, such as `shift', `control', etc.\n" +"\n" +" enum Modifier {\n" +" ALPHALOCK = 0,\n" +" SHIFT,\n" +" CONTROL,\n" +" ALTERNATE,\n" +" COMMAND,\n" +" KEYPAD,\n" +" HELP\n" +" };\n" +"\n" +" struct ModifierGroup {\n" +" number modifier; // A Modifier constant\n" +" number num_scan_codes;\n" +" number scan_codes[...]; // Variable number of scan codes\n" +" };\n" +"\n" +"The scan_codes[] array contains a list of all scan codes which map to the\n" +"specified modifier. The `shift', `command', and `alternate' modifiers are\n" +"frequently mapped to two different scan codes, apiece, since these\n" +"modifiers often appear on both the left and right sides of the keyboard.\n" +"\n" +"Scan Group\n" +"----------\n" +"There is one ScanGroup for each scan code generated by the given keyboard.\n" +"This number is given by KeyMapping::num_scan_codes. The first scan group\n" +"represents hardware scan code 0, the second represents scan code 1, etc.\n" +"\n" +" enum ModifierMask {\n" +" ALPHALOCK_MASK = 1 << 0,\n" +" SHIFT_MASK = 1 << 1,\n" +" CONTROL_MASK = 1 << 2,\n" +" ALTERNATE_MASK = 1 << 3,\n" +" CARRIAGE_RETURN_MASK = 1 << 4\n" +" };\n" +" #define NOT_BOUND 0xff\n" +"\n" +" struct ScanGroup {\n" +" number mask;\n" +" Character characters[...];\n" +" };\n" +"\n" +"For each scan code, `mask' defines which modifier combinations generate\n" +"characters. If `mask' is NOT_BOUND (0xff) then then this scan code does\n" +"not generate any characters ever, and its characters[] array is zero\n" +"length. Otherwise, the characters[] array contains one Character record\n" +"for each modifier combination.\n" +"\n" +"The number of records in characters[] is determined by computing (1 <<\n" +"bits_set_in_mask). In other words, if mask is zero, then zero bits are\n" +"set, so characters[] contains only one record. If `mask' is (SHIFT_MASK |\n" +"CONTROL_MASK), then two bits are set, so characters[] contains four\n" +"records.\n" +"\n" +"The first record always represents the character which is generated by that\n" +"key when no modifiers are active. The remaining records represent\n" +"characters generated by the various modifier combinations. Using the\n" +"example with the `shift' and `control' masks set, record two would\n" +"represent the character with the `shift' modifier active; record three, the\n" +"`control' modifier active; and record four, both the `shift' and `control'\n" +"modifiers active.\n" +"\n" +"As a special case, ALPHALOCK_MASK implies SHIFT_MASK, though only\n" +"ALPHALOCK_MASK appears in `mask'. In this case the same character is\n" +"generated for both the `shift' and `alpha-lock' modifiers, but only needs\n" +"to appear once in the characters[] array.\n" +"\n" +"CARRIAGE_RETURN_MASK does not actually refer to a modifier key. Instead,\n" +"it is used to distinguish the scan code which is given the special\n" +"pseudo-designation of `carriage return' key. Typically, this mask appears\n" +"solo in a ScanGroup record and only the two Character records for control-M\n" +"and control-C follow. This flag may be a throwback to an earlier time or\n" +"may be specially interpreted by the low-level keyboard driver, but its\n" +"purpose is otherwise enigmatic.\n" +"Character\n" +"---------\n" +"Each Character record indicates the character generated when this key is\n" +"pressed, as well as the character set which contains the character. Well\n" +"known character sets are `ASCII' and `Symbol'. The character set can also\n" +"be one of the meta values FUNCTION_KEY or KEY_SEQUENCE. If it is\n" +"FUNCTION_KEY then `char_code' represents a generally well-known function\n" +"key such as those enumerated by FunctionKey. If the character set is\n" +"KEY_SEQUENCE then `char_code' represents a zero-base index into\n" +"KeyMapping::sequence_lists[].\n" +"\n" +" enum CharacterSet {\n" +" ASCII = 0x00,\n" +" SYMBOL = 0x01,\n" +" ...\n" +" FUNCTION_KEY = 0xfe,\n" +" KEY_SEQUENCE = 0xff\n" +" };\n" +"\n" +" struct Character {\n" +" number set; // CharacterSet of generated character\n" +" number char_code; // Actual character generated\n" +" };\n" +"\n" +" enum FunctionKey {\n" +" F1 = 0x20, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,\n" +" INSERT, DELETE, HOME, END, PAGE_UP, PAGE_DOWN, PRINT_SCREEN,\n" +" SCROLL_LOCK, PAUSE, SYS_REQUEST, BREAK, RESET, STOP, MENU, USER,\n" +" SYSTEM, PRINT, CLEAR_LINE, CLEAR_DISPLAY, INSERT_LINE,\n" +" DELETE_LINE, INSERT_CHAR, DELETE_CHAR, PREV, NEXT, SELECT\n" +" };\n" +"\n" +"Sequence\n" +"--------\n" +"When Character::set contains the meta value KEY_SEQUENCE, the scan code is\n" +"bound to a sequence of keys rather than a single character. A sequence is\n" +"a series of modifiers and characters which are automatically generated when\n" +"the associated key is depressed.\n" +"\n" +" #define MODIFIER_KEY 0xff\n" +"\n" +" struct Sequence {\n" +" number num_chars;\n" +" Character characters[...];\n" +" };\n" +"\n" +"Each generated Character is represented as previously described, with the\n" +"exception that MODIFIER_KEY may appear in place of KEY_SEQUENCE. When the\n" +"value of Character::set is MODIFIER_KEY then Character::char_code\n" +"represents a modifier key rather than an actual character. If the modifier\n" +"represented by `char_code' is non-zero, then it indicates that the\n" +"associated modifier key has been depressed. In this case, the value is one\n" +"of the constants enumerated by Modifier (SHIFT, CONTROL, ALTERNATE, etc.).\n" +"If the value is zero then it means that the modifier keys have been\n" +"released.\n" +"\n" +"Special Key\n" +"-----------\n" +"A special key is one which is scanned directly by the Mach kernel rather\n" +"than by the WindowServer. In general, events are not generated for special\n" +"keys.\n" +"\n" +" enum SpecialKeyType {\n" +" VOLUME_UP = 0,\n" +" VOLUME_DOWN,\n" +" BRIGHTNESS_UP,\n" +" BRIGHTNESS_DOWN,\n" +" ALPHA_LOCK,\n" +" HELP,\n" +" POWER,\n" +" SECONDARY_ARROW_UP,\n" +" SECONDARY_ARROW_DOWN\n" +" };\n" +"\n" +" struct SpecialKey {\n" +" number type; // A SpecialKeyType constant\n" +" number scan_code; // Actual scan code\n" +" };\n" +"\n", f ); + } + + +//----------------------------------------------------------------------------- +// Print an explanation of the output generated by this program. +//----------------------------------------------------------------------------- +static void print_output_info( FILE* f ) + { + fputs( +"What follows is an explanation and description of the various pieces of\n" +"information emitted by dumpkeymap.\n" +"\n" +"For a more thorough discussion of any particular piece of information\n" +"described here, refer to the detailed description of the internal layout of\n" +"a key mapping given by the --help-layout option.\n" +"\n" +"Conventions\n" +"-----------\n" +"Depending upon context, some numeric values are displayed in decimal\n" +"notation, whereas others are displayed in hexadecimal notation.\n" +"Hexadecimal numbers are denoted by a `0x' prefix (for instance, `0x7b'),\n" +"except when explicitly noted otherwise.\n" +"\n" +"Key Mapping Source\n" +"------------------\n" +"The first piece of information presented about a particular key mapping is\n" +"the source from which the data was gleaned. For a .keymapping file, the\n" +"title `KEYMAP FILE' is emitted along with the path and name of the file in\n" +"question. For the key mapping currently in use by the WindowServer and\n" +"AppKit, the title `ACTIVE KEYMAP' is emitted instead.\n" +"\n" +"Device Information\n" +"------------------\n" +"Each .keymapping file may contain one or more raw key mappings. For\n" +"example, a file which maps keys to a Dvorak-style layout might contain raw\n" +"mappings for Intel PC, ADB, NeXT, and Sun Type5 keyboards.\n" +"\n" +"For each raw mapping, the following information is emitted:\n" +"\n" +" o The title `KEYMAP' along with the mapping's relative position in the\n" +" .keymapping file.\n" +" o The `interface' identifier.\n" +" o The `handler_id' sub-identifier.\n" +" o The size of the raw mapping resource counted in bytes.\n" +"\n" +"The `interface' and `handler_id' values, taken together, define a specific\n" +"keyboard device. A .keyboard file, which describes the visual layout of a\n" +"keyboard, also contains `interface' and `handler_id' identifiers. The\n" +".keyboard file corresponding to a particular key mapping can be found by\n" +"matching the `interface' and `handler_id' values from each resource.\n" +"\n" +"Modifiers\n" +"---------\n" +"Each mapping may contain zero or more modifier records which associate\n" +"hardware scan codes with modifier descriptions such as `shift', `control',\n" +"`alternate', etc. The title `MODIFIERS' is printed along with the count of\n" +"modifier records which follow. For each modifier record, the modifier's\n" +"name is printed along with a list of scan codes, in hexadecimal format,\n" +"which generate that modifier value. For example:\n" +"\n" +" MODIFIERS [4]\n" +" alternate: 0x1d 0x60\n" +" control: 0x3a\n" +" keypad: 0x52 0x53 ... 0x63 0x62\n" +" shift: 0x2a 0x36\n" +"\n" +"Characters\n" +"----------\n" +"Each mapping may contain zero or more character records which associate\n" +"hardware scan codes with the actual characters generated by those scan\n" +"codes in the presence or absence of various modifier combinations. The\n" +"title `CHARACTERS' is printed along with the count of character records\n" +"which follow. Here is a highly abbreviated example:\n" +"\n" +" CHARACTERS [9]\n" +" scan 0x00: -AC-L \"a\" \"A\" \"^A\" \"^A\" ca c7 \"^A\" \"^A\"\n" +" scan 0x07: -AC-L \"x\" \"X\" \"^X\" \"^X\" 01/b4 01/ce \"^X\" \"^X\"\n" +" scan 0x0a: ---S- \"<\" \">\"\n" +" scan 0x13: -ACS- \"2\" \"@\" \"^@\" \"^@\" b2 b3 \"^@\" \"^@\"\n" +" scan 0x24: R---- \"^M\" \"^C\"\n" +" scan 0x3e: ----- [F4]\n" +" scan 0x4a: ----- [page up]\n" +" scan 0x60: ----- {seq#3}\n" +" scan 0x68: not-bound\n" +"\n" +"For each record, the hexadecimal value of the hardware scan code is\n" +"printed, followed by a list of modifier flag combinations and the actual\n" +"characters generated by this scan code with and without modifiers applied.\n" +"\n" +"The modifier flags field is composed of a combination of single letter\n" +"representations of the various modifier types. The letters stand for:\n" +"\n" +" L - alpha-lock\n" +" S - shift\n" +" C - control\n" +" A - alternate\n" +" R - carriage-return\n" +"\n" +"As a special case, the `alpha-lock' flag also implies the `shift' flag, so\n" +"these two flags never appear together in the same record.\n" +"\n" +"The combination of modifier flags determines the meaning and number of\n" +"fields which follow. The first field after the modifier flags always\n" +"represents the character that will be generated if no modifier keys are\n" +"depressed. The remaining fields represent characters generated by the\n" +"various modifier combinations. The order of the fields follows this\n" +"general pattern:\n" +"\n" +" o The character generated by this scan code when no modifiers are in\n" +" effect is listed first.\n" +"\n" +" o If the `L' or `S' flag is active, then the shifted character\n" +" generated by this scan code is listed next.\n" +"\n" +" o If the `C' flag is active, then the control-character generated by\n" +" this scan code is listed next. Furthermore, if the `L' or `S' flag\n" +" is also active, then the shifted control-character is listed after\n" +" that.\n" +"\n" +" o If the `A' flag is active, then the alternate-character generated by\n" +" this scan code is listed next. Furthermore, if the `L' or `S' flag\n" +" is active, then the shifted alternate-character is listed after that.\n" +" If the `C' flag is also active, then the alternate-control-character\n" +" is listed next. Finally, if the `C' and `L' or `C' and `S' flags are\n" +" also active, then the shifted alternate-control-character is listed.\n" +"\n" +"The `R' flag does not actually refer to a modifier key. Instead, it is\n" +"used to distinguish the scan code which is given the special\n" +"pseudo-designation of `carriage return' key. Typically, this mask appears\n" +"solo and only the two fields for control-M and control-C follow. This flag\n" +"may be a throwback to an earlier time or may be specially interpreted by\n" +"the low-level keyboard driver, but its purpose is otherwise enigmatic.\n" +"\n" +"Recalling the example from above, the following fields can be identified:\n" +"\n" +" scan 0x00: -AC-L \"a\" \"A\" \"^A\" \"^A\" ca c7 \"^A\" \"^A\"\n" +"\n" +" o Lower-case `a' is generated when no modifiers are active.\n" +" o Upper-case `A' is generated when `shift' or `alpha-lock' are active.\n" +" o Control-A is generated when `control' is active.\n" +" o Control-A is generated when `control' and `shift' are active.\n" +" o The character represented by the hexadecimal code 0xca is generated\n" +" when `alternate' is active.\n" +" o The character represented by 0xc7 is generated when `alternate' and\n" +" `shift' (or `alpha-lock') are active.\n" +" o Control-A is generated when `alternate' and `control' are active.\n" +" o Control-A is generated when `alternate', `control' and `shift' (or\n" +" `alpha-lock') are active.\n" +"\n" +"The notation used to represent a particular generated character varies.\n" +"\n" +" o Printable ASCII characters are quoted, as in \"x\" or \"X\".\n" +"\n" +" o Control-characters are quoted and prefixed with `^', as in \"^X\".\n" +"\n" +" o Characters with values greater than 127 (0x7f) are displayed as\n" +" hexadecimal values without the `0x' prefix.\n" +"\n" +" o Characters in a non-ASCII character set (such as `Symbol') are\n" +" displayed as two hexadecimal numbers separated by a slash, as in\n" +" `01/4a'. The first number is the character set's identification code\n" +" (such as `01' for the `Symbol' set), and the second number is the\n" +" value of the generated character.\n" +"\n" +" o Non-printing special function characters are displayed with the\n" +" function's common name enclosed in brackets, as in `[page up]' or\n" +" `[F4]'.\n" +"\n" +" o If the binding represents a key sequence rather than a single\n" +" character, then the sequence's identification number is enclosed in\n" +" braces, as in `{seq#3}'.\n" +"\n" +"Recalling a few examples from above, the following interpretations can be\n" +"made:\n" +"\n" +" scan 0x07: -AC-L \"x\" \"X\" \"^X\" \"^X\" 01/b4 01/ce \"^X\" \"^X\"\n" +" scan 0x3e: ----- [F4]\n" +" scan 0x4a: ----- [page up]\n" +" scan 0x60: ----- {seq#3}\n" +"\n" +" o \"x\" and \"X\" are printable ASCII characters.\n" +" o \"^X\" is a control-character.\n" +" o `01/b4' and `01/ce' represent the character codes 0xb4 and 0xce in\n" +" the `Symbol' character set.\n" +" o Scan code 0x3e generates function-key `F4', and scan code 0x4a\n" +" generates function-key `page up'.\n" +" o Scan code 0x60 is bound to key sequence #3.\n" +"\n" +"Finally, if a scan code is not bound to any characters, then it is\n" +"annotated with the label `not-bound', as with example scan code 0x68 from\n" +"above.\n" +"\n" +"Sequences\n" +"---------\n" +"A scan code (modified and unmodified) can be bound to a key sequence rather\n" +"than generating a single character or acting as a modifier. When it is\n" +"bound to a key sequence, a series of character invocations and modifier\n" +"actions are automatically generated rather than a single keystroke.\n" +"\n" +"Each mapping may contain zero or more key sequence records. The title\n" +"`SEQUENCES' is printed along with the count of sequence records which\n" +"follow. For example:\n" +"\n" +" SEQUENCES [3]\n" +" sequence 0: \"f\" \"o\" \"o\"\n" +" sequence 1: {alternate} \"b\" \"a\" \"r\" {unmodify}\n" +" sequence 2: [home] \"b\" \"a\" \"z\"\n" +"\n" +"The notation used to represent the sequence of generated characters is\n" +"identical to the notation already described in the `Characters' section\n" +"above, with the exception that modifier actions may be interposed between\n" +"generated characters. Such modifier actions are represented by the\n" +"modifier's name enclosed in braces. The special name `{unmodify}'\n" +"indicates the release of the modifier keys.\n" +"\n" +"Thus, the sequences in the above example can be interpreted as follows:\n" +"\n" +" o Sequence #0 generates `foo'.\n" +" o Sequence #1 invokes the `alternate' modifier, generates `bar', and\n" +" then releases `alternate'.\n" +" o Sequence #2 invokes the `home' key and then generates `baz'. In a\n" +" text editor, this would probably result in `baz' being prepended to\n" +" the line of text on which the cursor resides.\n" +"\n" +"Special Keys\n" +"------------\n" +"Certain keyboards feature keys which perform some type of special purpose\n" +"function rather than generating a character or acting as a modifier. For\n" +"instance, Apple keyboards often contain a `power' key, and NeXT keyboards\n" +"have historically featured screen brightness and volume control keys.\n" +"\n" +"Each mapping may contain zero or more special-key records which associate\n" +"hardware scan codes with such special purpose functions. The title\n" +"`SPECIALS' is printed along with the count of records which follow. For\n" +"each record, the special function's name is printed along with a list of\n" +"scan codes, in hexadecimal format, which are bound to that function. For\n" +"example:\n" +"\n" +" SPECIALS [6]\n" +" alpha-lock: 0x39\n" +" brightness-down: 0x79\n" +" brightness-up: 0x74\n" +" power: 0x7f\n" +" sound-down: 0x77\n" +" sound-up: 0x73\n" +"\n", f ); + } + + +//----------------------------------------------------------------------------- +// Print a summary of the various files and directories which are related to +// key mappings. +//----------------------------------------------------------------------------- +static void print_files_info( FILE* f ) + { + fputs( +"This is a summary of the various files and directories which are related to\n" +"key mappings.\n" +"\n" +"*.keymapping\n" +" A key mapping file which precisely defines the relationship of all\n" +" hardware-specific keyboard scan-codes with their associated\n" +" functionality.\n" +"\n" +"*.keyboard\n" +" A file describing the physical layout of keys on a particular type of\n" +" keyboard. Each `key' token in this file defines the position and shape\n" +" of the key on the keyboard, as well as the associated scan code which\n" +" that key generates. A .keymapping file, on the other hand, defines the\n" +" characters which are generated by a particular scan code depending upon\n" +" the state of the various modifier keys (such as shift, control, etc.).\n" +" The `interface' and `handler_id' values from a .keymapping file are\n" +" matched against those in each .keyboard file in order to associate a\n" +" particular .keyboard file with a key mapping. Various GUI programs use\n" +" the .keyboard file to display a visual representation of a keyboard for\n" +" the user. Since these files are just plain text, they can be easily\n" +" viewed and interpreted without the aid of a specialized program, thus\n" +" dumpkeymap leaves these files alone.\n" +"\n" +"/System/Library/Keyboards\n" +"/Network/Library/Keyboards\n" +"/Local/Library/Keyboards\n" +"/Library/Keyboards\n" +" Repositories for .keymapping and .keyboard files for MacOS/X, Darwin,\n" +" and MacOS/X Server.\n" +"\n" +"/NextLibrary/Keyboards\n" +"/LocalLibrary/Keyboards\n" +" Repositories for .keymapping and .keyboard files for OpenStep and\n" +" NextStep.\n" +"\n" +"$(HOME)/Library/Keyboards\n" +" Repository for personal .keymapping and .keyboard files.\n" +"\n", f ); + } + + +//----------------------------------------------------------------------------- +// Print a list of the various diagnostic messages which may be emitted. +//----------------------------------------------------------------------------- +static void print_diagnostics_info( FILE* f ) + { + fputs( +"The following diagnostic messages may be issued to the standard error\n" +"stream.\n" +"\n" +"Unrecognized option.\n" +" An unrecognized option was specified on the command-line. Invoke\n" +" dumpkeymap with the --help option to view a list of valid options.\n" +"\n" +"Insufficient data in keymapping data stream.\n" +" The key mapping file or data stream is corrupt. Either the file has\n" +" been incorrectly truncated or a field, such as those which indicates\n" +" the number of variable records which follow, contains a corrupt value.\n" +"\n" +"The following diagnostic messages have significance only when trying to\n" +"print .keymapping files mentioned on the command-line.\n" +"\n" +"Bad magic number.\n" +" The mentioned file is not a .keymapping file. The file's content does\n" +" not start with the string `KYM1'.\n" +"\n" +"Unable to open key mapping file.\n" +" The call to fopen() failed; probably because the specified path is\n" +" invalid or dumpkeymap does not have permission to read the file.\n" +"\n" +"Unable to determine key mapping file size.\n" +" The call to fstat() failed, thus memory can not be allocated for\n" +" loading the file.\n" +"\n" +"Unable to read key mapping file.\n" +" The call to fread() failed.\n" +"\n" +"The following diagnostic messages have significance only when trying to\n" +"print the currently active key mapping when no .keymapping files have been\n" +"mentioned on the command-line.\n" +"\n" +"Unable to open event status driver.\n" +" The call to NXOpenEventStatus() failed.\n" +"\n" +"Bad key mapping length.\n" +" The call to NXKeyMappingLength() returned a bogus value.\n" +"\n" +"Unable to get current key mapping.\n" +" The call to NXGetKeyMapping() failed.\n" +"\n" +"The following diagnostic messages have significance only when using\n" +"dumpkeymap on a non-Apple/NeXT platform.\n" +"\n" +"Must specify at least one .keymapping file.\n" +" No .keymapping files were mentioned on the command-line. On\n" +" non-Apple/NeXT platforms, there is no concept of a currently active\n" +" .keymapping file, so at least one file must be mentioned on the\n" +" command-line.\n" +"\n", f ); + } + + +//----------------------------------------------------------------------------- +// Print warranty. +//----------------------------------------------------------------------------- +static void print_warranty( FILE* f ) + { + fputs( +"This software is provided by the author `AS IS' and any express or implied\n" +"WARRANTIES, including, but not limited to, the implied warranties of\n" +"MERCHANTABILITY and FITNESS FOR A PARTICULAR PURPOSE are DISCLAIMED. In NO\n" +"EVENT shall the author be LIABLE for any DIRECT, INDIRECT, INCIDENTAL,\n" +"SPECIAL, EXEMPLARY, or CONSEQUENTIAL damages (including, but not limited\n" +"to, procurement of substitute goods or services; loss of use, data, or\n" +"profits; or business interruption) however caused and on any theory of\n" +"liability, whether in contract, strict liability, or tort (including\n" +"negligence or otherwise) arising in any way out of the use of this\n" +"software, even if advised of the possibility of such damage.\n" +"\n", f ); + } + + +//----------------------------------------------------------------------------- +// Print this program's version number. +//----------------------------------------------------------------------------- +static void print_version( FILE* f ) + { + fputs( "Version " PROG_VERSION " (built " __DATE__ ")\n\n", f ); + } + + +//----------------------------------------------------------------------------- +// Print a usage summary. +//----------------------------------------------------------------------------- +static void print_usage( FILE* f ) + { + fputs( +"Usage: dumpkeymap [options] [-] [file ...]\n" +"\n" +"Prints a textual representation of each Apple/NeXT .keymapping file\n" +"mentioned on the command-line. If no files are mentioned and if the local\n" +"machine is an Apple or NeXT installation, then the key mapping currently in\n" +"use by the WindowServer and the AppKit is printed instead.\n" +"\n" +"Options:\n" +" -h --help\n" +" Display general program instructions and option summary.\n" +"\n" +" -k --help-keymapping\n" +" Display a detailed description of the internal layout of a\n" +" .keymapping file.\n" +"\n" +" -o --help-output\n" +" Display an explanation of the output generated by dumpkeymap when\n" +" dissecting a .keymapping file.\n" +"\n" +" -f --help-files\n" +" Display a summary of the various files and directories which are\n" +" related to key mappings.\n" +"\n" +" -d --help-diagnostics\n" +" Display a list of the various diagnostic messages which may be\n" +" emitted by dumpkeymap.\n" +"\n" +" -v --version\n" +" Display the dumpkeymap version number and warranty information.\n" +"\n" +" - --\n" +" Inhibit processing of options at this point in the argument list.\n" +" An occurrence of `-' or `--' in the argument list causes all\n" +" following arguments to be treated as file names even if an argument\n" +" begins with a `-' character.\n" +"\n", f ); + } + + +//----------------------------------------------------------------------------- +// Print an informational banner. +//----------------------------------------------------------------------------- +static void print_banner( FILE* f ) + { + fputs( "\n" PROG_NAME " v" PROG_VERSION " by " AUTHOR_INFO "\n" + COPYRIGHT "\n\n", f ); + } + + +//----------------------------------------------------------------------------- +// Process command-line arguments. Examine options first; collecting files +// along the way. If all is well, process collected file list. +//----------------------------------------------------------------------------- +int main( int const argc, char const* const argv[] ) + { + int rc = 0, i, nfiles = 0, more_options = 1, process_files = 1; + int* files = (int*)calloc( argc - 1, sizeof(int) ); + print_banner( stdout ); + + for (i = 1; i < argc; i++) + { + char const* const s = argv[i]; + if (!more_options || *s != '-') + files[ nfiles++ ] = i; + else + { + OPT_SWITCH(s) + OPT_CASE(-,--) + more_options = 0; + OPT_CASE(-h,--help) + print_usage( stdout ); + process_files = 0; + OPT_CASE(-k,--help-keymapping) + print_internal_layout_info( stdout ); + process_files = 0; + OPT_CASE(-o,--help-output) + print_output_info( stdout ); + process_files = 0; + OPT_CASE(-f,--help-files) + print_files_info( stdout ); + process_files = 0; + OPT_CASE(-d,--help-diagnostics) + print_diagnostics_info( stdout ); + process_files = 0; + OPT_CASE(-v,--version) + print_version( stdout ); + print_warranty( stdout ); + process_files = 0; + OPT_DEFAULT + fprintf( stderr, "ERROR: Unrecognized option: %s\n\n", s ); + process_files = 0; + rc = 1; + OPT_SWITCH_END + } + } + + if (process_files) + { + if (nfiles == 0) + rc = handle_empty_document_list(); + else + for (i = 0; i < nfiles; i++) + rc |= unparse_keymap_file( argv[files[i]] ); + } + + free( files ); + return rc; + } diff --git a/nx-X11/programs/Xserver/hw/darwin/utils/dumpkeymap.man b/nx-X11/programs/Xserver/hw/darwin/utils/dumpkeymap.man new file mode 100644 index 000000000..12983bada --- /dev/null +++ b/nx-X11/programs/Xserver/hw/darwin/utils/dumpkeymap.man @@ -0,0 +1,1004 @@ +.ig +//============================================================================= +// +// Manual page for `dumpkeymap'. +// +// 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. +// +//============================================================================= +// +// $XFree86$ +// +.. +.ig +//----------------------------------------------------------------------------- +// Local identification information. +//----------------------------------------------------------------------------- +.. +.nr VE 4 \" Version number +.TH DUMPKEYMAP 1 "v\n(VE \-\- 1 December 2000" "Version \n(VE" +.de UP +1 December 2000 +.. +.ig +//----------------------------------------------------------------------------- +// Annotation Macros +// ----------------- +// Facilitate creation of annotated, non-filled blocks of text. An +// annotated block is initiated with the `AS' macro. Each annotated, +// non-filled line within the block must be introduced with the `AN' macro +// which takes three arguments. The first argument is the detail text to +// be annotated. The second is a string of spaces used to align the +// annotations by certain (broken) roff interpreters which fail to +// implement the proper set of roff commands (such as diversions, +// indentation, and tab stops). It is assumed that the spaces will be +// used with fixed-point font. The third argument is the annotation +// itself. The block should be terminated with the `AE' macro. For all +// roff interpreters which properly implement diversions, indentation, and +// tab stops, all anotations within the block are automatically aligned at +// the same horizontal position. This position is guaranteed to be just +// to the right of the widest `AN' detail line. For broken roff +// interpreters, such as `rman', the string of spaces from the second +// argument are used to align the annotations. Finally, the `AZ' macro, +// which takes a single argument, can be used to to insert a non-annotated +// line into the block which does not play a part in the calculation of +// the horizontal annotation alignment. +// +// Implementation Notes +// -------------------- +// *1* These macros utilize a diversion (named `AD'). Since the prevailing +// indentation is stored along with the diverted text, we must muck with +// the indentation level in order to prevent the indentation from being +// applied to the text a second time when `AD' is finally emitted. +// +// *2* Unfortunately, `.if' strips leading whitespace from following text, so +// `AN' uses \& to preserve the whitespace. +// +// *3* This manual page has been tested for proper formatting with troff, +// groff, nroff and rman (the `man' to `HTML' converter). Unfortunately, +// rman fails to implement many useful features such as diversions, +// indentation, and tab stops, and is also hideously buggy. Furthermore +// it identifies itself as nroff and fails to provide any further +// identification, so there is no way to create macros which specifically +// work around its limitations. Following is a list of several bugs in +// rman which the implementation of these macros must avoid: +// o Fails with multi-line conditionals within macros. +// o Fails on macro definition within multi-line conditionals. +// o Fails when macro arguments are not delimited by exactly 1 space. +// o String definition `.ds' ignores the value; uses empty "" instead. +// As a consequence of these problems, the following macros are written +// using a series of ugly single-line `.if' conditionals rather than the +// more natural multi-line `.if' and `.ie' conditionals. Also, rman fails +// to understand the common idiom of `.\"' to introduce a comment, which +// is why all comments in this file are wrapped in ignore `.ig' blocks. +//----------------------------------------------------------------------------- +.. +.de AS +.if t .nr AW 0 +.if t .nr AI \\n(.i +.if t .in -\\n(AI +.nf +.. +.de AN +.if t .if \w'\\$1'>\\n(AW .nr AW \w'\\$1' +.if t .da AD +.if t \\&\\$1\\t\\$3 +.if t .da +.if n \\&\\$1 \\$2\\$3 +.. +.de AZ +.if t .da AD +\\$1 +.if t .da +.. +.de AE +.if t .in +\\n(AIu +.if t .if \\n(AW .ta \\n(AWu+\w'\\(em'u +.if t .AD +.if t .DT +.if t .rm AD +.if t .rm AW +.fi +.. +.ig +//----------------------------------------------------------------------------- +// Bulleted list macros -- `BG' begins a bulleted list; `BU' delimits +// bulleted entries; `BE' ends a bulleted list. +//----------------------------------------------------------------------------- +.. +.de BG +.PP +.RS +.. +.de BU +.HP +\\(bu\\ \\c +.. +.de BE +.RE +.PP +.. +.ig +//----------------------------------------------------------------------------- +// Indented paragraph with stylized hanging tag macro. `TG' takes a single +// argument and treats it as the hanging tag of the indented paragraph. +// The tag is italicized in troff but not in nroff. +//----------------------------------------------------------------------------- +.. +.de TG +.TP +.ie t .I "\\$1" +.el \\$1 +.. +.ig +//----------------------------------------------------------------------------- +// Manual page for `dumpkeymap'. +//----------------------------------------------------------------------------- +.. +.SH NAME +dumpkeymap \- Dianostic dump of a .keymapping file +.SH SYNOPSIS +.B dumpkeymap +.RI [ options "] [-] [" file "...]" +.SH DESCRIPTION +.I dumpkeymap +prints a textual representation of each Apple/\c +.SM NeXT +.I .keymapping +file mentioned on the command-line. If no files are mentioned and if the +local machine is an Apple or +.SM NeXT +installation, then the key mapping currently in use by the WindowServer and the +AppKit is printed instead. +.SH OPTIONS +.TP +.B "\-h \-\^\-help" +Display general program instructions and option summary. +.TP +.B "\-k \-\^\-help\-keymapping" +Display a detailed description of the internal layout of a +.I .keymapping +file. This is the same information as that presented in the +.I "Key Mapping Description" +section of this document. +.TP +.B "\-o \-\^\-help\-output" +Display an explanation of the output generated by +.I dumpkeymap +when dissecting a +.I .keymapping +file. This is the same information as that presented in the +.I "Output Description" +section of this document. +.TP +.B "\-f \-\^\-help\-files" +Display a summary of the various files and directories which are related to +key mappings. This is the same information as that presented in the +.I "Files" +section of this document. +.TP +.B "\-d \-\^\-help\-diagnostics" +Display a list of the various diagnostic messages which may be emitted by +.I dumpkeymap. +This is the same information as that presented in the +.I "Diagnostics" +section of this document. +.TP +.B "\-v \-\^\-version" +Display the +.I dumpkeymap +version number and warranty information. +.TP +.B "\- \-\^\-" +Inhibit processing of options at this point in the argument list. An +occurrence of `\-' or `\-\^\-' in the argument list causes all following +arguments to be treated as file names even if an argument begins with a `\-' +character. +.SH "KEY MAPPING DESCRIPTION" +The following sections describe, in complete detail, the format of a raw key +mapping resource, as well as the format of the +.I .keymapping +file which encapsulates one or more raw mappings. +.SH "Types and Data" +The following type definitions are employed throughout this discussion: +.PP +.RS +.AS +.AZ "typedef unsigned char byte;" +.AZ "typedef unsigned short word;" +.AZ "typedef unsigned long dword;" +.AE +.RE +.PP +Additionally, the type definition +.RI ` number ' +is used generically to +indicate a numeric value. The actual size of the +.RI ` number ' +type may be one or two bytes depending upon how the data is stored in the key +map. Although most key maps use byte-sized numeric values, word-sized values +are also allowed. +.PP +Multi-byte values in a key mapping file are stored in big-endian byte order. +.SH "Key Mapping File and Device Mapping" +A key mapping file begins with a magic-number and continues with a +variable number of device-specific key mappings. +.PP +.RS +.AS +.AZ "struct KeyMappingFile {" +.AN " char magic_number[4];" " " "// `KYM1'" +.AN " DeviceMapping maps[...];" "" "// Variable number of maps" +.AZ }; +.AE +.PP +.AS +.AZ "struct DeviceMapping {" +.AN " dword interface;" " " "// Interface type" +.AN " dword handler_id;" "" "// Interface subtype" +.AN " dword map_size;" " " "// Byte count of `map' (below)" +.AN " KeyMapping map;" +.AZ }; +.AE +.RE +.PP +The value of `interface' represents a family of keyboard device types +(such as Intel +.SM "PC, ADB, NeXT," +Sun Type5, etc.), and is generally specified as one of the constant values +.SM "NX_EVS_DEVICE_INTERFACE_ADB, NX_EVS_DEVICE_INTERFACE_ACE," +etc., which are are defined in IOHIDTypes.h on MacOS/X and Darwin, and in +ev_types.h on MacOS/X Server, OpenStep, and NextStep. +.PP +The value of `handler_id' represents a specific keyboard layout within the +much broader `interface' family. For instance, for a 101-key Intel +.SM PC +keyboard (of type +.SM NX_EVS_DEVICE_INTERFACE_ACE\c +) the `handler_id' is '0', whereas for a 102-key keyboard it is `1'. +.PP +Together, `interface' and `handler_id' identify the exact keyboard hardware to +which this mapping applies. Programs which display a visual representation of +a keyboard layout, match `interface' and `handler_id' from the +.I .keymapping +file against the `interface' and `handler_id' values found in each +.I .keyboard +file. +.SH "Key Mapping" +A key mapping completely defines the relationship of all scan codes with their +associated functionality. A +.I KeyMapping +structure is embedded within the +.I DeviceMapping +structure in a +.IR KeyMappingFile . +The key mapping currently in use by the WindowServer and AppKit is also +represented by a +.I KeyMapping +structure, and can be referred to directly by calling NXGetKeyMapping() and +accessing the `mapping' data member of the returned +.I NXKeyMapping +structure. +.PP +.RS +.AS +.AZ "struct KeyMapping {" +.AN " word number_size;" " " "// 0=1 byte, non-zero=2 bytes" +.AN " number num_modifier_groups;" "" "// Modifier groups" +.AZ " ModifierGroup modifier_groups[...];" +.AN " number num_scan_codes;" " " "// Scan groups" +.AN " ScanGroup scan_table[...];" +.AN " number num_sequence_lists;" " " "// Sequence lists" +.AN " Sequence sequence_lists[...];" +.AN " number num_special_keys;" " " "// Special keys" +.AN " SpecialKey special_key[...];" +.AZ }; +.AE +.RE +.PP +The `number_size' flag determines the size, in bytes, of all remaining numeric +values (denoted by the type definition +.RI ` number ') +within the +key mapping. If its value is zero, then numbers are represented by a single +byte. If it is non-zero, then numbers are represented by a word (two bytes). +.SH "Modifier Group" +A modifier group defines all scan codes which map to a particular type of +modifier, such as +.IR shift , +.IR control , +etc. +.PP +.RS +.AS +.AZ "enum Modifier {" +.AZ " ALPHALOCK = 0," +.AZ " SHIFT," +.AZ " CONTROL," +.AZ " ALTERNATE," +.AZ " COMMAND," +.AZ " KEYPAD," +.AZ " HELP" +.AZ }; +.AE +.PP +.AS +.AZ "struct ModifierGroup {" +.AN " number modifier;" " " "// A Modifier constant" +.AN " number num_scan_codes;" +.AN " number scan_codes[...];" "" "// Variable number of scan codes" +.AZ }; +.AE +.RE +.PP +The scan_codes[] array contains a list of all scan codes which map to the +specified modifier. The +.IR shift ", " command ", and " alternate +modifiers are frequently mapped to two different scan codes, apiece, +since these modifiers often appear on both the left and right sides of +the keyboard. +.SH "Scan Group" +There is one +.I ScanGroup +for each scan code generated by the given keyboard. This number is given by +KeyMapping::num_scan_codes. The first scan group represents hardware scan +code 0, the second represents scan code 1, etc. +.PP +.RS +.AS +.AZ "enum ModifierMask {" +.AN " ALPHALOCK_MASK" " " "= 1 << 0," +.AN " SHIFT_MASK" " " "= 1 << 1," +.AN " CONTROL_MASK" " " "= 1 << 2," +.AN " ALTERNATE_MASK" " " "= 1 << 3," +.AN " CARRIAGE_RETURN_MASK" "" "= 1 << 4" +.AZ }; +.AZ "#define NOT_BOUND 0xff" +.AE +.PP +.AS +.AZ "struct ScanGroup {" +.AN " number mask;" +.AN " Character characters[...];" +.AZ }; +.AE +.RE +.PP +For each scan code, `mask' defines which modifier combinations generate +characters. If `mask' is +.SM NOT_BOUND +(0xff) then then this scan code does not generate any characters ever, and its +characters[] array is zero length. Otherwise, the characters[] array contains +one +.I Character +record for each modifier combination. +.PP +The number of records in characters[] is determined by computing (1 << +bits_set_in_mask). In other words, if mask is zero, then zero bits are set, +so characters[] contains only one record. If `mask' is +.SM "(SHIFT_MASK | CONTROL_MASK)," +then two bits are set, so characters[] contains four records. +.PP +The first record always represents the character which is generated by that +key when no modifiers are active. The remaining records represent characters +generated by the various modifier combinations. Using the example with the +.I shift +and +.I control +masks set, record two would represent the character with the +.I shift +modifier active; record three, the +.I control +modifier active; and record four, both the +.I shift +and +.I control +modifiers active. +.PP +As a special case, +.SM ALPHALOCK_MASK +implies +.SM SHIFT_MASK, +though only +.SM ALPHALOCK_MASK +appears in `mask'. In this case the same character is generated for both the +.I shift +and +.I alpha-lock +modifiers, but only needs to appear once in the characters[] array. +.PP +.SM CARRIAGE_RETURN_MASK +does not actually refer to a modifier key. Instead, it is used to +distinguish the scan code which is given the special pseudo-designation of +.I "carriage return" +key. Typically, this mask appears solo in a +.I ScanGroup +record and only the two +.I Character +records for control-M and control-C follow. This flag may be a throwback to +an earlier time or may be specially interpreted by the low-level keyboard +driver, but its purpose is otherwise enigmatic. +.SH Character +Each +.I Character +record indicates the character generated when this key is pressed, as well as +the character set which contains the character. Well known character sets are +.SM `ASCII' +and `Symbol'. The character set can also be one of the meta values +.SM FUNCTION_KEY +or +.SM KEY_SEQUENCE. +If it is +.SM FUNCTION_KEY +then `char_code' represents a generally well-known function key such as those +enumerated by +.I FunctionKey. +If the character set is +.SM KEY_SEQUENCE +then `char_code' represents is a zero-base index into +KeyMapping::sequence_lists[]. +.PP +.RS +.AS +.AZ "enum CharacterSet {" +.AN " ASCII" " " "= 0x00," +.AN " SYMBOL" " " "= 0x01," +.AN " ..." +.AN " FUNCTION_KEY" "" "= 0xfe," +.AN " KEY_SEQUENCE" "" "= 0xff" +.AZ }; +.AE +.PP +.AS +.AZ "struct Character {" +.AN " number set;" " " "// CharacterSet of generated character" +.AN " number char_code;" "" "// Actual character generated" +.AZ }; +.AE +.PP +.AS +.AZ "enum FunctionKey {" +.AZ " F1 = 0x20, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12," +.AZ " INSERT, DELETE, HOME, END, PAGE_UP, PAGE_DOWN, PRINT_SCREEN," +.AZ " SCROLL_LOCK, PAUSE, SYS_REQUEST, BREAK, RESET, STOP, MENU," +.AZ " USER, SYSTEM, PRINT, CLEAR_LINE, CLEAR_DISPLAY, INSERT_LINE," +.AZ " DELETE_LINE, INSERT_CHAR, DELETE_CHAR, PREV, NEXT, SELECT" +.AZ }; +.AE +.RE +.SH Sequence +When Character::set contains the meta value +.SM KEY_SEQUENCE, +the scan code is bound to a sequence of keys rather than a single character. +A sequence is a series of modifiers and characters which are automatically +generated when the associated key is depressed. +.PP +.RS +.AS +.AZ "#define MODIFIER_KEY 0xff" +.AE +.PP +.AS +.AZ "struct Sequence {" +.AN " number num_chars;" +.AN " Character characters[...];" +.AZ }; +.AE +.RE +.PP +Each generated +.I Character +is represented as previously described, with the exception that +.SM MODIFIER_KEY +may appear in place of +.SM KEY_SEQUENCE. +When the value of Character::set is +.SM MODIFIER_KEY +then Character::char_code represents a modifier key rather than an actual +character. If the modifier represented by `char_code' is non-zero, then it +indicates that the associated modifier key has been depressed. In this case, +the value is one of the constants enumerated by +.I Modifier +(\c +.SM "SHIFT, CONTROL, ALTERNATE," +etc.). If the value is zero then it means that the modifier keys have been +released. +.SH "Special Key" +A special key is one which is scanned directly by the Mach kernel rather than +by the WindowServer. In general, events are not generated for special keys. +.PP +.RS +.AS +.AZ "enum SpecialKeyType {" +.AZ " VOLUME_UP = 0," +.AZ " VOLUME_DOWN," +.AZ " BRIGHTNESS_UP," +.AZ " BRIGHTNESS_DOWN," +.AZ " ALPHA_LOCK," +.AZ " HELP," +.AZ " POWER," +.AZ " SECONDARY_ARROW_UP," +.AZ " SECONDARY_ARROW_DOWN" +.AZ }; +.AE +.PP +.AS +.AZ "struct SpecialKey {" +.AN " number type;" " " "// A SpecialKeyType constant" +.AN " number scan_code;" "" "// Actual scan code" +.AZ }; +.AE +.RE +.SH OUTPUT +What follows is an explanation and description of the various pieces of +information emitted by +.I dumpkeymap. +.PP +For a more thorough discussion of any particular piece of information described +here, refer to the detailed description of the internal layout of a key mapping +provided by the +.I "Key Mapping Description" +section above. +.SH Conventions +Depending upon context, some numeric values are displayed in decimal +notation, whereas others are displayed in hexadecimal notation. +Hexadecimal numbers are denoted by a `0x' prefix (for instance, `0x7b'), +except when explicitly noted otherwise. +.SH "Key Mapping Source" +The first piece of information presented about a particular key mapping is the +source from which the data was gleaned. For a +.I .keymapping +file, the title +.SM "`KEYMAP FILE'" +is emitted along with the path and name of the file in question. For the key +mapping currently in use by the WindowServer and AppKit, the title +.SM "`ACTIVE KEYMAP'" +is emitted instead. +.SH "Device Information" +Each +.I .keymapping +file may contain one or more raw key mappings. For example, a file which maps +keys to a Dvorak-style layout might contain raw mappings for Intel +.SM "PC, ADB, NeXT," +and Sun Type5 keyboards. +.PP +For each raw mapping, the following information is emitted: +.BG +.BU +The title +.SM `KEYMAP' +along with the mapping's relative position in the +.I .keymapping +file. +.BU +The `interface' identifier. +.BU +The `handler_id' sub-identifier. +.BU +The size of the raw mapping resource counted in bytes. +.BE +The `interface' and `handler_id' values, taken together, define a specific +keyboard device. A +.I .keyboard +file, which describes the visual layout of a keyboard, also contains +`interface' and `handler_id' identifiers. The +.I .keyboard +file corresponding to a particular key mapping can be found by matching the +`interface' and `handler_id' values from each resource. +.SH Modifiers +Each mapping may contain zero or more modifier records which associate hardware +scan codes with modifier descriptions such as +.I "shift, control, alternate," +etc. The title +.SM `MODIFIERS' +is printed along with the count of modifier records which follow. For each +modifier record, the modifier's name is printed along with a list of scan +codes, in hexadecimal format, which generate that modifier value. For example: +.PP +.RS +.nf +MODIFIERS [4] +alternate: 0x1d 0x60 +control: 0x3a +keypad: 0x52 0x53 ... 0x63 0x62 +shift: 0x2a 0x36 +.fi +.RE +.SH Characters +Each mapping may contain zero or more character records which associate +hardware scan codes with the actual characters generated by those scan +codes in the presence or absence of various modifier combinations. The +title +.SM `CHARACTERS' +is printed along with the count of character records which follow. Here is a +highly abbreviated example: +.PP +.RS +.nf +CHARACTERS [9] +scan 0x00: -AC-L "a" "A" "^A" "^A" ca c7 "^A" "^A" +scan 0x07: -AC-L "x" "X" "^X" "^X" 01/b4 01/ce "^X" "^X" +scan 0x0a: ---S- "<" ">" +scan 0x13: -ACS- "2" "@" "^@" "^@" b2 b3 "^@" "^@" +scan 0x24: R---- "^M" "^C" +scan 0x3e: ----- [F4] +scan 0x4a: ----- [page up] +scan 0x60: ----- {seq#3} +scan 0x68: not-bound +.fi +.RE +.PP +For each record, the hexadecimal value of the hardware scan code is printed, +followed by a list of modifier flag combinations and the actual characters +generated by this scan code with and without modifiers applied. +.PP +The modifier flags field is composed of a combination of single letter +representations of the various modifier types. The letters stand for: +.PP +.RS +.nf +L \- alpha-lock +S \- shift +C \- control +A \- alternate +R \- carriage-return +.fi +.RE +.PP +As a special case, the +.I alpha-lock +flag also implies the +.I shift +flag, so these two flags never appear together in the same record. +.PP +The combination of modifier flags determines the meaning and number of fields +which follow. The first field after the modifier flags always represents the +character that will be generated if no modifier keys are depressed. The +remaining fields represent characters generated by the various modifier +combinations. The order of the fields follows this general pattern: +.BG +.BU +The character generated by this scan code when no modifiers are in effect is +listed first. +.BU +If the `L' or `S' flag is active, then the shifted character generated by this +scan code is listed next. +.BU +If the `C' flag is active, then the control-character generated by this scan +code is listed next. Furthermore, if the `L' or `S' flag is also active, then +the shifted control-character is listed after that. +.BU +If the `A' flag is active, then the alternate-character generated by this scan +code is listed next. Furthermore, if the `L' or `S' flag is active, then the +shifted alternate-character is listed after that. If the `C' flag is also +active, then the alternate-control-character is listed next. Finally, if the +`C' and `L' or `C' and `S' flags are also active, then the shifted +alternate-control-character is listed. +.BE +The `R' flag does not actually refer to a modifier key. Instead, it is used to +distinguish the scan code which is given the special pseudo-designation of +.I "carriage return" +key. Typically, this mask appears solo and only the two fields for control-M +and control-C follow. This flag may be a throwback to an earlier time or may +be specially interpreted by the low-level keyboard driver, but its purpose is +otherwise enigmatic. +.PP +Recalling the example from above, the following fields can be identified: +.PP +.RS +.nf +scan 0x00: -AC-L "a" "A" "^A" "^A" ca c7 "^A" "^A" +.fi +.RE +.BG +.BU +Lower-case `a' is generated when no modifiers are active. +.BU +Upper-case `A' is generated when +.IR shift " or " alpha-lock +are active. +.BU +Control-A is generated when +.I control +is active. +.BU +Control-A is generated when +.IR control " and " shift +are active. +.BU +The character represented by the hexadecimal code 0xca is generated when +.I alternate +is active. +.BU +The character represented by 0xc7 is generated when +.IR alternate " and " shift " (or " alpha-lock ") are active." +.BU +Control-A is generated when +.IR alternate " and " control +are active. +.BU +Control-A is generated when +.IR "alternate, control" " and " shift " (or " alpha-lock ") are active." +.BE +The notation used to represent a particular generated character varies. +.BG +.BU +Printable +.SM ASCII +characters are quoted, as in "x" or "X". +.BU +Control-characters are quoted and prefixed with `^', as in "^X". +.BU +Characters with values greater than 127 (0x7f) are displayed as hexadecimal +values without the `0x' prefix. +.BU +Characters in a non-\c +.SM ASCII +character set (such as `Symbol') are displayed as two hexadecimal numbers +separated by a slash, as in `01/4a'. The first number is the character set's +identification code (such as `01' for the `Symbol' set), and the second number +is the value of the generated character. +.BU +Non-printing special function characters are displayed with the function's +common name enclosed in brackets, as in `[page up]' or `[F4]'. +.BU +If the binding represents a key sequence rather than a single character, then +the sequence's identification number is enclosed in braces, as in `{seq#3}'. +.BE +Recalling a few examples from above, the following interpretations can be made: +.PP +.RS +.nf +scan 0x07: -AC-L "x" "X" "^X" "^X" 01/b4 01/ce "^X" "^X" +scan 0x3e: ----- [F4] +scan 0x4a: ----- [page up] +scan 0x60: ----- {seq#3} +.fi +.RE +.BG +.BU +"x" and "X" are printable +.SM ASCII +characters. +.BU +"^X" is a control-character. +.BU +`01/b4' and `01/ce' represent the character codes 0xb4 and 0xce in the `Symbol' +character set. +.BU +Scan code 0x3e generates function-key `F4', and scan code 0x4a generates +function-key `page up'. +.BU +Scan code 0x60 is bound to key sequence #3. +.BE +Finally, if a scan code is not bound to any characters, then it is annotated +with the label `not-bound', as with example scan code 0x68 from above. +.SH Sequences +A scan code (modified and unmodified) can be bound to a key sequence rather +than generating a single character or acting as a modifier. When it is bound +to a key sequence, a series of character invocations and modifier actions are +automatically generated rather than a single keystroke. +.PP +Each mapping may contain zero or more key sequence records. The title +.SM `SEQUENCES' +is printed along with the count of sequence records which follow. For example: +.PP +.RS +.nf +SEQUENCES [3] +sequence 0: "f" "o" "o" +sequence 1: {alternate} "b" "a" "r" {unmodify} +sequence 2: [home] "b" "a" "z" +.fi +.RE +.PP +The notation used to represent the sequence of generated characters is +identical to the notation already described in the +.I Characters +section above, with the exception that modifier actions may be interposed +between generated characters. Such modifier actions are represented by the +modifier's name enclosed in braces. The special name `{unmodify}' indicates +the release of the modifier keys. +.PP +Thus, the sequences in the above example can be interpreted as follows: +.BG +.BU +Sequence\ #0 generates `foo'. +.BU +Sequence\ #1 invokes the +.I alternate +modifier, generates `bar', and then releases +.I alternate. +.BU +Sequence\ #2 invokes the +.I home +key and then generates `baz'. In a text editor, this would probably result in +`baz' being prepended to the line of text on which the cursor resides. +.BE +.SH Special Keys +Certain keyboards feature keys which perform some type of special purpose +function rather than generating a character or acting as a modifier. For +instance, Apple keyboards often contain a +.I power +key, and +.SM NeXT +keyboards have historically featured screen brightness and volume control keys. +.PP +Each mapping may contain zero or more special-key records which associate +hardware scan codes with such special purpose functions. The title +.SM `SPECIALS' +is printed along with the count of records which follow. For each record, the +special function's name is printed along with a list of scan codes, in +hexadecimal format, which are bound to that function. For example: +.PP +.RS +.nf +SPECIALS [6] +alpha-lock: 0x39 +brightness-down: 0x79 +brightness-up: 0x74 +power: 0x7f +sound-down: 0x77 +sound-up: 0x73 +.fi +.RE +.SH FILES +.IP *.keymapping +A key mapping file which precisely defines the relationship of all +hardware-specific keyboard scan-codes with their associated functionality. +.IP *.keyboard +A file describing the physical layout of keys on a particular type of +keyboard. Each `key' token in this file defines the position and shape of the +key on the keyboard, as well as the associated scan code which that key +generates. A +.I .keymapping +file, on the other hand, defines the characters which are generated by a +particular scan code depending upon the state of the various modifier keys +(such as +.I shift, +.I control, +etc.). The `interface' and `handler_id' values from a +.I .keymapping +file are matched against those in each +.I .keyboard +file in order to associate a particular +.I .keyboard +file with a key mapping. Various +.SM GUI +programs use the +.I .keyboard +file to display a visual representation of a keyboard for the user. Since +these files are just plain text, they can be easily viewed and interpreted +without the aid of a specialized program, thus +.I dumpkeymap +leaves these files alone. +.PP +/System/Library/Keyboards +.br +/Network/Library/Keyboards +.br +/Local/Library/Keyboards +.br +/Library/Keyboards +.RS +Repositories for +.I .keymapping +and +.I .keyboard +files for MacOS/X, Darwin, and MacOS/X Server. +.RE +.PP +/NextLibrary/Keyboards +.br +/LocalLibrary/Keyboards +.RS +Repositories for +.I .keymapping +and +.I .keyboard +files for OpenStep and NextStep. +.RE +.IP $(HOME)/Library/Keyboards +Repository for personal +.I .keymapping +and +.I .keyboard +files. +.SH DIGANOSTICS +The following diagnostic messages may be issued to the standard error stream. +.TG "Unrecognized option." +An unrecognized option was specified on the command-line. Invoke +.I dumpkeymap +with the +.B "\-\^\-help" +option to view a list of valid options. +.TG "Insufficient data in keymapping data stream." +The key mapping file or data stream is corrupt. Either the file has been +incorrectly truncated or a field, such as those which indicates the number of +variable records which follow, contains a corrupt value. +.PP +The following diagnostic messages have significance only when trying to print +.I .keymapping +files mentioned on the command-line. +.TG "Bad magic number." +The mentioned file is not a +.I .keymapping +file. The file's content does not start with the string `KYM1'. +.TG "Unable to open key mapping file." +The call to fopen() failed; probably because the specified path is invalid or +.I dumpkeymap +does not have permission to read the file. +.TG "Unable to determine key mapping file size." +The call to fstat() failed, thus memory can not be allocated for loading the +file. +.TG "Unable to read key mapping file." +The call to fread() failed. +.PP +The following diagnostic messages have significance only when trying to print +the currently active key mapping when no +.I .keymapping +files have been mentioned on the command-line. +.TG "Unable to open event status driver." +The call to NXOpenEventStatus() failed. +.TG "Bad key mapping length." +The call to NXKeyMappingLength() returned a bogus value. +.TG "Unable to get current key mapping." +The call to NXGetKeyMapping() failed. +.PP +The following diagnostic messages have significance only when using +.I dumpkeymap +on a non-Apple/\c +.SM NeXT +platform. +.TG "Must specify at least one .keymapping file." +No +.I .keymapping +files were mentioned on the command-line. On non-Apple/\c +.SM NeXT +platforms, there is no concept of a currently active +.I .keymapping +file, so at least one file must be mentioned on the command-line. +.SH AUTHOR +Eric Sunshine <sunshine@sunshineco.com> wrote +.I dumpkeymap +and this document, the +.I "dumpkeymap user's manual." +Both +.I dumpkeymap +and this document are copyright \(co1999,2000 by Eric Sunshine +<sunshine@sunshineco.com>. All rights reserved. +.PP +The implementation of +.I dumpkeymap +is based upon information gathered on September 3, 1997 by Eric Sunshine +<sunshine@sunshineco.com> and Paul S. McCarthy <zarnuk@zarnuk.com> during an +effort to reverse engineer the format of the +.SM NeXT +.I .keymapping +file. +.if n .PP +.if n Version \n(VE \-\- +.if n .UP |