keymap.subr revision 279612
1139969Simpif [ ! "$_KEYMAP_SUBR" ]; then _KEYMAP_SUBR=1
21556Srgrimes#
31556Srgrimes# Copyright (c) 2013 Devin Teske
41556Srgrimes# All rights reserved.
51556Srgrimes#
61556Srgrimes# Redistribution and use in source and binary forms, with or without
71556Srgrimes# modification, are permitted provided that the following conditions
81556Srgrimes# are met:
91556Srgrimes# 1. Redistributions of source code must retain the above copyright
101556Srgrimes#    notice, this list of conditions and the following disclaimer.
111556Srgrimes# 2. Redistributions in binary form must reproduce the above copyright
121556Srgrimes#    notice, this list of conditions and the following disclaimer in the
131556Srgrimes#    documentation and/or other materials provided with the distribution.
141556Srgrimes#
151556Srgrimes# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
161556Srgrimes# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
171556Srgrimes# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
181556Srgrimes# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
191556Srgrimes# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
201556Srgrimes# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
211556Srgrimes# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
221556Srgrimes# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
231556Srgrimes# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
241556Srgrimes# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
251556Srgrimes# SUCH DAMAGE.
261556Srgrimes#
271556Srgrimes# $FreeBSD: stable/10/usr.sbin/bsdconfig/share/keymap.subr 279612 2015-03-05 00:37:54Z dteske $
281556Srgrimes#
291556Srgrimes############################################################ INCLUDES
301556Srgrimes
311556SrgrimesBSDCFG_SHARE="/usr/share/bsdconfig"
321556Srgrimes. $BSDCFG_SHARE/common.subr || exit 1
331556Srgrimesf_dprintf "%s: loading includes..." keymap.subr
3450471Speterf_include $BSDCFG_SHARE/struct.subr
351556Srgrimes
36211965Sbrian############################################################ CONFIGURATION
371556Srgrimes
3879526Sru#
391556Srgrimes# Defaults taken from usr.sbin/kbdmap/kbdmap.h
401556Srgrimes#
411556Srgrimes: ${DEFAULT_LANG:=en}
421556Srgrimes: ${DEFAULT_KEYMAP_DIR:=/usr/share/syscons/keymaps}
4368935Sru
4476286Skris############################################################ GLOBALS
451556Srgrimes
461556SrgrimesKEYMAPS=
471556SrgrimesNKEYMAPS=0
481556Srgrimes
491556Srgrimes# A "keymap" from kbdmap's point of view
5070150Sruf_struct_define KEYMAP \
511556Srgrimes	desc \
521556Srgrimes	keym \
531556Srgrimes	mark
5470150Sru
551556Srgrimes#
561556Srgrimes# Default behavior is to call f_keymap_get_all() automatically when loaded.
571556Srgrimes#
5870150Sru: ${KEYMAP_SELF_SCAN_ALL=1}
591556Srgrimes
601556Srgrimes############################################################ FUNCTIONS
611556Srgrimes
621556Srgrimes# f_keymap_register $name $desc $keym $mark
631556Srgrimes#
641556Srgrimes# Register a keymap. A `structure' (see struct.subr) is created with the name
651556Srgrimes# keymap_$name (so make sure $name contains only alpha-numeric characters or
6670150Sru# the underscore, `_'). The remaining arguments after $name correspond to the
671556Srgrimes# propertise of the `KEYMAP' structure-type (defined above).
6870150Sru#
6968935Sru# If not already registered, the keymap is then appended to the KEYMAPS
701556Srgrimes# environment variable, a space-separated list of all registered keymaps.
7176286Skris#
721556Srgrimesf_keymap_register()
731556Srgrimes{
741556Srgrimes	local name="$1" desc="$2" keym="$3" mark="$4"
751556Srgrimes
761556Srgrimes	f_struct_new KEYMAP "keymap_$name" || return $FAILURE
7770150Sru	keymap_$name set desc "$desc"
781556Srgrimes	keymap_$name set keym "$keym"
791556Srgrimes	keymap_$name set mark "$mark"
801556Srgrimes
8170150Sru	# Scan our global register to see if needs ammending
821556Srgrimes	local k found=
831556Srgrimes	for k in $KEYMAPS; do
841556Srgrimes		[ "$k" = "$name" ] || continue
8570150Sru		found=1 && break
861556Srgrimes	done
871556Srgrimes	[ "$found" ] || KEYMAPS="$KEYMAPS $name"
881556Srgrimes
891556Srgrimes	return $SUCCESS
9070150Sru}
911556Srgrimes
921556Srgrimes# f_keymap_checkfile $keymap
931556Srgrimes#
9470150Sru# Check that $keymap is a readable kbdmap(5) file. Returns success if $keymap
951556Srgrimes# is a file, is readable, and exists in $DEFAULT_KEYMAP_DIR; otherwise failure.
961556Srgrimes# If debugging is enabled, an appropriate debug error message is printed if
971556Srgrimes# $keymap is not available.
981556Srgrimes#
991556Srgrimesf_keymap_checkfile()
1001556Srgrimes{
1011556Srgrimes	local keym="$1"
10270150Sru	
1031556Srgrimes	# Fixup keymap if it doesn't already contain at least one `/'
10470150Sru	[ "${keym#*/}" = "$keym" ] && keym="$DEFAULT_KEYMAP_DIR/$keym"
10568935Sru
1061556Srgrimes	# Short-cuts
10776286Skris	[ -f "$keym" -a -r "$keym" ] && return $SUCCESS
1081556Srgrimes	f_debugging || return $FAILURE
1091556Srgrimes
1101556Srgrimes	# Print an appropriate debug error message
1111556Srgrimes	if [ ! -e "$keym" ]; then
1121556Srgrimes		f_dprintf "%s: No such file or directory" "$keym"
1131556Srgrimes	elif [ ! -f "$keym" ]; then
1141556Srgrimes		f_dprintf "%s: Not a file!" "$keym"
1151556Srgrimes	elif [ ! -r "$keym" ]; then
1161556Srgrimes		f_dprintf "%s: Permission denied" "$keym"
1171556Srgrimes	fi
1181556Srgrimes
1191556Srgrimes	return $FAILURE
12070150Sru}
1211556Srgrimes
1221556Srgrimes# f_keymap_get_all
1231556Srgrimes#
12470150Sru# Get all keymap information for kbdmap(5) entries both in the database and
1251556Srgrimes# loosely existing in $DEFAULT_KEYMAP_DIR.
1261556Srgrimes#
1271556Srgrimesf_keymap_get_all()
12870150Sru{
1291556Srgrimes	local fname=f_keymap_get_all
1301556Srgrimes	local lang="${LC_ALL:-${LC_CTYPE:-${LANG:-$DEFAULT_LANG}}}"
1311556Srgrimes	[ "$lang" = "C" ] && lang="$DEFAULT_LANG"
13270150Sru
1331556Srgrimes	f_dprintf "%s: Looking for keymap files..." $fname
1341556Srgrimes	f_dialog_info "$msg_looking_for_keymap_files"
1351556Srgrimes	f_dprintf "DEFAULT_LANG=[%s]" "$DEFAULT_LANG"
1361556Srgrimes
1371556Srgrimes	eval "$( awk -F: -v lang="$lang" -v lang_default="$DEFAULT_LANG" '
1381556Srgrimes		BEGIN {
1391556Srgrimes			# en_US.ISO8859-1 -> en_..\.ISO8859-1
1401556Srgrimes			dialect = lang
1411556Srgrimes			if (length(dialect) >= 6 &&
1421556Srgrimes			    substr(dialect, 3, 1) == "_")
1431556Srgrimes				dialect = substr(dialect, 1, 3) ".." \
14470150Sru				          substr(dialect, 6)
1451556Srgrimes			printf "f_dprintf \"dialect=[%%s]\" \"%s\";\n", dialect
14672432Sru
14768935Sru			# en_US.ISO8859-1 -> en
1481556Srgrimes			lang_abk = lang
1491556Srgrimes			if (length(lang_abk) >= 3 &&
1501556Srgrimes			    substr(lang_abk, 3, 1) == "_")
1511556Srgrimes				lang_abk = substr(lang_abk, 1, 2)
1521556Srgrimes			printf "f_dprintf \"lang_abk=[%%s]\" \"%s\";\n",
15370150Sru			       lang_abk
1541556Srgrimes		}
1551556Srgrimes		function find_token(buffer, token)
1561556Srgrimes		{
15770150Sru			if (split(buffer, tokens, /,/) == 0) return 0
1581556Srgrimes			found = 0
1591556Srgrimes			for (t in tokens)
1601556Srgrimes				if (token == tokens[t]) { found = 1; break }
16170150Sru			return found
1621556Srgrimes		}
1631556Srgrimes		function add_keymap(desc,mark,keym)
1641556Srgrimes		{
16570150Sru			marks[keym] = mark
1661556Srgrimes			name = keym
1671556Srgrimes			gsub(/[^[:alnum:]_]/, "_", name)
1681556Srgrimes			gsub(/'\''/, "'\''\\'\'\''", desc);
1691556Srgrimes			printf "f_keymap_checkfile %s && " \
1701556Srgrimes			       "f_keymap_register %s '\'%s\'' %s %u\n",
1711556Srgrimes			       keym, name, desc, keym, mark
1721556Srgrimes		}
1731556Srgrimes		!/^[[:space:]]*(#|$)/ {
17470150Sru			sub(/^[[:space:]]*/, "", $0)
1751556Srgrimes			keym = $1
17672432Sru			if (keym ~ /^(MENU|FONT)$/) next
1771556Srgrimes			lg = ($2 == "" ? lang_default : $2)
1781556Srgrimes
17995204Scharnier			# Match the entry and store the type of match we made
18095204Scharnier			# as the mark value (so that if we make a better match
18195204Scharnier			# later on with a higher mark, it overwrites previous)
1821556Srgrimes
18395204Scharnier			mark = marks[keym];
18495204Scharnier			if (find_token(lg, lang))
1851556Srgrimes				add_keymap($3, 4, keym) # Best match
1861556Srgrimes			else if (mark <= 3 && find_token(lg, dialect))
1871556Srgrimes				add_keymap($3, 3, keym)
1881556Srgrimes			else if (mark <= 2 && find_token(lg, lang_abk))
1891556Srgrimes				add_keymap($3, 2, keym)
1901556Srgrimes			else if (mark <= 1 && find_token(lg, lang_default))
1911556Srgrimes				add_keymap($3, 1, keym)
1921556Srgrimes			else if (mark <= 0)
1931556Srgrimes				add_keymap($3, 0, keym)
19436049Scharnier		}
1951556Srgrimes	' "$DEFAULT_KEYMAP_DIR/INDEX.${DEFAULT_KEYMAP_DIR##*/}" )"
1961556Srgrimes
1971556Srgrimes
19871895Sru	#
1991556Srgrimes	# Look for keymaps not in database
2001556Srgrimes	#
2011556Srgrimes	local direntry keym name
20295204Scharnier	set +f # glob
2031556Srgrimes	for direntry in "$DEFAULT_KEYMAP_DIR"/*; do
2041556Srgrimes		[ "${direntry##*.}" = ".kbd" ] || continue
2051556Srgrimes		keym="${direntry##*/}"
2061556Srgrimes		f_str2varname "$keym" name
20771895Sru		f_struct keymap_$name && continue
2081556Srgrimes		f_keymap_checkfile "$keym" &&
2091556Srgrimes			f_keymap_register $name "${keym%.*}" "$keym" 0
2101556Srgrimes		f_dprintf "%s: not in kbdmap(5) database" "$keym"
2111556Srgrimes	done
21295204Scharnier
2131556Srgrimes	#
21479754Sdd	# Sort the items by their descriptions
21571895Sru	#
2161556Srgrimes	f_dprintf "%s: Sorting keymap entries by description..." $fname
2171556Srgrimes	KEYMAPS=$(
2181556Srgrimes		for k in $KEYMAPS; do
2191556Srgrimes			echo -n "$k "
2201556Srgrimes			# NOTE: Translate '8x8' to '8x08' before sending to
2211556Srgrimes			# sort(1) so that things work out as we might expect.
2221556Srgrimes			debug= keymap_$k get desc | awk 'gsub(/8x8/,"8x08")||1'
2231556Srgrimes		done | sort -k2 | awk '{
2241556Srgrimes			printf "%s%s", (started ? " " : ""), $1; started = 1
2251556Srgrimes		}'
22695204Scharnier	)
2271556Srgrimes
2281556Srgrimes	return $SUCCESS
2291556Srgrimes}
2301556Srgrimes
23179754Sdd# f_keymap_kbdcontrol $keymap
2321556Srgrimes#
23379754Sdd# Install keyboard map file from $keymap.
2341556Srgrimes#
23579754Sddf_keymap_kbdcontrol()
2361556Srgrimes{
2371556Srgrimes	local keymap="$1"
2381556Srgrimes
2391556Srgrimes	[ "$keymap" ] || return $SUCCESS
2401556Srgrimes
24195204Scharnier	# Fixup keymap if it doesn't already contain at least one `/'
2421556Srgrimes	[ "${keymap#*/}" = "$keymap" ] && keymap="$DEFAULT_KEYMAP_DIR/$keymap"
2431556Srgrimes
2441556Srgrimes	[ "$USE_XDIALOG" ] || kbdcontrol -l "$keymap"
24579754Sdd}
2461556Srgrimes
2471556Srgrimes############################################################ MAIN
2481556Srgrimes
2491556Srgrimes#
2501556Srgrimes# Scan for keymaps unless requeted otherwise
2511556Srgrimes#
2521556Srgrimesf_dprintf "%s: KEYMAP_SELF_SCAN_ALL=[%s]" keymap.subr "$KEYMAP_SELF_SCAN_ALL"
2531556Srgrimescase "$KEYMAP_SELF_SCAN_ALL" in
2541556Srgrimes""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
2551556Srgrimes*) f_keymap_get_all
2561556Srgrimesesac
2571556Srgrimes
2581556Srgrimesf_count NKEYMAPS $KEYMAPS
2591556Srgrimesf_dprintf "%s: Found %u keymap file(s)." keymap.subr $NKEYMAPS
2601556Srgrimes
2611556Srgrimesf_dprintf "%s: Successfully loaded." keymap.subr
2621556Srgrimes
2631556Srgrimesfi # ! $_KEYMAP_SUBR
2641556Srgrimes