⛏️ index : haiku.git

#!/bin/sh

# path to a keysymdef.h
KEYSYM_PATHS=(/usr/include/X11/ /zeta/apps/X11R6.4/include/X11/ ./)
KEYSYMDEF=keysymdef.h

# maps Linux (X11) keycodes to BeOS keycodes
L2B=(
	0x00	0x00	0x12	0x13	0x14	0x15	0x16	0x17
	0x18	0x19	0x1a	0x1b	0x1c	0x1d	0x00	0x00
	#16
	0x27	0x28	0x29	0x2a	0x2b	0x2c	0x2d	0x2e
	0x2f	0x30	0x31	0x32	0x00	0x00	0x3c	0x3d
	#32
	0x3e	0x3f	0x40	0x41	0x42	0x43	0x44	0x45
	0x46	0x11	0x00	0x33	0x4c	0x4d	0x4e	0x4f
	#48
	0x50	0x51	0x52	0x53	0x54	0x55	0x00	0x00
	0x00	0x5e	0x00	0x00	0x00	0x00	0x00	0x00
	#64
	0x00	0x00	0x00	0x00	0x00	0x00	0x00	0x00
	#72
	0x00	0x00	0x00	0x00	0x00	0x00	0x00	0x00
	#80
	0x00	0x00	0x00	0x00	0x00	0x00	0x69	0x00
	#88
	0x00	0x00	0x00	0x00	0x00	0x00	0x00	0x00
	#96
	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
	#128
)

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/ /\\\x/g')"
		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')"
		#utf8="$uni"
		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}"
		;;
#	01[0-7][0-9a-f])
#		utf8="c5$(printf '' $((0x80${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
			#warn "skipping $line"
			continue
		fi
		mods=0
		for k in $keyspec; do
			#echo -n "-$k-"
			case "$k" in
				Shift|shift)
					mods=$((mods | 0x1))
					;;
				Control|control)
					mods=$((mods | 0x4))
					;;
				Alt|alt)
					mods=$((mods | 0x2))
					#warn "unhandled modifier"
					;;
				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
			#echo "skipping Alt line: $line"
			continue
		fi
		hkeycode="$(remap_key_l2b "$keycode")"
		#echo "$hkeycode"
		# handle values
		kv=($keyvals)
		hkv=('' '' '' '')
		if [ -z "${kv[1]}" ]; then
			case "${kv[0]}" in 
			[a-z])
				#echo "plop-${kv[0]}-"
				kv[1]="$(echo "${kv[0]}" | tr '[a-z]' '[A-Z]')"
				#echo "-${#kv[@]}-"
				;;
			*)
				;;
			esac
		fi
		for n in $(seq 0 3); do
			#if [ -z "${kv[$n]}" ]; then
			#	continue;
			#fi
			hkv[$n]="$(convert_keyval "${kv[$n]}")"
			if [ "${hkv[$n]}" = "" ]; then
				hkv[$n]="''"
			fi
		done
		#echo "-$mods-"
		case "$mods" in
			0)
				eval "hkmap_${hkeycode}[0]=\"${hkv[0]}\""	# n
				eval "hkmap_${hkeycode}[1]=\"${hkv[1]}\""	# s
				#eval "hkmap_${hkeycode}[2]=\"${hkv[2]}\""	# c
				eval "hkmap_${hkeycode}[3]=\"${hkv[2]}\""	# o
				eval "hkmap_${hkeycode}[4]=\"${hkv[3]}\""	# os
				eval "hkmap_${hkeycode}[5]=\"${hkv[1]}\""	# C
				eval "hkmap_${hkeycode}[6]=\"${hkv[0]}\""	# Cs
				eval "hkmap_${hkeycode}[7]=\"${hkv[2]}\""	# Co
				eval "hkmap_${hkeycode}[8]=\"${hkv[3]}\""	# Cos
				;;
			64)	#Option(AltGr)
				eval "hkmap_${hkeycode}[3]=\"${hkv[0]}\""
				;;
			65)	#Shift+Option(AltGr)
				eval "hkmap_${hkeycode}[4]=\"${hkv[0]}\""
				;;
			*)
				warn "unhandled modifiers $mods"
				;;
		esac
		#for i in $(seq 0 3); do
		#	if [ -z "${kv[$i]}" ]; then
		#		break
		#	fi
		#	
		#	#echo "[$i]='${kv[$i]}'"
		#done
		#echo ":$keycode:"
		#echo "$keyspec===$keyvals"
	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="'.'";;
#			$((0x66)))
#				val="''";;
			*)
				;;
		esac
		if [ -z "$val2" ]; then
			val2="$val"
		fi
		eval "hkmap_$n=(\"$val\" \"$val2\" \"$val\" \"$val\" \"$val2\" \"$val\" \"$val2\" \"$val\" \"$val2\")"
		
		#eval v="(\${hkmap_$n[*]})"
		#echo "${v[7]}"
	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 
"

}

# find keysymdef.h
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"