[comp.sources.misc] v15i078: kbmap source posting

tony@ajfcal.cpsc.ucalgary.ca (Tony Field) (10/15/90)

Posting-number: Volume 15, Issue 78
Submitted-by: Tony Field <tony@ajfcal.cpsc.ucalgary.ca>
Archive-name: kbmap/part01

"kbmap" is an attempt to modify the AT&T Unix SysV/386 v3.2.2 system
keyboard map. In particular, it can make minor adjustments to the
system's keyboard scancodes to allow all "alt" keys to be used in the
gnuemacs meta-commands. Aside from the system default and emacs maps, any
keyboard map may be manually added to a "kbmap.table" file.

tony...
  --------------------------------------------------------------------

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  Readme kbmap.doc kbmap.1 kbmap.c Makefile
# Wrapped by ajf@ajfcal on Sun Sep  9 18:53:46 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Readme' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Readme'\"
else
echo shar: Extracting \"'Readme'\" \(1425 characters\)
sed "s/^X//" >'Readme' <<'END_OF_FILE'
X"kbmap" is an attempt to modify the AT&T Unix SysV/386 v3.2.2 system
Xkeyboard map. In particular, it can make minor adjustments to the
Xsystem's keyboard scancodes to allow all "alt" keys to be used in the
Xgnuemacs meta-mode. Aside from the system default and emacs maps, any
Xkeyboard map may be manually added to a "kbmap.table" file.
X
XTwo gnuemacs mappings are available: one that uses the ALT key to
Xgenerate 8th bit set letters (<letter>|0x080) and another that follows
XAT&T conventions such that the ALT key generates (<esc>N<letter>).
X
XNote that X11R2 will not recognize 8th bit set letters. If you have
XX11R2 and ascii console users, then you should use the 'conventional
X<esc>N<letter> mapping - even so, X11 uses it's own keyboard mapping
Xwhich is similar to, but not the same as, the default map. X11 will NOT
Xrecognize the mappings provided by kbmap. The differences are mostly in
Xthe assignment of the keyboard arrow keys to become Dec'ish in nature.
X
XTo add to the havoc, vtlmgr also takes liberties and twiddles the
Xkeyboard mapping.
X
Xkbmap works on AT&T Unix SysV/386 v3.2.2. It may or may not work on other
Xversions of unix.
X
X
XINSTALLATION:     Modify the Makefile to select your compiler, default
X                  bin directory and default map table name.
X                  
X                  Then:		make all
X                  
X                  Then:		read the SETUP section "kbmap.doc" to install
X
Xtony...
END_OF_FILE
if test 1425 -ne `wc -c <'Readme'`; then
    echo shar: \"'Readme'\" unpacked with wrong size!
