aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/hw/darwin/utils
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/hw/darwin/utils')
-rw-r--r--nx-X11/programs/Xserver/hw/darwin/utils/Imakefile10
-rw-r--r--nx-X11/programs/Xserver/hw/darwin/utils/README.txt111
-rw-r--r--nx-X11/programs/Xserver/hw/darwin/utils/dumpkeymap.c1454
-rw-r--r--nx-X11/programs/Xserver/hw/darwin/utils/dumpkeymap.man1004
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