1256325Sdteskeif [ ! "$_KEYMAP_SUBR" ]; then _KEYMAP_SUBR=1 2256325Sdteske# 3256325Sdteske# Copyright (c) 2013 Devin Teske 4256325Sdteske# All rights reserved. 5256325Sdteske# 6256325Sdteske# Redistribution and use in source and binary forms, with or without 7256325Sdteske# modification, are permitted provided that the following conditions 8256325Sdteske# are met: 9256325Sdteske# 1. Redistributions of source code must retain the above copyright 10256325Sdteske# notice, this list of conditions and the following disclaimer. 11256325Sdteske# 2. Redistributions in binary form must reproduce the above copyright 12256325Sdteske# notice, this list of conditions and the following disclaimer in the 13256325Sdteske# documentation and/or other materials provided with the distribution. 14256325Sdteske# 15256325Sdteske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16256325Sdteske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17256325Sdteske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18256325Sdteske# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19256325Sdteske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20256325Sdteske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21256325Sdteske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22256325Sdteske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23256325Sdteske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24256325Sdteske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25256325Sdteske# SUCH DAMAGE. 26256325Sdteske# 27256325Sdteske# $FreeBSD$ 28256325Sdteske# 29256325Sdteske############################################################ INCLUDES 30256325Sdteske 31256325SdteskeBSDCFG_SHARE="/usr/share/bsdconfig" 32256325Sdteske. $BSDCFG_SHARE/common.subr || exit 1 33256325Sdteskef_dprintf "%s: loading includes..." keymap.subr 34256325Sdteskef_include $BSDCFG_SHARE/struct.subr 35256325Sdteske 36256325Sdteske############################################################ CONFIGURATION 37256325Sdteske 38256325Sdteske# 39256325Sdteske# Defaults taken from usr.sbin/kbdmap/kbdmap.h 40256325Sdteske# 41256325Sdteske: ${DEFAULT_LANG:=en} 42256325Sdteske: ${DEFAULT_KEYMAP_DIR:=/usr/share/syscons/keymaps} 43256325Sdteske 44256325Sdteske############################################################ GLOBALS 45256325Sdteske 46256325SdteskeKEYMAPS= 47260678SdteskeNKEYMAPS=0 48256325Sdteske 49256325Sdteske# A "keymap" from kbdmap's point of view 50256325Sdteskef_struct_define KEYMAP \ 51256325Sdteske desc \ 52256325Sdteske keym \ 53256325Sdteske mark 54256325Sdteske 55256325Sdteske# 56256325Sdteske# Default behavior is to call f_keymap_get_all() automatically when loaded. 57256325Sdteske# 58256325Sdteske: ${KEYMAP_SELF_SCAN_ALL=1} 59256325Sdteske 60256325Sdteske############################################################ FUNCTIONS 61256325Sdteske 62256325Sdteske# f_keymap_register $name $desc $keym $mark 63256325Sdteske# 64256325Sdteske# Register a keymap. A `structure' (see struct.subr) is created with the name 65256325Sdteske# keymap_$name (so make sure $name contains only alpha-numeric characters or 66256325Sdteske# the underscore, `_'). The remaining arguments after $name correspond to the 67256325Sdteske# propertise of the `KEYMAP' structure-type (defined above). 68256325Sdteske# 69256325Sdteske# If not already registered, the keymap is then appended to the KEYMAPS 70256325Sdteske# environment variable, a space-separated list of all registered keymaps. 71256325Sdteske# 72256325Sdteskef_keymap_register() 73256325Sdteske{ 74256325Sdteske local name="$1" desc="$2" keym="$3" mark="$4" 75256325Sdteske 76256325Sdteske f_struct_new KEYMAP "keymap_$name" || return $FAILURE 77256325Sdteske keymap_$name set desc "$desc" 78256325Sdteske keymap_$name set keym "$keym" 79256325Sdteske keymap_$name set mark "$mark" 80256325Sdteske 81256325Sdteske # Scan our global register to see if needs ammending 82256325Sdteske local k found= 83256325Sdteske for k in $KEYMAPS; do 84256325Sdteske [ "$k" = "$name" ] || continue 85256325Sdteske found=1 && break 86256325Sdteske done 87256325Sdteske [ "$found" ] || KEYMAPS="$KEYMAPS $name" 88256325Sdteske 89256325Sdteske return $SUCCESS 90256325Sdteske} 91256325Sdteske 92256325Sdteske# f_keymap_checkfile $keymap 93256325Sdteske# 94256325Sdteske# Check that $keymap is a readable kbdmap(5) file. Returns success if $keymap 95256325Sdteske# is a file, is readable, and exists in $DEFAULT_KEYMAP_DIR; otherwise failure. 96256325Sdteske# If debugging is enabled, an appropriate debug error message is printed if 97256325Sdteske# $keymap is not available. 98256325Sdteske# 99256325Sdteskef_keymap_checkfile() 100256325Sdteske{ 101256325Sdteske local keym="$1" 102256325Sdteske 103256325Sdteske # Fixup keymap if it doesn't already contain at least one `/' 104256325Sdteske [ "${keym#*/}" = "$keym" ] && keym="$DEFAULT_KEYMAP_DIR/$keym" 105256325Sdteske 106256325Sdteske # Short-cuts 107256325Sdteske [ -f "$keym" -a -r "$keym" ] && return $SUCCESS 108256325Sdteske f_debugging || return $FAILURE 109256325Sdteske 110256325Sdteske # Print an appropriate debug error message 111256325Sdteske if [ ! -e "$keym" ]; then 112256325Sdteske f_dprintf "%s: No such file or directory" "$keym" 113256325Sdteske elif [ ! -f "$keym" ]; then 114256325Sdteske f_dprintf "%s: Not a file!" "$keym" 115256325Sdteske elif [ ! -r "$keym" ]; then 116256325Sdteske f_dprintf "%s: Permission denied" "$keym" 117256325Sdteske fi 118256325Sdteske 119256325Sdteske return $FAILURE 120256325Sdteske} 121256325Sdteske 122256325Sdteske# f_keymap_get_all 123256325Sdteske# 124256325Sdteske# Get all keymap information for kbdmap(5) entries both in the database and 125256325Sdteske# loosely existing in $DEFAULT_KEYMAP_DIR. 126256325Sdteske# 127256325Sdteskef_keymap_get_all() 128256325Sdteske{ 129256325Sdteske local fname=f_keymap_get_all 130256325Sdteske local lang="${LC_ALL:-${LC_CTYPE:-${LANG:-$DEFAULT_LANG}}}" 131256325Sdteske [ "$lang" = "C" ] && lang="$DEFAULT_LANG" 132256325Sdteske 133256325Sdteske f_dprintf "%s: Looking for keymap files..." $fname 134256325Sdteske f_dialog_info "$msg_looking_for_keymap_files" 135256325Sdteske f_dprintf "DEFAULT_LANG=[%s]" "$DEFAULT_LANG" 136256325Sdteske 137256325Sdteske eval "$( awk -F: -v lang="$lang" -v lang_default="$DEFAULT_LANG" ' 138256325Sdteske BEGIN { 139256325Sdteske # en_US.ISO8859-1 -> en_..\.ISO8859-1 140256325Sdteske dialect = lang 141256325Sdteske if (length(dialect) >= 6 && 142256325Sdteske substr(dialect, 3, 1) == "_") 143256325Sdteske dialect = substr(dialect, 1, 3) ".." \ 144256325Sdteske substr(dialect, 6) 145256325Sdteske printf "f_dprintf \"dialect=[%%s]\" \"%s\";\n", dialect 146256325Sdteske 147256325Sdteske # en_US.ISO8859-1 -> en 148256325Sdteske lang_abk = lang 149256325Sdteske if (length(lang_abk) >= 3 && 150256325Sdteske substr(lang_abk, 3, 1) == "_") 151256325Sdteske lang_abk = substr(lang_abk, 1, 2) 152256325Sdteske printf "f_dprintf \"lang_abk=[%%s]\" \"%s\";\n", 153256325Sdteske lang_abk 154256325Sdteske } 155256325Sdteske function find_token(buffer, token) 156256325Sdteske { 157256325Sdteske if (split(buffer, tokens, /,/) == 0) return 0 158256325Sdteske found = 0 159256325Sdteske for (t in tokens) 160256325Sdteske if (token == tokens[t]) { found = 1; break } 161256325Sdteske return found 162256325Sdteske } 163256325Sdteske function add_keymap(desc,mark,keym) 164256325Sdteske { 165256325Sdteske marks[keym] = mark 166256325Sdteske name = keym 167256325Sdteske gsub(/[^[:alnum:]_]/, "_", name) 168263980Sdteske gsub(/'\''/, "'\''\\'\'\''", desc); 169256325Sdteske printf "f_keymap_checkfile %s && " \ 170256325Sdteske "f_keymap_register %s '\'%s\'' %s %u\n", 171256325Sdteske keym, name, desc, keym, mark 172256325Sdteske } 173256325Sdteske !/^[[:space:]]*(#|$)/ { 174256325Sdteske sub(/^[[:space:]]*/, "", $0) 175256325Sdteske keym = $1 176256325Sdteske if (keym ~ /^(MENU|FONT)$/) next 177256325Sdteske lg = ($2 == "" ? lang_default : $2) 178256325Sdteske 179256325Sdteske # Match the entry and store the type of match we made 180256325Sdteske # as the mark value (so that if we make a better match 181256325Sdteske # later on with a higher mark, it overwrites previous) 182256325Sdteske 183256325Sdteske mark = marks[keym]; 184256325Sdteske if (find_token(lg, lang)) 185256325Sdteske add_keymap($3, 4, keym) # Best match 186256325Sdteske else if (mark <= 3 && find_token(lg, dialect)) 187256325Sdteske add_keymap($3, 3, keym) 188256325Sdteske else if (mark <= 2 && find_token(lg, lang_abk)) 189256325Sdteske add_keymap($3, 2, keym) 190256325Sdteske else if (mark <= 1 && find_token(lg, lang_default)) 191256325Sdteske add_keymap($3, 1, keym) 192256325Sdteske else if (mark <= 0) 193256325Sdteske add_keymap($3, 0, keym) 194256325Sdteske } 195256325Sdteske ' "$DEFAULT_KEYMAP_DIR/INDEX.${DEFAULT_KEYMAP_DIR##*/}" )" 196256325Sdteske 197256325Sdteske 198256325Sdteske # 199256325Sdteske # Look for keymaps not in database 200256325Sdteske # 201256325Sdteske local direntry keym name 202256325Sdteske set +f # glob 203256325Sdteske for direntry in "$DEFAULT_KEYMAP_DIR"/*; do 204256325Sdteske [ "${direntry##*.}" = ".kbd" ] || continue 205256325Sdteske keym="${direntry##*/}" 206256325Sdteske f_str2varname "$keym" name 207256325Sdteske f_struct keymap_$name && continue 208256325Sdteske f_keymap_checkfile "$keym" && 209256325Sdteske f_keymap_register $name "${keym%.*}" "$keym" 0 210256325Sdteske f_dprintf "%s: not in kbdmap(5) database" "$keym" 211256325Sdteske done 212256325Sdteske 213256325Sdteske # 214256325Sdteske # Sort the items by their descriptions 215256325Sdteske # 216256325Sdteske f_dprintf "%s: Sorting keymap entries by description..." $fname 217256325Sdteske KEYMAPS=$( 218256325Sdteske for k in $KEYMAPS; do 219256325Sdteske echo -n "$k " 220256325Sdteske # NOTE: Translate '8x8' to '8x08' before sending to 221256325Sdteske # sort(1) so that things work out as we might expect. 222256325Sdteske debug= keymap_$k get desc | sed -e 's/8x8/8x08/g' 223256325Sdteske done | sort -k2 | awk '{ 224256325Sdteske printf "%s%s", (started ? " " : ""), $1; started = 1 225256325Sdteske }' 226256325Sdteske ) 227256325Sdteske 228256325Sdteske return $SUCCESS 229256325Sdteske} 230256325Sdteske 231256325Sdteske# f_keymap_kbdcontrol $keymap 232256325Sdteske# 233256325Sdteske# Install keyboard map file from $keymap. 234256325Sdteske# 235256325Sdteskef_keymap_kbdcontrol() 236256325Sdteske{ 237256325Sdteske local keymap="$1" 238256325Sdteske 239256325Sdteske [ "$keymap" ] || return $SUCCESS 240256325Sdteske 241256325Sdteske # Fixup keymap if it doesn't already contain at least one `/' 242256325Sdteske [ "${keymap#*/}" = "$keymap" ] && keymap="$DEFAULT_KEYMAP_DIR/$keymap" 243256325Sdteske 244256325Sdteske [ "$USE_XDIALOG" ] || kbdcontrol -l "$keymap" 245256325Sdteske} 246256325Sdteske 247256325Sdteske############################################################ MAIN 248256325Sdteske 249256325Sdteske# 250256325Sdteske# Scan for keymaps unless requeted otherwise 251256325Sdteske# 252256325Sdteskef_dprintf "%s: KEYMAP_SELF_SCAN_ALL=[%s]" keymap.subr "$KEYMAP_SELF_SCAN_ALL" 253256325Sdteskecase "$KEYMAP_SELF_SCAN_ALL" in 254256325Sdteske""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;; 255256325Sdteske*) f_keymap_get_all 256256325Sdteskeesac 257256325Sdteske 258260678Sdteskef_count NKEYMAPS $KEYMAPS 259260678Sdteskef_dprintf "%s: Found %u keymap file(s)." keymap.subr $NKEYMAPS 260256325Sdteske 261256325Sdteskef_dprintf "%s: Successfully loaded." keymap.subr 262256325Sdteske 263256325Sdteskefi # ! $_KEYMAP_SUBR 264