KEYSYM_PATHS=(/usr/include/X11/ /zeta/apps/X11R6.4/include/X11/ ./)
KEYSYMDEF=keysymdef.h
L2B=(
0x00 0x00 0x12 0x13 0x14 0x15 0x16 0x17
0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x00 0x00
0x27 0x28 0x29 0x2a 0x2b 0x2c 0x2d 0x2e
0x2f 0x30 0x31 0x32 0x00 0x00 0x3c 0x3d
0x3e 0x3f 0x40 0x41 0x42 0x43 0x44 0x45
0x46 0x11 0x00 0x33 0x4c 0x4d 0x4e 0x4f
0x50 0x51 0x52 0x53 0x54 0x55 0x00 0x00
0x00 0x5e 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x69 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
)
stop () {
echo "$@"
exit 1
}
warn () {
echo "warning: " "$@" >&2
}
remap_key_l2b () {
echo "$((${L2B[$1]}))"
}
unicode_to_utf8 () {
uni="${1}"
if [ "${uni:0:2}" = "U+" ]; then
uni="${uni:2}"
fi
if [ "${uni:0:2}" = "0x" ]; then
uni="${uni:2}"
fi
if [ "${#uni}" = "3" ]; then
uni="0${uni}"
fi
case "$uni" in
[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F])
utf8="$(echo -en "\x${uni:0:2}\x${uni:2}" | iconv -f UCS-2BE -t UTF-8 | od -A n -t x1 | sed 's/ //g')"
if [ -z "$uni" ]; then
warn "empty utf-8 for '$uni'"
fi
;;
*)
warn "unhandled unicode '$uni'"
utf8="00"
;;
esac
echo "0x$utf8"
}
broken_unicode_to_utf8 () {
uni="${1}"
if [ "${lk:0:2}" = "U+" ]; then
uni="${lk:2}"
fi
case "$uni" in
[0-7][0-9a-f])
utf8="$uni"
;;
00[0-7][0-9a-f])
utf8="${uni:2:2}"
;;
20[8-9a-f][0-9a-f])
utf8="e282${uni:2:2}"
;;
*)
warn "unhandled unicode '$uni'"
utf8="00"
;;
esac
echo "0x$utf8"
}
convert_keyval () {
lk="$1"
if [ "${lk:0:1}" = "+" ]; then
warn "unhandled +"
lk="${lk:1}"
fi
warn "lk: $lk"
case "$lk" in
[0-9a-zA-Z])
echo "'$lk'"
;;
U+*)
echo "$(unicode_to_utf8 $lk)"
;;
space)
echo "' '"
;;
underscore)
echo "'_'"
;;
'')
echo "''"
;;
*)
keysymhex="$(grep "XK_$lk[ ]" "$keysymdef" | awk '{print $3}')"
warn "found: '$keysymhex'"
if [ -n "$keysymhex" ]; then
echo "$(unicode_to_utf8 $keysymhex)"
return
fi
case "$lk" in
one)
echo "'1'";;
two)
echo "'2'";;
three)
echo "'3'";;
four)
echo "'4'";;
five)
echo "'5'";;
six)
echo "'6'";;
seven)
echo "'7'";;
eight)
echo "'8'";;
nine)
echo "'9'";;
zero)
echo "'0'";;
*)
warn "unknown: '$lk'"
;;
esac
echo "''"
;;
esac
}
parse_lkeymap () {
while read line; do
if [ "${line:0:1}" = "#" ]; then
continue
fi
keyspec="${line%=*}"
keyvals="${line#*=}"
if [ "${keyspec}" = "${keyvals}" ]; then
continue
fi
mods=0
for k in $keyspec; do
case "$k" in
Shift|shift)
mods=$((mods | 0x1))
;;
Control|control)
mods=$((mods | 0x4))
;;
Alt|alt)
mods=$((mods | 0x2))
;;
AltGr|altgr)
mods=$((mods | 0x40))
;;
plain)
mods=0
continue;;
keycode)
continue;;
*)
case "${k:0:1}" in
[0-9]*)
keycode="${k/[^0-9]}"
;;
*)
stop "unknown: $k"
;;
esac
;;
esac
done
if [ $((mods & 0x2)) -gt 0 ]; then
continue
fi
hkeycode="$(remap_key_l2b "$keycode")"
kv=($keyvals)
hkv=('' '' '' '')
if [ -z "${kv[1]}" ]; then
case "${kv[0]}" in
[a-z])
kv[1]="$(echo "${kv[0]}" | tr '[a-z]' '[A-Z]')"
;;
*)
;;
esac
fi
for n in $(seq 0 3); do
hkv[$n]="$(convert_keyval "${kv[$n]}")"
if [ "${hkv[$n]}" = "" ]; then
hkv[$n]="''"
fi
done
case "$mods" in
0)
eval "hkmap_${hkeycode}[0]=\"${hkv[0]}\""
eval "hkmap_${hkeycode}[1]=\"${hkv[1]}\""
eval "hkmap_${hkeycode}[3]=\"${hkv[2]}\""
eval "hkmap_${hkeycode}[4]=\"${hkv[3]}\""
eval "hkmap_${hkeycode}[5]=\"${hkv[1]}\""
eval "hkmap_${hkeycode}[6]=\"${hkv[0]}\""
eval "hkmap_${hkeycode}[7]=\"${hkv[2]}\""
eval "hkmap_${hkeycode}[8]=\"${hkv[3]}\""
;;
64)
eval "hkmap_${hkeycode}[3]=\"${hkv[0]}\""
;;
65)
eval "hkmap_${hkeycode}[4]=\"${hkv[0]}\""
;;
*)
warn "unhandled modifiers $mods"
;;
esac
done
gen_hkeymap
}
prefill_hkeymap () {
for n in $(seq 0 127); do
val="''"
val2=""
case $n in
1)
val="0x1b";;
[2-9]|1[0-6])
val="0x10";;
$((0x1e)))
val="0x08";;
$((0x1f)))
val="0x05";;
$((0x20)))
val="0x01";;
$((0x21)))
val="0x0b";;
$((0x23)))
val="'/'";;
$((0x24)))
val="'*'";;
$((0x25)))
val="'-'";;
$((0x26)))
val="0x09";;
$((0x34)))
val="0x7f";;
$((0x35)))
val="0x04";;
$((0x36)))
val="0x0c";;
$((0x37)))
val="0x01";val2="'7'";;
$((0x38)))
val="0x1e";val2="'8'";;
$((0x39)))
val="0x0b";val2="'9'";;
$((0x3a)))
val="'+'";;
$((0x47)))
val="0x0a";;
$((0x48)))
val="0x1c";val2="'4'";;
$((0x49)))
val="''";val2="'5'";;
$((0x4a)))
val="0x1d";val2="'6'";;
$((0x57)))
val="0x1e";;
$((0x58)))
val="0x01";val2="'1'";;
$((0x59)))
val="0x1e";val2="'2'";;
$((0x5a)))
val="0x0b";val2="'3'";;
$((0x5b)))
val="0x0a";;
$((0x61)))
val="0x1c";;
$((0x62)))
val="0x1f";;
$((0x63)))
val="0x1d";;
$((0x64)))
val="0x05";val2="'0'";;
$((0x65)))
val="0x7f";val2="'.'";;
*)
;;
esac
if [ -z "$val2" ]; then
val2="$val"
fi
eval "hkmap_$n=(\"$val\" \"$val2\" \"$val\" \"$val\" \"$val2\" \"$val\" \"$val2\" \"$val\" \"$val2\")"
done
}
gen_hkeymap () {
echo "#!/bin/keymap -l
Version = 3
CapsLock = 0x3b
ScrollLock = 0x0f
NumLock = 0x22
LShift = 0x4b
RShift = 0x56
LCommand = 0x5d
RCommand = 0x00
LControl = 0x5c
RControl = 0x60
LOption = 0x66
ROption = 0x5f
Menu = 0x68
#
# Lock settings
# To set NumLock, do the following:
# LockSettings = NumLock
#
# To set everything, do the following:
# LockSettings = CapsLock NumLock ScrollLock
#
LockSettings =
# Legend:
# n = Normal
# s = Shift
# c = Control
# C = CapsLock
# o = Option
# Key n s c o os C Cs Co Cos
"
for n in $(seq 0 127); do
printf "Key 0x%02x = " $n
eval v="(\${hkmap_$n[*]})"
for n in $(seq 0 8); do
printf "%-10s" "${v[$n]}"
done
echo ""
done
echo "
Acute ' ' = 0xc2b4
Acute 'A' = 0xc381
Acute 'E' = 0xc389
Acute 'I' = 0xc38d
Acute 'O' = 0xc393
Acute 'U' = 0xc39a
Acute 'Y' = 0xc39d
Acute 'a' = 0xc3a1
Acute 'e' = 0xc3a9
Acute 'i' = 0xc3ad
Acute 'o' = 0xc3b3
Acute 'u' = 0xc3ba
Acute 'y' = 0xc3bd
AcuteTab = Option Option-Shift CapsLock-Option CapsLock-Option-Shift
Grave ' ' = '\`'
Grave 'A' = 0xc380
Grave 'E' = 0xc388
Grave 'I' = 0xc38c
Grave 'O' = 0xc392
Grave 'U' = 0xc399
Grave 'a' = 0xc3a0
Grave 'e' = 0xc3a8
Grave 'i' = 0xc3ac
Grave 'o' = 0xc3b2
Grave 'u' = 0xc3b9
GraveTab = Option Option-Shift CapsLock-Option CapsLock-Option-Shift
Circumflex ' ' = '^'
Circumflex 'A' = 0xc382
Circumflex 'E' = 0xc38a
Circumflex 'I' = 0xc38e
Circumflex 'O' = 0xc394
Circumflex 'U' = 0xc39b
Circumflex 'a' = 0xc3a2
Circumflex 'e' = 0xc3aa
Circumflex 'i' = 0xc3ae
Circumflex 'o' = 0xc3b4
Circumflex 'u' = 0xc3bb
CircumflexTab = Normal Shift CapsLock CapsLock-Shift
Diaeresis ' ' = 0xc2a8
Diaeresis 'A' = 0xc384
Diaeresis 'E' = 0xc38b
Diaeresis 'I' = 0xc38f
Diaeresis 'O' = 0xc396
Diaeresis 'U' = 0xc39c
Diaeresis 'Y' = 0xc5b8
Diaeresis 'a' = 0xc3a4
Diaeresis 'e' = 0xc3ab
Diaeresis 'i' = 0xc3af
Diaeresis 'o' = 0xc3b6
Diaeresis 'u' = 0xc3bc
Diaeresis 'y' = 0xc3bf
DiaeresisTab = Normal Shift CapsLock CapsLock-Shift
Tilde ' ' = '~'
Tilde 'A' = 0xc383
Tilde 'O' = 0xc395
Tilde 'N' = 0xc391
Tilde 'a' = 0xc3a3
Tilde 'o' = 0xc3b5
Tilde 'n' = 0xc3b1
TildeTab = Option Option-Shift CapsLock-Option CapsLock-Option-Shift
"
}
for d in "${KEYSYM_PATHS[@]}"; do
if [ -e "$d$KEYSYMDEF" ]; then
keysymdef="$d$KEYSYMDEF"
break;
fi
done
if [ -z "$keysymdef" ]; then
stop "Cannot find a keysymdef.h"
fi
prefill_hkeymap
parse_lkeymap < "$1"