fi
# end of 'Readme'
fi
if test -f 'kbmap.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kbmap.doc'\"
else
echo shar: Extracting \"'kbmap.doc'\" \(6313 characters\)
sed "s/^X//" >'kbmap.doc' <<'END_OF_FILE'
X
X
X     KBMAP(1)		       Unix System V		      KBMAP(1)
X
X
X     NAME
X	  kbmap	- change keyboard scancode mapping
X
X     SYNOPSIS
X	  kbmap	[-i] [-1] [-g] [-n n] [d] [-e] [-m] [-a] [-t /dev/xxx] [file]
X		 -i	 = show	index of available maps
X		 -q	 = query which table is	currently in use
X		 -g	 = generate a key map table
X		 -n n	 = set keyboard	to map 'n' mapping
X		 -d	 = set keyboard	to normal mapping
X		 -e	 = set keyboard	to <esc>N emacs	mapping
X		 -m	 = set keyboard	to meta	(8bit) emacs mapping
X		 -a	 = do not convert <alt><ctl> and <alt><shf><ctl>
X		 -t /dev/xxx = apply map to this device
X		 file	 = use specified key map file
X
X
X     DESCRIPTION
X	  Kbmap	reads a	text file containg keyboard mapping
X	  information and set the keyboard to the selected mapping.
X
X	  Kbmap	can create a standard mapping file
X	  (/local/lib/kbmap.table) that	contains the system default
X	  mapping as well as an	two different emacs mapping that allow
X	  alt to be used as the	emacs meta-key.	Other keyboard
X	  mappings may be manually added to the	kbmap.table file.
X
X	  Only root may	use this programme from	the console.
X
X	  It cannot be run from	an rc2.d/xxx file or cron.
X
X	  True META mapping (with 8th bit set) set with	-m cannot be
X	  used with X11R2 (X11 does not	use the	standard keyboard
X	  maps).  If you use X11R2 and the ascii console environments,
X	  the -e option	should be used for emacs mapping simply	to
X	  ensure that the .emacs files can be used in either mode
X	  without change.
X
X
X     OPTIONS
X	  -i   Show index of maps recorded in map.table.  The map
X	       numbers may be used with	the -n option to select	maps
X	       by number.
X
X
X	  -q   The query option	causes the current scancode table in
X	       the kernal to be	compared to all	of the tables in
X	       kbmap.table. If a match is found, the name of the
X	       currently active	table is printed.
X
X	       If vtlmgr is used, then an attempt is made to identify
X	       which keyboard map is in	use in spite of	modifications
X
X
X     Page 1					      (printed 9/9/90)
X
X
X     KBMAP(1)		       Unix System V		      KBMAP(1)
X
X
X	       made by vtlmgr.
X
X
X	  -g   Generate	a new keyboard map file.  The systems current
X	       keyboard	map is retrieved and written to	the
X	       kbmap.table file.  Two mapping files for	emacs are
X	       appended.  The system's keyboard	map is not updated.
X
X
X	  file Select file to be the generated keyboard	map file,
X	       usually kbmap.table.
X
X
X	  -d   Select the system default map from kbmap.table and
X	       update the system's current keyboard map.
X
X
X	  -e   Select the emacs	default	map from kbmap.table and
X	       update the system's current keyboard map.  Emacs	users
X	       may use alt as the meta-key.   If you press the alt key
X	       and a letter together, the letter is generated with the
X	       escape sequence <esc>N<letter>.
X
X	       If this mapping is used,	the .emacs files should
X	       contain the following:
X
X		    (define-key	global-map "\M-N" 'ESC-prefix)
X
X	       to enable the recognition of the	new escape sequences.
X
X	       The only	significant change to the AT&T standard
X	       keyboard	mapping	is that	the <alt><del> meta is enabled
X	       to allow	backward-kill-word.
X
X
X	  -m   Select the emacs	meta-key 8th bit map from kbmap.table
X	       and update the system's current keyboard	map.  Emacs
X	       users may use alt as the	meta-key.   If you press the
X	       alt key and a letter together, the letter is generated
X	       as <letter> | 0x080.
X
X	       If this mapping is used,	the .emacs files should
X	       contain the following:
X
X		    (setq meta-flag t)
X
X	       to enable the recognition 8th bit set meta characters.
X
X	       X11R2 will not recognize	8th bit	set characters.	 As a
X	       result, the -m option should not	be used	if you intend
X	       to run emacs with X11R2.
X
X
X     Page 2					      (printed 9/9/90)
X
X
X     KBMAP(1)		       Unix System V		      KBMAP(1)
X
X
X	  -n i Select the i'th map from	the kbmap.table	file and
X	       update the system.  The system default map is 0 and the
X	       emacs map is 1 or 2. If other keyboard maps are added
X	       to the end of the kbmap.table file, then	they may be
X	       accessed	by number.
X
X
X	  -a   Normally, kbmap extends mapping for <alt><ctl> and
X	       <alt><shif><ctl>	keys.  If the -a option	is used, these
X	       will be disabled.
X
X	       If the -a is used, then the gnuemacs C-M- sequences
X	       (such as	C-M-s (isearch-forward-regexp))	cannot use the
X	       <alt><ctl><letter> combinations.	 Instead, the <esc> +
X	       <ctl><letter> sequence is used.
X
X
X	  -t /dev/xxx
X	       Use the specified device	rather than stdin.  (This is
X	       not really useful.)
X
X
X     SETUP
X	  Create a basic keyboard mapping file that contains both the
X	  standard map and the emacs meta-key map:
X
X		    kbmap -g kbmap.table
X
X	  The current keyboard table is	fetched. The current mapping
X	  information as described in the keymap_t structure is
X	  written to disk file kbmap.table. The	meta-conversion	for
X	  emacs	is performed on	the structure and the resulting
X	  information is appended to kbmap.table. The new information
X	  is NOT updated in the	kernal.
X
X	  Copy kbmap.table to /local/lib/kbmap.table (or other file as
X	  specified during system compilation.)	      Any keyboard
X	  mapping may now be selected (using the default file
X	  /local/lib/kbmap.table):
X
X		kbmap -d    = select default map
X		kbmap -e    = select emacs <esc>N<letter> map
X		kbmap -m    = select emacs <letter>|0x080 meta map
X
X	  Alternatively, the key mapping may be	selected by number:
X
X		kbmap -m 0  = select map 0 (default map)
X		kbmap -m 1  = select map 1 (emacs <letter>|0x08	meta-map)
X		kbmap -m 2  = select map 2 (normal <esc>N<letter> emacs)
X		kbmap -m 3  = select map 3 (your additional)
X		   etc.
X
X
X     Page 3					      (printed 9/9/90)
X
X
X     KBMAP(1)		       Unix System V		      KBMAP(1)
X
X
X     NOTES
X	  The changes made by kbmap are	reset to system	defaults
X	  whenever the system is booted.  If permanent changes are
X	  needed, then the system default mapping in
X	  /etc/conf/pack.d/kd/Driver.o should be "zapped" with the
X	  appropriate table and	the kernal rebuilt.
X
X
X     FILES
X	  /local/lib/kbmap.table
X
X
X     AUTHOR
X	  Tony Field (tony%ajfcal@cpsc.ucalgary.ca, tony@ajfcal)
X
X
X     Page 4					      (printed 9/9/90)
X
X
END_OF_FILE
if test 6313 -ne `wc -c <'kbmap.doc'`; then
    echo shar: \"'kbmap.doc'\" unpacked with wrong size!
fi
# end of 'kbmap.doc'
fi
if test -f 'kbmap.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kbmap.1'\"
else
echo shar: Extracting \"'kbmap.1'\" \(5749 characters\)
sed "s/^X//" >'kbmap.1' <<'END_OF_FILE'
X.TH KBMAP 1 ""
X.SH NAME
Xkbmap \- change keyboard scancode mapping
X.SH SYNOPSIS
X.nf
X
Xkbmap [-i] [-1] [-g] [-n n] [d] [-e] [-m] [-a] [-t /dev/xxx] [file]
X       -i      = show index of available maps
X       -q      = query which table is currently in use
X       -g      = generate a key map table
X       -n n    = set keyboard to map 'n' mapping
X       -d      = set keyboard to normal mapping
X       -e      = set keyboard to <esc>N emacs mapping
X       -m      = set keyboard to meta (8bit) emacs mapping
X       -a      = do not convert <alt><ctl> and <alt><shf><ctl>
X       -t /dev/xxx = apply map to this device
X       file    = use specified key map file
X.fi
X
X.SH DESCRIPTION
X
XKbmap reads a text file containg keyboard mapping information and
Xset the keyboard to the selected mapping.
X
XKbmap can create a standard mapping file (/local/lib/kbmap.table)
Xthat contains the system default mapping as well as an two different
Xemacs mapping that allow
X.B alt
Xto be used as the emacs meta-key. Other
Xkeyboard mappings may be manually added to the kbmap.table file.
X
XOnly root may use this programme from the console.
X
XIt cannot be run from an rc2.d/xxx file or cron.
X
XTrue META mapping (with 8th bit set) set with -m cannot be used with 
XX11R2 (X11 does not use the standard keyboard maps).  If you use
XX11R2 and the ascii console environments, the 
X.B \-e
Xoption should be used for emacs mapping simply to ensure that
Xthe .emacs files can be used in either mode without change.
X
X.SH OPTIONS
X.TP
X.B \-i
XShow index of maps recorded in map.table.  The map numbers
Xmay be used with the 
X.B \-n
Xoption to select maps by number.
X
X.TP
X.B \-q
XThe query option causes the current scancode table
Xin the kernal to be compared to all of the tables in
X.B kbmap.table.
XIf a match is found, the name of the currently
Xactive table is printed.
X
XIf vtlmgr is used, then an attempt is made to
Xidentify which keyboard map is in use in spite
Xof modifications made by vtlmgr.
X
X.TP
X.B \-g
XGenerate a new keyboard map file.  The systems current keyboard
Xmap is retrieved and written to the
X.B kbmap.table
Xfile.  Two mapping files for emacs are appended.
XThe system's keyboard map is not updated.
X
X.TP
X.B file
XSelect
X.B file
Xto be the generated keyboard map file, usually
X.B kbmap.table.
X
X.TP
X.B \-d
XSelect the system default map from
X.B kbmap.table
Xand update the system's current keyboard map.
X
X.TP
X.B \-e
XSelect the emacs default map from
X.B kbmap.table
Xand update the system's current keyboard map.  Emacs
Xusers may use
X.B alt
Xas the meta-key.   If you press
Xthe
X.B alt
Xkey and a letter together, the letter is generated with
Xthe escape sequence <esc>N<letter>.
X
XIf this mapping is used, the \.emacs files should contain
Xthe following:
X.nf
X
X     (define-key global-map "\\M-N" 'ESC-prefix)
X.fi
X
Xto enable the recognition of the new escape sequences.
X
XThe only significant change to the AT&T standard
Xkeyboard mapping is that the <alt><del> meta is
Xenabled to allow backward-kill-word.
X
X.TP
X.B \-m
XSelect the emacs meta-key 8th bit map from
X.B kbmap.table
Xand update the system's current keyboard map.  Emacs
Xusers may use
X.B alt
Xas the meta-key.   If you press
Xthe
X.B alt
Xkey and a letter together, the letter is generated
Xas <letter> | 0x080.
X
XIf this mapping is used, the \.emacs files should contain
Xthe following:
X.nf
X
X     (setq meta-flag t)
X.fi
X
Xto enable the recognition 8th bit set meta characters.
X
XX11R2 will not recognize 8th bit set characters.  As a result,
Xthe
X.B \-m
Xoption should not be used if you intend to run emacs with
XX11R2.
X
X.TP
X.B \-n i
XSelect the 
X.B i'th
Xmap from the
X.B kbmap.table
Xfile and update the system.  The system default map is
X.B 0
Xand the emacs map is
X.B 1
Xor
X.B 2.
XIf other keyboard maps are added to the end of the
X.B kbmap.table
Xfile, then they may be accessed by number.
X
X.TP
X.B \-a
XNormally, kbmap extends mapping for <alt><ctl>
Xand <alt><shif><ctl> keys.  If the
X.B \-a
Xoption is used, these will be disabled.
X
XIf the
X.B \-a
Xis used, then the gnuemacs
XC-M- sequences (such as C-M-s (isearch-forward-regexp))
Xcannot use the <alt><ctl><letter> combinations.  Instead,
Xthe <esc> + <ctl><letter> sequence is used.
X
X.TP
X.B \-t /dev/xxx
XUse the specified device rather than stdin.
X(This is not really useful.)
X
X.SH SETUP
X
XCreate a basic keyboard mapping file that contains both the
Xstandard map and the emacs meta-key map:
X
X.nf
X          kbmap -g kbmap.table
X.fi
X
XThe current keyboard table is fetched. The current mapping
Xinformation as described in the 
X.B keymap_t
Xstructure is written to
Xdisk file 
X.B kbmap.table.
XThe meta-conversion for
X.B emacs
Xis performed on the structure and the resulting information is appended
Xto 
X.B kbmap.table.
XThe new information is NOT updated in the kernal.
X
XCopy
X.B kbmap.table
Xto
X.B \/local\/lib\/kbmap.table
X(or other file as specified during system compilation.)
X	
XAny keyboard mapping may now be selected (using the default
Xfile 
X.B \/local\/lib\/kbmap.table):
X
X.nf
X      kbmap -d    = select default map
X      kbmap -e    = select emacs <esc>N<letter> map
X      kbmap -m    = select emacs <letter>|0x080 meta map
X.fi
X
XAlternatively, the key mapping may be selected by number:
X.nf
X
X      kbmap -m 0  = select map 0 (default map)
X      kbmap -m 1  = select map 1 (emacs <letter>|0x08 meta-map)
X      kbmap -m 2  = select map 2 (normal <esc>N<letter> emacs)
X      kbmap -m 3  = select map 3 (your additional)
X         etc.
X.fi
X
X.SH NOTES
X
XThe changes made by kbmap are reset to system defaults whenever
Xthe system is booted.  If permanent changes are needed, then
Xthe system default mapping in /etc/conf/pack.d/kd/Driver.o
Xshould be "zapped" with the appropriate table and the kernal
Xrebuilt.
X
X.SH FILES
X
X/local/lib/kbmap.table
X
X.SH AUTHOR
X
XTony Field (tony%ajfcal@cpsc.ucalgary.ca, tony@ajfcal)
END_OF_FILE
if test 5749 -ne `wc -c <'kbmap.1'`; then
    echo shar: \"'kbmap.1'\" unpacked with wrong size!
fi
# end of 'kbmap.1'
fi
if test -f 'kbmap.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'kbmap.c'\"
else
echo shar: Extracting \"'kbmap.c'\" \(18744 characters\)
sed "s/^X//" >'kbmap.c' <<'END_OF_FILE'
X/* ta=4     tabs set at 4*/
X/*
X		kbmap.c
X		
X	Kbmap reads a text file containg keyboard mapping information and
X	set the keyboard to the selected mapping.  It can also create
X	a map file with the -g option.
X
X	Only root may use this programme from the console.
X	It cannot be run from an rc2.d/xxx file or cron.
X
X	Then true-meta keys cannot be used with X11R2 - which uses its own map.
X	VTLMGR tends to modify a couple of keys.  The -q option (query_map())
X	tries to detect a vtlmgr modification.
X
X	This works for AT&T Unix 3.2.2 - other systems not tested.
X
XAUTHOR:    Tony Field    (tony%ajfcal@cpsc.ucalgary.ca)
X
XNOTES:
X
X  Structure of keyboard translation table (from /usr/include/sys/kd.h)
X
X	#define NUM_KEYS	256					Maximum number of keys
X	#define NUM_STATES	8					Number of key states
X	#pragma pack(2)
X	typedef struct {
X		short  n_keys ;						Number of entries in table
X		struct key_t {
X			unsigned char map[NUM_STATES];	Key code for each state
X			unsigned char spcl;				Bits marking states as special
X			unsigned char flgs;				Flags
X		} key[NUM_KEYS+1];					One entry for each key
X	} keymap_t;
X
X	(note: NUM_KEYS is specified as 256, however n_keys only
X		   describes 128 keys...  kbmap only updates the first
X		   128 keys.  The remainder are unmodified.)
X
X	Each key has 8 (NUM_STATES) possible scan states honoured if
X	set in the "spcl" field:
X
X		spcl	map[i]
X		bit 7 	i=0		= normal
X			6 	  1		= shifted
X			5 	  2		= control
X			4	  3		= shift-control
X			3 	  4		= alt
X			2 	  5		= alt-shift
X			1 	  6		= alt-control
X			0 	  7		= alt-shift-control
X	
X	If the corresponding bit is set, then the feature is enabled. For
X	example, if bit 3 is set, then the keyboard driver will translate
X	the scan code into the "<esc>Nx" escape sequence. If the 3ed bit is
X	NOT set, then the driver will use the character as specified in
X	map[4] as the returned value.
X
X	The "flgs" field needs no modification: it allows the "numlok",
X	"caploc" and "control" keys to be used with specific keys:
X	
X			0x8000		allow numlock
X			0x4000		allow caps lock
X			0x2000		allow control
X			0x1000		locking is off
X	
X	At leaset that is what <sys/kd.h> indicates.  But that is not
X	what is indicated in the actual dump of the tables...  Alphabetic
X	characters contain 0x01, the numeric keypad contains 0x02, and
X	verything else contains 0x00.  Oh well...  A more reasonable
X	interpretation is that these meanings are assigned to the
X	high order 4 bits of "spcl", but that is only a guess.
X
X	In addition, the default value for the map[4] entry for most codes
X	that can be translated into the <esc>Nx sequence is 0x7d.
X	The 7x numbers are used for function key translation.  They mean
X	(of course i am guessing):
X	
X			7d	= use <esc>Nx		where 'x' is the un-alted value
X			7e	= use <esc>Ox		of the scan code (funny that 7e
X			7f	= use <esc>Lx		and 7f do not appear in the table
X									nor are visible in keyboard(7))
X	
X	Conversion of the table to emacs "meta" bits is done as follows:
X
X		1.	read the entire keyboard mapping structure with ioctl().	
X		2.	if the base key (map[0]) is between ' ' & 0x7f and not uppercase
X				then remove bit 3 from the spcl field and
X				set map[4] = map[0] | 0x80.  The creates the
X				meta-mapping of the keys for lower case letters.
X		3.	if the shifted key (map[1]) is between ' ' & 0x7f and the
X				map[0] value is not an upper case character,
X				then remove bit 2 from the spcl field and
X				set map[5] = map[1] | 0x80.  The creates the
X				meta-mapping of the keys for upper case letters.
X		4.	write the new keyboard mapping with ioctl().
X
X	Similar conversion is make for the "normal" emacs <esc>N prefix
X	sequence.  This requires forcing the 0x7d code into all <alt>x slots.
X	
X	The map structure contains map[0] entries for both lower and upper
X	case letters.  The lower case entries "seem" to be the only ones
X	used.  No explanation is offered for the upper case entries.
X*/
X
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/at_ansi.h>
X#include <sys/kd.h>
X#include <sys/ioctl.h>
X#include <fcntl.h>
X
X/*	where does kbmap expect to find the default map table	*/
X
X#ifndef DEFAULTMAP
X#define DEFAULTMAP	"/local/lib/kbmap.table"
X#endif
X
Xchar	progname[150];
Xint		vtlmgr;
X
Xmain (argc, argv)
Xint		argc;
Xchar	*argv[];
X{
X	extern char *optarg;
X	extern int	optind;
X	int		c;
X	int		select_map = -1;
X	char	use_file[200];
X	int		generate_file = 0;
X	FILE	*use_fp, *open_file();
X	char	tfile[100];
X	int		tn = -1;
X	int		index_only = 0;
X	char	line[200];
X	int		query_only = 0;
X	int		option_count = 0;
X	int		also_alt_ctl = 1;
X		
X	strcpy (progname, argv[0]);
X	use_fp = NULL;
X	use_file[0] = '\0';
X	if (argc == 1  ||  strcmp (argv[1], "-") == 0  || strcmp (argv[1], "--") == 0)
X		usage();
X
X	while ((c = getopt(argc, argv, "aqgin:dmet:-?")) != -1)
X	{	option_count++;
X		switch (c)
X		{
X		case 'a':	also_alt_ctl = 0;					/*	disable  alt+ctl expansion */
X					break;
X		case 'i':	index_only = 1;
X					break;
X		case 'n':	select_map = atoi (optarg);			/*	select by number	*/
X					break;
X		case 'd':	select_map = 0;						/*	select default = 0	*/
X					if (use_file[0] == '\0')
X						strcpy (use_file, DEFAULTMAP);
X					break;
X		case 'e':	select_map = 2;						/*	select emacs = 2	*/
X					if (use_file[0] == '\0')
X						strcpy (use_file, DEFAULTMAP);
X					break;
X		case 'm':	select_map = 1;						/*	select emacs = 1 (meta) */
X					if (use_file[0] == '\0')
X						strcpy (use_file, DEFAULTMAP);
X					break;
X		case 't':	strcpy (tfile, optarg);				/*	use terminal at /dev/xxxx */
X					if ((tn = open (tfile, O_RDWR)) < 0)
X					{	fprintf (stderr, "%s: Cannot open %s\n", progname, tfile);
X						exit (1);
X					}
X					break;
X		case 'q':	query_only = 1;
X					break;
X		case 'g':	generate_file = 1;					/*	generate map file	*/
X					if (use_file[0] == '\0')
X						strcpy (use_file, DEFAULTMAP);
X					break;
X
X		default:	usage ();
X		}
X	}
X	if (optind < argc)
X	{	strcpy (use_file, argv[optind]);			/*	specify map file	*/
X		if (option_count == 0)
X			index_only = 1;
X	}
X
X	if (tn < 1)
X		tn = 0;
X
X	if (index_only)									/*	show index of maps	*/
X	{	use_fp = open_file (use_file, "r");
X		c = 0;
X		while (fgets (line, 190, use_fp) != NULL)
X			if (strncmp (line, "...", 3) == 0)
X				printf ("map %d = %s", c++, line + 3);
X		fclose (use_fp);
X		exit (0);
X	}		
X	
X	if (query_only)									/*	which map is in use	*/
X	{	use_fp = open_file (use_file, "r");
X		if (query_map (use_fp) == 0)
X			printf ("current map is not in %s\n", use_file);
X		exit (0);
X	}
X
X	if (generate_file)								/*	create new kbmap.table file */
X	{	if (use_file[0])
X		{	use_fp = open_file (use_file, "w");
X			create_table (use_fp, tn, also_alt_ctl);
X			fclose (use_fp);
X		}
X		else
X			create_table (stdout, tn, also_alt_ctl);
X	}		
X
X	if (select_map >= 0)
X	{	use_fp = open_file (use_file, "r");
X		update_map (use_fp, select_map);
X		fclose (use_fp);
X	}		
X
X	exit (0);
X}
X
X/****************************************************************************
X*	create_table (fp)														*
X*	Get the existing keyboard mapping structure and write to file.			*
X*	Translate all alt and alt-shift keys to the meta-mapping.				*
X*	Write the meta-mapping structure to disk file.							*
X****************************************************************************/
X
Xcreate_table (fp, tn, also_alt_ctl)
XFILE *fp;			/*	file containing the keyboard maps				*/
Xint	 tn;
Xint	 also_alt_ctl;	/*	convert ALT/CTL and ALT/SHIFT/CTL as well?		*/
X{
X	int	i, j, cb, cs;
X	keymap_t kt;
X	char	title[200];
X
X	/*	get existing mapping	*/
X		
X	if (ioctl (tn, GIO_KEYMAP, &kt))
X		ioctl_failure ('r');
X
X	/* 	write the existing mapping to the disk file
X
X		some potentiall useful keyboard scan numbers:
X	
X			1	esc
X			14	bs
X			15	tab
X			28	cr
X			83	del
X			116	cr
X			119	break
X			121	del
X
X		For example, if scan code 1 (esc) is specifically selected,
X		then the <ALT><ESC> combination becomes available.  This is
X		not done because double-striking <esc> is quite easy.
X
X		It might be useful to force full alt-decoding for cr and tab.
X		Emacs would recognize such sequences by default (see comments
X		in the code to make this modification)
X		
X		The variable sequence is:
X	  char scan scpl flgs NORMAL SHIFT CTRL SHFCTL ALT ALTSHF ALTCTL ALTSHFCTL
X	*/
X
X	header (fp, "system default keyboard mapping", -1);
X	for (i = 0;  i < kt.n_keys;  i++)
X	{
X		cb = kt.key[i].map[0];
X		cs = kt.key[i].map[1];
X		fprintf (fp, "%c%c %3d   %02x   %02x", 
X				cb > ' ' &&  cb < 127 ? cb : ' ',
X				cs > ' ' &&  cs < 127 &&  cs != cb ? cs : ' ',
X				i, 
X				kt.key[i].spcl & 0x0ff, 
X				kt.key[i].flgs & 0x0ff);
X		for (j = 0;  j < NUM_STATES;  j++)
X			fprintf (fp, "   %02x", kt.key[i].map[j]);
X		fprintf (fp, "\n");
X	}
X	
X	/*	convert the existing mapping to emacs-meta (8th bit set) conventions
X		and write to file
X	*/	
X	
X	fprintf (fp, "\n\n");
X	strcpy (title, "emacs 8th bit set (<letter>|0x080) meta mapping");
X	header (fp, title, also_alt_ctl);
X	for (i = 0;  i < kt.n_keys;  i++)
X	{
X		cb = kt.key[i].map[NORMAL];			/*	base char		*/
X		cs = kt.key[i].map[SHIFT];			/*	shifted char	*/
X
X		if (1)								/*	things to ignore e,g,  (i == 121) */
X		{
X			/*	convert ALT key to meta. */
X
X			/*	add the following the various "if" statements below
X				to enable full conversion of \t and \n:
X			
X					||  (i == 15)  ||  (i == 28)
X			*/
X			if ((cb >= ' '  &&  cb < 'A')  || (cb > 'Z'  &&  cb <= 127))
X			{	kt.key[i].map[ALT] = (kt.key[i].map[NORMAL] | 0x080);
X				kt.key[i].spcl &= 0x0f7;
X			}
X
X			/*	convert ALT-CTRL key to meta. (dont include <alt><ctl><del> */
X	
X			if (also_alt_ctl  
X					&&  ((cb >= ' '  &&  cb < 'A')  || (cb > 'Z'  &&  cb < 127)))
X			{	kt.key[i].map[ALTCTL] = (kt.key[i].map[CTRL] | 0x080);
X				kt.key[i].spcl &= 0x0fd;
X			}
X
X			/* convert ALT-SHIFT to meta */
X
X			if (((cb >= ' '  &&  cb < 'A')  || (cb > 'Z'  &&  cb <= 127))
X					&&  (cs >= ' '  &&  cs <= 127))
X			{	kt.key[i].map[ALTSHF] = (kt.key[i].map[SHIFT] | 0x080);
X				kt.key[i].spcl &= 0x0fb;
X			}
X		
X			/* convert ALT-SHIFT-CTL to meta */
X
X			if (also_alt_ctl
X					&&   ((cb >= ' '  &&  cb < 'A')  || (cb > 'Z'  &&  cb <= 127))
X					&&  (cs >= ' '  &&  cs <= 127))
X			{	kt.key[i].map[ALTSHFCTL] = (kt.key[i].map[SHFCTL] | 0x080);
X				kt.key[i].spcl &= 0x0fe;
X			}
X		}
X		fprintf (fp, "%c%c %3d   %02x   %02x", 
X				cb > ' ' &&  cb < 127 ? cb : ' ',
X				cs > ' ' &&  cs < 127 &&  cs != cb ? cs : ' ',
X				i, 
X				kt.key[i].spcl & 0x0ff, 
X				kt.key[i].flgs & 0x0ff);
X		for (j = 0;  j < NUM_STATES;  j++)
X			fprintf (fp, "   %02x", kt.key[i].map[j]);
X		fprintf (fp, "\n");
X	}
X
X	/*	re-get existing mapping	to remove the above meta-conversion
X	
X		Set the k.key[i].map[xx] values to 0x7d.  This seems to be
X		the code that forces the <esc>N sequence durning translation
X	*/
X		
X	if (ioctl (tn, GIO_KEYMAP, &kt))
X		ioctl_failure('r');
X
X	fprintf (fp, "\n\n");
X	strcpy (title, "emacs normal (<esc>N<letter>) meta mapping");
X	header (fp, title, also_alt_ctl);
X	for (i = 0;  i < kt.n_keys;  i++)
X	{
X		cb = kt.key[i].map[NORMAL];			/*	base char		*/
X		cs = kt.key[i].map[SHIFT];			/*	shifted char	*/
X
X		if (1)								/*	things to ignore */
X		{		/*	make ALT converssion available */
X
X			if ((cb >= ' '  &&  cb < 'A')  ||  (cb > 'Z'  &&  cb <= 127))
X			{	kt.key[i].map[ALT] = 0x7d;
X				kt.key[i].spcl |= 0x08;
X			}
X
X			/*	make ALT-CTL conversion available  (dont include <alt><ctl><del> */
X
X			if (also_alt_ctl
X					&&  ((cb >= ' '  &&  cb < 'A')  || (cb > 'Z'  &&  cb < 127)))
X			{	kt.key[i].map[ALTCTL] = 0x7d;
X				kt.key[i].spcl |= 0x02;
X			}
X
X			/* make  ALT-SHIFT available */
X
X			if (((cb >= ' '  &&  cb < 'A')  || (cb > 'Z'  &&  cb <= 127))
X					&&  (cs >= ' '  &&  cs <= 127))
X			{	kt.key[i].map[ALTSHF] = 0x7d;
X				kt.key[i].spcl |= 0x04;
X			}
X		
X			/* make  ALT-SHIFT-CTL available */
X
X			if (also_alt_ctl
X					&&	((cb >= ' '  &&  cb < 'A')  || (cb > 'Z'  &&  cb <= 127))
X					&&  (cs >= ' '  &&  cs <= 127))
X			{	kt.key[i].map[ALTSHFCTL] = 0x7d;
X				kt.key[i].spcl |= 0x01;
X			}
X		}
X		fprintf (fp, "%c%c %3d   %02x   %02x", 
X				cb > ' ' &&  cb < 127 ? cb : ' ',
X				cs > ' ' &&  cs < 127 &&  cs != cb ? cs : ' ',
X				i, 
X				kt.key[i].spcl & 0x0ff, 
X				kt.key[i].flgs & 0x0ff);
X		for (j = 0;  j < NUM_STATES;  j++)
X			fprintf (fp, "   %02x", kt.key[i].map[j]);
X		fprintf (fp, "\n");
X	}
X
X}
X
X/****************************************************************************
X*	header ()																*
X*	Standard table header generation										*
X****************************************************************************/
X
Xheader (fp, title, also_alt_ctl)
XFILE *fp;
Xchar	*title;
X{	fprintf (fp, "...%s", title);
X	if (also_alt_ctl == -1)
X		fprintf (fp, "\n");
X	else if (also_alt_ctl)
X		fprintf (fp, " -- full alt/ctl\n");
X	else
X		fprintf (fp, " -- no alt/ctl\n");
X	fprintf (fp, "                                                     alt\n");
X	fprintf (fp, "                                 shif      alt  alt  shif\n");
X	fprintf (fp, "  key   spcl flgs norm shif ctrl ctrl alt  shif ctrl ctrl\n");
X	fprintf (fp, "------  ---- ---- ---- ---- ---- ---- ---- ---- ---- ----\n");
X}
X
X
X/****************************************************************************
X*	update_map (fp, which_map)												*
X*	Read the specified mapping table from the map file.  Send the new map	*
X*	to key keyboard driver.													*
X****************************************************************************/
X
Xupdate_map (fp, which_map)
XFILE *fp;				/*	file containing keyboard maps					*/
Xint	 which_map;			/*	select this table from the file  (0..n)			*/
X{
X	int	i, j, how;
X	keymap_t kt;
X
X	/*	find the desired map in the file and read it into the keytable */
X	
X	if (ioctl (1, GIO_KEYMAP, &kt))						/*	read current map		*/
X		ioctl_failure ('r');
X
X	for (i = 0;  i <= which_map;  i++)
X		how = read_map (i == which_map, fp, &kt, NULL);
X	if (how)
X	{	fprintf (stderr, "%s: map %d not found\n", progname, which_map);
X		exit (1);
X	}
X	if (ioctl (1, PIO_KEYMAP, &kt))						/*	send found map to driver */
X		ioctl_failure ('w');
X}
X
X/****************************************************************************
X*	query_map (fp)															*
X*	Identifiy which table file map matches the keyboard map in use.			*
X****************************************************************************/
X
Xquery_map (fp)
XFILE *fp;				/*	file containing keyboard maps					*/
X{
X	int	i, j, k;
X	char	text[200];
X	keymap_t kt, inuse;
X	int		found;
X	int		vtlmgr;
X
X	if (ioctl (1, GIO_KEYMAP, &inuse))					/*	read current map		*/
X		ioctl_failure ('r');
X
X	vtlmgr = 0;
X	found = 0;
X	kt = inuse;
X	for (k = 0;  ;  k++)
X	{	if (read_map (1, fp, &kt, text))
X			return (found);
X		for (i = 0;  i < inuse.n_keys;  i++)
X		{	for (j = 0;  j < NUM_STATES;  j++)		/*	compare all keys	*/
X			{	if (inuse.key[i].map[j] != kt.key[i].map[j])
X				{	/* detect minor mod made by vtlmgr  in line 3 for  "1!" */
X					if (i == 2  &&  (j == ALTSHF  ||  j == ALTSHFCTL))
X						vtlmgr = 1;
X					else
X						goto next_map;
X				}
X			}
X		}
X		printf ("using map %d: %s\n", k, text);
X		if (vtlmgr)
X			printf ("             (modified by vtlmgr)\n");
X		found = 1;
X		break;
Xnext_map:	;
X	}
X	return (found);
X}
X
X/****************************************************************************
X*	read_map (fp, kt, title)												*
X*	Read the nextd mapping table from the map file.							*
X****************************************************************************/
X
Xread_map (getit, fp, kt, title)
Xint			getit;		/*	1 = update kt, 0 = get title only			*/
XFILE 		*fp;		/*	file containing keyboard maps				*/
Xkeymap_t	*kt;		/*	read structure into this					*/
Xchar		*title;		/*	read title line into this buffer			*/
X{
X	int	i, j, cc;
X	char	key_line[200], *c;
X	int		a0,a1,a2,a3,a4,a5,a6,a7,a8,a9;
X	int		good_read;
X	
X	/*	find the next map in the file and read it into the keytable */
X	
X	while (good_read = (fgets (key_line, 199, fp) != NULL))
X	{	if (title != NULL  &&  strncmp (key_line, "...", 3) == 0)
X		{	strcpy (title, key_line + 3);
X			c = title;
X			while (*c)
X			{	if (*c < ' ')
X				{	*c = '\0';
X					break;
X				}
X				c++;
X			}
X		}
X		else if (strncmp (key_line, "------  -", 8) == 0)
X			break;
X	}
X	if (good_read == 0)
X		return (-1);
X	if (strncmp (key_line, "------  -", 8) != 0)
X		bad_file ();
X
X	if (getit == 0)
X		return (1);
X	for (i = 0;  i < kt->n_keys;  i++)
X	{	if (fgets (key_line, 199, fp) == NULL)
X			bad_file ();
X		if (atoi (key_line + 2) != i)
X			bad_file ();
X		sscanf (key_line + 7, "%x %x %x %x %x %x %x %x %x %x",
X				&a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8, &a9);
X		kt->key[i].spcl		= a0;
X		kt->key[i].flgs		= a1;
X		kt->key[i].map[0]	= a2;
X		kt->key[i].map[1]	= a3;
X		kt->key[i].map[2]	= a4;
X		kt->key[i].map[3]	= a5;
X		kt->key[i].map[4]	= a6;
X		kt->key[i].map[5]	= a7;
X		kt->key[i].map[6]	= a8;
X		kt->key[i].map[7]	= a9;
X		 
X	}
X	return (0);
X}
X
X/****************************************************************************
X*	open_file (use_file, how)												*
X*	Open a table file.  If there is a problem, quit now.					*
X****************************************************************************/
X
XFILE *open_file (use_file, how)
Xchar	*use_file;
Xchar	*how;
X{	FILE	*use_fp;
X	char	*strchr();
X
X	if (*use_file == '\0')
X		strcpy (use_file, DEFAULTMAP);
X
X	if ((use_fp = fopen (use_file, how)) == NULL)
X	{	fprintf (stderr, "%s: cannot open file %s\n", progname, use_file);
X		exit (1);
X	}
X	return (use_fp);
X}
X
X/****************************************************************************
X*	bad_file ()																*
X****************************************************************************/
X
Xbad_file ()
X{
X	fprintf (stderr, "%s: invalid key map file format\n", progname);
X	exit (2);
X}
X
Xioctl_failure (how)
Xint		how;
X{
X	fprintf (stderr, "%s: ioctl failure, %s\n", 
X		progname, how == 'r' ? "cannot read, possibly using X11???" : "must be root?");
X	exit (2);
X}
X
X/****************************************************************************
X*	usage ()																*
X****************************************************************************/
X
Xusage ()
X{
X	printf ("Usage:     kbmap [-i] [-q] [-g] [-n n] [-d] [-e] [-m] [-1] [-t /dev/xxx] [file]\n");
X	printf ("    where:        -i      = show index of available maps\n");
X	printf ("                  -q      = identify map currenly in use\n");
X	printf ("                  -g      = generate a key map table\n");
X	printf ("                  -n n    = set keyboard to map 'n' mapping\n");
X	printf ("                  -d      = set keyboard to default mapping\n");
X	printf ("                  -e      = set keyboard to emacs mapping (<esc>N)\n");
X	printf ("                  -m      = set keyboard to emacs meta-mapping (8bit)\n");
X	printf ("                  -a      = disable <alt><ctl> & <alt><shf><ctl>\n");
X	printf ("                  -t /dev/xxx = apply map to this device (default stdin)\n");
X	printf ("                  file    = use specified key map file\n");
X	printf ("                            default = %s\n", DEFAULTMAP);
X	exit (0);
X}
END_OF_FILE
if test 18744 -ne `wc -c <'kbmap.c'`; then
    echo shar: \"'kbmap.c'\" unpacked with wrong size!
fi
# end of 'kbmap.c'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(509 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#		k b m a p 
X#
X#	change the keyboard scan code mapping for AT&T unix SysV 3.2.2
X#
X# Select your compiler and options
X
XCC=gcc
XCFLAGS=-traditional
X
X# CC=cc
X# CFLAGS=
X
X# Set BINDIR as desired.  Provide a name for the default keyboard map table.
X
XBINDIR = /local/bin
XMAPTABLE = /local/lib/kbmap.table
X
Xall:
X	$(CC) $(CFLAGS) -DDEFAULTMAP="\"$(MAPTABLE)"\" kbmap.c -o kbmap
X
Xinstall:
X	strip kbmap
X	cp kbmap $(BINDIR)
X
Xshar:
X	shar Readme kbmap.doc kbmap.1 kbmap.c Makefile > kbmap.shar
X
Xclean:
X	rm -f *.o *.B *.BAK
END_OF_FILE
if test 509 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
echo shar: End of shell archive.
exit 0