13636c235SDevin Teskeif [ ! "$_KEYMAP_SUBR" ]; then _KEYMAP_SUBR=1 23636c235SDevin Teske# 335994c42SDevin Teske# Copyright (c) 2013-2015 Devin Teske 43636c235SDevin Teske# All rights reserved. 53636c235SDevin Teske# 63636c235SDevin Teske# Redistribution and use in source and binary forms, with or without 73636c235SDevin Teske# modification, are permitted provided that the following conditions 83636c235SDevin Teske# are met: 93636c235SDevin Teske# 1. Redistributions of source code must retain the above copyright 103636c235SDevin Teske# notice, this list of conditions and the following disclaimer. 113636c235SDevin Teske# 2. Redistributions in binary form must reproduce the above copyright 123636c235SDevin Teske# notice, this list of conditions and the following disclaimer in the 133636c235SDevin Teske# documentation and/or other materials provided with the distribution. 143636c235SDevin Teske# 153636c235SDevin Teske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 163636c235SDevin Teske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 173636c235SDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 183636c235SDevin Teske# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 193636c235SDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 203636c235SDevin Teske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 213636c235SDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 223636c235SDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 233636c235SDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 243636c235SDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 253636c235SDevin Teske# SUCH DAMAGE. 263636c235SDevin Teske# 273636c235SDevin Teske# 283636c235SDevin Teske############################################################ INCLUDES 293636c235SDevin Teske 303636c235SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig" 313636c235SDevin Teske. $BSDCFG_SHARE/common.subr || exit 1 323636c235SDevin Teskef_dprintf "%s: loading includes..." keymap.subr 333636c235SDevin Teskef_include $BSDCFG_SHARE/struct.subr 343636c235SDevin Teske 353636c235SDevin Teske############################################################ CONFIGURATION 363636c235SDevin Teske 373636c235SDevin Teske# 383636c235SDevin Teske# Defaults taken from usr.sbin/kbdmap/kbdmap.h 393636c235SDevin Teske# 403636c235SDevin Teske: ${DEFAULT_LANG:=en} 41*ab00ac32SDevin Teskecase "$( sysctl -n kern.vty )" in 42*ab00ac32SDevin Teskevt) : ${DEFAULT_KEYMAP_DIR:=/usr/share/vt/keymaps} ;; 43*ab00ac32SDevin Teske*) : ${DEFAULT_KEYMAP_DIR:=/usr/share/syscons/keymaps} ;; 44*ab00ac32SDevin Teskeesac 453636c235SDevin Teske 463636c235SDevin Teske############################################################ GLOBALS 473636c235SDevin Teske 483636c235SDevin TeskeKEYMAPS= 49d4ae33f0SDevin TeskeNKEYMAPS=0 503636c235SDevin Teske 513636c235SDevin Teske# A "keymap" from kbdmap's point of view 523636c235SDevin Teskef_struct_define KEYMAP \ 533636c235SDevin Teske desc \ 543636c235SDevin Teske keym \ 553636c235SDevin Teske mark 563636c235SDevin Teske 573636c235SDevin Teske# 583636c235SDevin Teske# Default behavior is to call f_keymap_get_all() automatically when loaded. 593636c235SDevin Teske# 603636c235SDevin Teske: ${KEYMAP_SELF_SCAN_ALL=1} 613636c235SDevin Teske 623636c235SDevin Teske############################################################ FUNCTIONS 633636c235SDevin Teske 643636c235SDevin Teske# f_keymap_register $name $desc $keym $mark 653636c235SDevin Teske# 663636c235SDevin Teske# Register a keymap. A `structure' (see struct.subr) is created with the name 673636c235SDevin Teske# keymap_$name (so make sure $name contains only alpha-numeric characters or 683636c235SDevin Teske# the underscore, `_'). The remaining arguments after $name correspond to the 693636c235SDevin Teske# propertise of the `KEYMAP' structure-type (defined above). 703636c235SDevin Teske# 713636c235SDevin Teske# If not already registered, the keymap is then appended to the KEYMAPS 723636c235SDevin Teske# environment variable, a space-separated list of all registered keymaps. 733636c235SDevin Teske# 743636c235SDevin Teskef_keymap_register() 753636c235SDevin Teske{ 763636c235SDevin Teske local name="$1" desc="$2" keym="$3" mark="$4" 773636c235SDevin Teske 783636c235SDevin Teske f_struct_new KEYMAP "keymap_$name" || return $FAILURE 793636c235SDevin Teske keymap_$name set desc "$desc" 803636c235SDevin Teske keymap_$name set keym "$keym" 813636c235SDevin Teske keymap_$name set mark "$mark" 823636c235SDevin Teske 833636c235SDevin Teske # Scan our global register to see if needs ammending 843636c235SDevin Teske local k found= 853636c235SDevin Teske for k in $KEYMAPS; do 863636c235SDevin Teske [ "$k" = "$name" ] || continue 873636c235SDevin Teske found=1 && break 883636c235SDevin Teske done 893636c235SDevin Teske [ "$found" ] || KEYMAPS="$KEYMAPS $name" 903636c235SDevin Teske 913636c235SDevin Teske return $SUCCESS 923636c235SDevin Teske} 933636c235SDevin Teske 943636c235SDevin Teske# f_keymap_checkfile $keymap 953636c235SDevin Teske# 963636c235SDevin Teske# Check that $keymap is a readable kbdmap(5) file. Returns success if $keymap 973636c235SDevin Teske# is a file, is readable, and exists in $DEFAULT_KEYMAP_DIR; otherwise failure. 983636c235SDevin Teske# If debugging is enabled, an appropriate debug error message is printed if 993636c235SDevin Teske# $keymap is not available. 1003636c235SDevin Teske# 1013636c235SDevin Teskef_keymap_checkfile() 1023636c235SDevin Teske{ 1033636c235SDevin Teske local keym="$1" 1043636c235SDevin Teske 1053636c235SDevin Teske # Fixup keymap if it doesn't already contain at least one `/' 1063636c235SDevin Teske [ "${keym#*/}" = "$keym" ] && keym="$DEFAULT_KEYMAP_DIR/$keym" 1073636c235SDevin Teske 1083636c235SDevin Teske # Short-cuts 1093636c235SDevin Teske [ -f "$keym" -a -r "$keym" ] && return $SUCCESS 1103636c235SDevin Teske f_debugging || return $FAILURE 1113636c235SDevin Teske 1123636c235SDevin Teske # Print an appropriate debug error message 1133636c235SDevin Teske if [ ! -e "$keym" ]; then 1143636c235SDevin Teske f_dprintf "%s: No such file or directory" "$keym" 1153636c235SDevin Teske elif [ ! -f "$keym" ]; then 1163636c235SDevin Teske f_dprintf "%s: Not a file!" "$keym" 1173636c235SDevin Teske elif [ ! -r "$keym" ]; then 1183636c235SDevin Teske f_dprintf "%s: Permission denied" "$keym" 1193636c235SDevin Teske fi 1203636c235SDevin Teske 1213636c235SDevin Teske return $FAILURE 1223636c235SDevin Teske} 1233636c235SDevin Teske 1243636c235SDevin Teske# f_keymap_get_all 1253636c235SDevin Teske# 1263636c235SDevin Teske# Get all keymap information for kbdmap(5) entries both in the database and 1273636c235SDevin Teske# loosely existing in $DEFAULT_KEYMAP_DIR. 1283636c235SDevin Teske# 1293636c235SDevin Teskef_keymap_get_all() 1303636c235SDevin Teske{ 1313636c235SDevin Teske local fname=f_keymap_get_all 1323636c235SDevin Teske local lang="${LC_ALL:-${LC_CTYPE:-${LANG:-$DEFAULT_LANG}}}" 1333636c235SDevin Teske [ "$lang" = "C" ] && lang="$DEFAULT_LANG" 1343636c235SDevin Teske 1353636c235SDevin Teske f_dprintf "%s: Looking for keymap files..." $fname 1363636c235SDevin Teske f_dialog_info "$msg_looking_for_keymap_files" 1373636c235SDevin Teske f_dprintf "DEFAULT_LANG=[%s]" "$DEFAULT_LANG" 1383636c235SDevin Teske 1393636c235SDevin Teske eval "$( awk -F: -v lang="$lang" -v lang_default="$DEFAULT_LANG" ' 1403636c235SDevin Teske BEGIN { 1413636c235SDevin Teske # en_US.ISO8859-1 -> en_..\.ISO8859-1 1423636c235SDevin Teske dialect = lang 1433636c235SDevin Teske if (length(dialect) >= 6 && 1443636c235SDevin Teske substr(dialect, 3, 1) == "_") 1453636c235SDevin Teske dialect = substr(dialect, 1, 3) ".." \ 1463636c235SDevin Teske substr(dialect, 6) 1473636c235SDevin Teske printf "f_dprintf \"dialect=[%%s]\" \"%s\";\n", dialect 1483636c235SDevin Teske 1493636c235SDevin Teske # en_US.ISO8859-1 -> en 1503636c235SDevin Teske lang_abk = lang 1513636c235SDevin Teske if (length(lang_abk) >= 3 && 1523636c235SDevin Teske substr(lang_abk, 3, 1) == "_") 1533636c235SDevin Teske lang_abk = substr(lang_abk, 1, 2) 1543636c235SDevin Teske printf "f_dprintf \"lang_abk=[%%s]\" \"%s\";\n", 1553636c235SDevin Teske lang_abk 1563636c235SDevin Teske } 1573636c235SDevin Teske function find_token(buffer, token) 1583636c235SDevin Teske { 1593636c235SDevin Teske if (split(buffer, tokens, /,/) == 0) return 0 1603636c235SDevin Teske found = 0 1613636c235SDevin Teske for (t in tokens) 1623636c235SDevin Teske if (token == tokens[t]) { found = 1; break } 1633636c235SDevin Teske return found 1643636c235SDevin Teske } 1653636c235SDevin Teske function add_keymap(desc,mark,keym) 1663636c235SDevin Teske { 1673636c235SDevin Teske marks[keym] = mark 1683636c235SDevin Teske name = keym 1693636c235SDevin Teske gsub(/[^[:alnum:]_]/, "_", name) 170bc3f5ec9SDevin Teske gsub(/'\''/, "'\''\\'\'\''", desc); 1713636c235SDevin Teske printf "f_keymap_checkfile %s && " \ 1723636c235SDevin Teske "f_keymap_register %s '\'%s\'' %s %u\n", 1733636c235SDevin Teske keym, name, desc, keym, mark 1743636c235SDevin Teske } 1753636c235SDevin Teske !/^[[:space:]]*(#|$)/ { 1763636c235SDevin Teske sub(/^[[:space:]]*/, "", $0) 1773636c235SDevin Teske keym = $1 1783636c235SDevin Teske if (keym ~ /^(MENU|FONT)$/) next 1793636c235SDevin Teske lg = ($2 == "" ? lang_default : $2) 1803636c235SDevin Teske 1813636c235SDevin Teske # Match the entry and store the type of match we made 1823636c235SDevin Teske # as the mark value (so that if we make a better match 1833636c235SDevin Teske # later on with a higher mark, it overwrites previous) 1843636c235SDevin Teske 1853636c235SDevin Teske mark = marks[keym]; 1863636c235SDevin Teske if (find_token(lg, lang)) 1873636c235SDevin Teske add_keymap($3, 4, keym) # Best match 1883636c235SDevin Teske else if (mark <= 3 && find_token(lg, dialect)) 1893636c235SDevin Teske add_keymap($3, 3, keym) 1903636c235SDevin Teske else if (mark <= 2 && find_token(lg, lang_abk)) 1913636c235SDevin Teske add_keymap($3, 2, keym) 1923636c235SDevin Teske else if (mark <= 1 && find_token(lg, lang_default)) 1933636c235SDevin Teske add_keymap($3, 1, keym) 1943636c235SDevin Teske else if (mark <= 0) 1953636c235SDevin Teske add_keymap($3, 0, keym) 1963636c235SDevin Teske } 1973636c235SDevin Teske ' "$DEFAULT_KEYMAP_DIR/INDEX.${DEFAULT_KEYMAP_DIR##*/}" )" 1983636c235SDevin Teske 1993636c235SDevin Teske 2003636c235SDevin Teske # 2013636c235SDevin Teske # Look for keymaps not in database 2023636c235SDevin Teske # 2033636c235SDevin Teske local direntry keym name 2043636c235SDevin Teske set +f # glob 2053636c235SDevin Teske for direntry in "$DEFAULT_KEYMAP_DIR"/*; do 2063636c235SDevin Teske [ "${direntry##*.}" = ".kbd" ] || continue 2073636c235SDevin Teske keym="${direntry##*/}" 2083636c235SDevin Teske f_str2varname "$keym" name 2093636c235SDevin Teske f_struct keymap_$name && continue 2103636c235SDevin Teske f_keymap_checkfile "$keym" && 2113636c235SDevin Teske f_keymap_register $name "${keym%.*}" "$keym" 0 2123636c235SDevin Teske f_dprintf "%s: not in kbdmap(5) database" "$keym" 2133636c235SDevin Teske done 2143636c235SDevin Teske 2153636c235SDevin Teske # 2163636c235SDevin Teske # Sort the items by their descriptions 2173636c235SDevin Teske # 2183636c235SDevin Teske f_dprintf "%s: Sorting keymap entries by description..." $fname 2193636c235SDevin Teske KEYMAPS=$( 2203636c235SDevin Teske for k in $KEYMAPS; do 2213636c235SDevin Teske echo -n "$k " 2223636c235SDevin Teske # NOTE: Translate '8x8' to '8x08' before sending to 2233636c235SDevin Teske # sort(1) so that things work out as we might expect. 22494f2a70eSDevin Teske debug= keymap_$k get desc | awk 'gsub(/8x8/,"8x08")||1' 2253636c235SDevin Teske done | sort -k2 | awk '{ 2263636c235SDevin Teske printf "%s%s", (started ? " " : ""), $1; started = 1 2273636c235SDevin Teske }' 2283636c235SDevin Teske ) 2293636c235SDevin Teske 2303636c235SDevin Teske return $SUCCESS 2313636c235SDevin Teske} 2323636c235SDevin Teske 2333636c235SDevin Teske# f_keymap_kbdcontrol $keymap 2343636c235SDevin Teske# 2353636c235SDevin Teske# Install keyboard map file from $keymap. 2363636c235SDevin Teske# 2373636c235SDevin Teskef_keymap_kbdcontrol() 2383636c235SDevin Teske{ 2393636c235SDevin Teske local keymap="$1" 2403636c235SDevin Teske 2413636c235SDevin Teske [ "$keymap" ] || return $SUCCESS 2423636c235SDevin Teske 2433636c235SDevin Teske # Fixup keymap if it doesn't already contain at least one `/' 2443636c235SDevin Teske [ "${keymap#*/}" = "$keymap" ] && keymap="$DEFAULT_KEYMAP_DIR/$keymap" 2453636c235SDevin Teske 2463636c235SDevin Teske [ "$USE_XDIALOG" ] || kbdcontrol -l "$keymap" 2473636c235SDevin Teske} 2483636c235SDevin Teske 2493636c235SDevin Teske############################################################ MAIN 2503636c235SDevin Teske 2513636c235SDevin Teske# 2523636c235SDevin Teske# Scan for keymaps unless requeted otherwise 2533636c235SDevin Teske# 2543636c235SDevin Teskef_dprintf "%s: KEYMAP_SELF_SCAN_ALL=[%s]" keymap.subr "$KEYMAP_SELF_SCAN_ALL" 2553636c235SDevin Teskecase "$KEYMAP_SELF_SCAN_ALL" in 2563636c235SDevin Teske""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;; 2573636c235SDevin Teske*) f_keymap_get_all 2583636c235SDevin Teskeesac 2593636c235SDevin Teske 260d4ae33f0SDevin Teskef_count NKEYMAPS $KEYMAPS 261d4ae33f0SDevin Teskef_dprintf "%s: Found %u keymap file(s)." keymap.subr $NKEYMAPS 2623636c235SDevin Teske 2633636c235SDevin Teskef_dprintf "%s: Successfully loaded." keymap.subr 2643636c235SDevin Teske 2653636c235SDevin Teskefi # ! $_KEYMAP_SUBR 266