#!/bin/sh
# mk_modmap
# Tries to translate a keytable file into a file parseable by xmodmap
#
# This is a hack, and has a lot of magic numbers and names hardcoded
# into it. Suggestions on how to avoid this are welcome.
#
# Kjetil T. Homme, University of Oslo 1993
# <kjetilho@ifi.uio.no>


case $1 in
	-v*)	verbose=1; shift ;;
esac

if test ! -f /usr/include/X11/X.h; then
	echo Make sure you have a link to you X include files called
	echo /usr/include/X11 first.
	exit 1
fi

cat <<__EOH__
! Converted keytable file to xmodmap file
! with `basename $0` by `whoami`@`hostname` `date`
clear Mod1
clear Mod2
__EOH__

awk -F'#' '
	/[a-z]+.*keycode/ { next }
	/^[ \t]*$/ { next }
	/^string/ { next }
	{ sub("^[ \t]*", "") }
	NF > 1 {
		printf("!");
		for (i = 2; i <= NF; i++) {
			printf(" " $i);
			$i = "";
		}
		print "";
		if ($1 == "")
			next;
	}
	{ print }
' "$@" | awk -v verbose=$verbose '
	BEGIN {
		while (getline < "/usr/include/X11/keysymdef.h" == 1) {
			if ($0 ~ /XK_/) {
				sub(/.*XK_/, "");
				sub(/[\t ].*/, "");
				valid[$0] = 1;
			}
		}
		valid["X386Sys_Req"] = 1;

		shifts["Control"] = shifts["Shift"] = 1;

		shift_keys[29]  = "Control_L";
		shift_keys[97]  = "Control_R";
		shift_keys[42]  = "Shift_L";
		shift_keys[54]  = "Shift_R";

		trans_keys[ 96] = 108; # KP_Enter
		trans_keys[ 97] = 109; # Control_R
		trans_keys[ 98] = 112; # KP_Divide
		trans_keys[100] = 113; # Mode_switch (AltGr)
		trans_keys[101] = 114; # Break
		trans_keys[103] =  98; # Up
		trans_keys[104] =  99; # Prior
		trans_keys[105] = 100; # Left
		trans_keys[106] = 102; # Right
		trans_keys[108] = 104; # Down
		trans_keys[109] = 105; # Next
		trans_keys[110] = 106; # Insert
		trans_keys[111] = 107; # Delete

		trans_names["Alt"]	= "Alt_L Meta_L";
		trans_names["AltGr"]	= "Mode_switch";
		trans_names["one"]	= "1";
		trans_names["two"]	= "2";
		trans_names["three"]	= "3";
		trans_names["four"]	= "4";
		trans_names["five"]	= "5";
		trans_names["six"]	= "6";
		trans_names["seven"]	= "7";
		trans_names["eight"]	= "8";
		trans_names["nine"]	= "9";
		trans_names["zero"]	= "0";
		trans_names["KP_Comma"]	= "KP_Decimal";
		trans_names["dead_tilde"]	= "asciitilde";
		trans_names["dead_circumflex"]	= "asciicircum";
		trans_names["dead_acute"]	= "acute";
		trans_names["dead_grave"]	= "grave";
		trans_names["dead_diaeresis"]	= "diaeresis";
		trans_names["Last_Console"]	= "X386Sys_Req";
	}
	$1 == "keycode" {
		output = "";
		keycode = $2;
		i = ($3 == "=") ? 4 : 3;
		for ( ; i <= NF; i++) {
			sub(/^\+/, "", $i);
			n = $i;
			if ($i in shifts)
				n = shift_keys[keycode];
			else if ($i in trans_names)
				n = trans_names[$i];

			if (n in valid || n in valid || $i in trans_names)
				output = output " " n;
			else
				msg("Skipped " $i);
		}

		if (keycode in trans_keys)
			keycode = trans_keys[keycode];
		else
			keycode += 8;

		if (keycode >= 115)
			msg("Skipped keycode " keycode-8 ": " output);
	 	else if (output)
			printf("keycode %3d =%s\n", keycode, output);
		next;
	}
	{ print }
	function msg(m) { if (verbose) print m > "/dev/stderr"; }'

cat <<__EOH__
add Mod1 = Alt_L
add Mod2 = Mode_switch
__EOH__
