1*3636c235SDevin Teskeif [ ! "$_KEYMAP_SUBR" ]; then _KEYMAP_SUBR=1 2*3636c235SDevin Teske# 3*3636c235SDevin Teske# Copyright (c) 2013 Devin Teske 4*3636c235SDevin Teske# All rights reserved. 5*3636c235SDevin Teske# 6*3636c235SDevin Teske# Redistribution and use in source and binary forms, with or without 7*3636c235SDevin Teske# modification, are permitted provided that the following conditions 8*3636c235SDevin Teske# are met: 9*3636c235SDevin Teske# 1. Redistributions of source code must retain the above copyright 10*3636c235SDevin Teske# notice, this list of conditions and the following disclaimer. 11*3636c235SDevin Teske# 2. Redistributions in binary form must reproduce the above copyright 12*3636c235SDevin Teske# notice, this list of conditions and the following disclaimer in the 13*3636c235SDevin Teske# documentation and/or other materials provided with the distribution. 14*3636c235SDevin Teske# 15*3636c235SDevin Teske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16*3636c235SDevin Teske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*3636c235SDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*3636c235SDevin Teske# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19*3636c235SDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*3636c235SDevin Teske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*3636c235SDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*3636c235SDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*3636c235SDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*3636c235SDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*3636c235SDevin Teske# SUCH DAMAGE. 26*3636c235SDevin Teske# 27*3636c235SDevin Teske# $FreeBSD$ 28*3636c235SDevin Teske# 29*3636c235SDevin Teske############################################################ INCLUDES 30*3636c235SDevin Teske 31*3636c235SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig" 32*3636c235SDevin Teske. $BSDCFG_SHARE/common.subr || exit 1 33*3636c235SDevin Teskef_dprintf "%s: loading includes..." keymap.subr 34*3636c235SDevin Teskef_include $BSDCFG_SHARE/struct.subr 35*3636c235SDevin Teske 36*3636c235SDevin Teske############################################################ CONFIGURATION 37*3636c235SDevin Teske 38*3636c235SDevin Teske# 39*3636c235SDevin Teske# Defaults taken from usr.sbin/kbdmap/kbdmap.h 40*3636c235SDevin Teske# 41*3636c235SDevin Teske: ${DEFAULT_LANG:=en} 42*3636c235SDevin Teske: ${DEFAULT_KEYMAP_DIR:=/usr/share/syscons/keymaps} 43*3636c235SDevin Teske 44*3636c235SDevin Teske############################################################ GLOBALS 45*3636c235SDevin Teske 46*3636c235SDevin TeskeKEYMAPS= 47*3636c235SDevin Teske 48*3636c235SDevin Teske# A "keymap" from kbdmap's point of view 49*3636c235SDevin Teskef_struct_define KEYMAP \ 50*3636c235SDevin Teske desc \ 51*3636c235SDevin Teske keym \ 52*3636c235SDevin Teske mark 53*3636c235SDevin Teske 54*3636c235SDevin Teske# 55*3636c235SDevin Teske# Default behavior is to call f_keymap_get_all() automatically when loaded. 56*3636c235SDevin Teske# 57*3636c235SDevin Teske: ${KEYMAP_SELF_SCAN_ALL=1} 58*3636c235SDevin Teske 59*3636c235SDevin Teske############################################################ FUNCTIONS 60*3636c235SDevin Teske 61*3636c235SDevin Teske# f_keymap_register $name $desc $keym $mark 62*3636c235SDevin Teske# 63*3636c235SDevin Teske# Register a keymap. A `structure' (see struct.subr) is created with the name 64*3636c235SDevin Teske# keymap_$name (so make sure $name contains only alpha-numeric characters or 65*3636c235SDevin Teske# the underscore, `_'). The remaining arguments after $name correspond to the 66*3636c235SDevin Teske# propertise of the `KEYMAP' structure-type (defined above). 67*3636c235SDevin Teske# 68*3636c235SDevin Teske# If not already registered, the keymap is then appended to the KEYMAPS 69*3636c235SDevin Teske# environment variable, a space-separated list of all registered keymaps. 70*3636c235SDevin Teske# 71*3636c235SDevin Teskef_keymap_register() 72*3636c235SDevin Teske{ 73*3636c235SDevin Teske local name="$1" desc="$2" keym="$3" mark="$4" 74*3636c235SDevin Teske 75*3636c235SDevin Teske f_struct_new KEYMAP "keymap_$name" || return $FAILURE 76*3636c235SDevin Teske keymap_$name set desc "$desc" 77*3636c235SDevin Teske keymap_$name set keym "$keym" 78*3636c235SDevin Teske keymap_$name set mark "$mark" 79*3636c235SDevin Teske 80*3636c235SDevin Teske # Scan our global register to see if needs ammending 81*3636c235SDevin Teske local k found= 82*3636c235SDevin Teske for k in $KEYMAPS; do 83*3636c235SDevin Teske [ "$k" = "$name" ] || continue 84*3636c235SDevin Teske found=1 && break 85*3636c235SDevin Teske done 86*3636c235SDevin Teske [ "$found" ] || KEYMAPS="$KEYMAPS $name" 87*3636c235SDevin Teske 88*3636c235SDevin Teske return $SUCCESS 89*3636c235SDevin Teske} 90*3636c235SDevin Teske 91*3636c235SDevin Teske# f_keymap_checkfile $keymap 92*3636c235SDevin Teske# 93*3636c235SDevin Teske# Check that $keymap is a readable kbdmap(5) file. Returns success if $keymap 94*3636c235SDevin Teske# is a file, is readable, and exists in $DEFAULT_KEYMAP_DIR; otherwise failure. 95*3636c235SDevin Teske# If debugging is enabled, an appropriate debug error message is printed if 96*3636c235SDevin Teske# $keymap is not available. 97*3636c235SDevin Teske# 98*3636c235SDevin Teskef_keymap_checkfile() 99*3636c235SDevin Teske{ 100*3636c235SDevin Teske local keym="$1" 101*3636c235SDevin Teske 102*3636c235SDevin Teske # Fixup keymap if it doesn't already contain at least one `/' 103*3636c235SDevin Teske [ "${keym#*/}" = "$keym" ] && keym="$DEFAULT_KEYMAP_DIR/$keym" 104*3636c235SDevin Teske 105*3636c235SDevin Teske # Short-cuts 106*3636c235SDevin Teske [ -f "$keym" -a -r "$keym" ] && return $SUCCESS 107*3636c235SDevin Teske f_debugging || return $FAILURE 108*3636c235SDevin Teske 109*3636c235SDevin Teske # Print an appropriate debug error message 110*3636c235SDevin Teske if [ ! -e "$keym" ]; then 111*3636c235SDevin Teske f_dprintf "%s: No such file or directory" "$keym" 112*3636c235SDevin Teske elif [ ! -f "$keym" ]; then 113*3636c235SDevin Teske f_dprintf "%s: Not a file!" "$keym" 114*3636c235SDevin Teske elif [ ! -r "$keym" ]; then 115*3636c235SDevin Teske f_dprintf "%s: Permission denied" "$keym" 116*3636c235SDevin Teske fi 117*3636c235SDevin Teske 118*3636c235SDevin Teske return $FAILURE 119*3636c235SDevin Teske} 120*3636c235SDevin Teske 121*3636c235SDevin Teske# f_keymap_get_all 122*3636c235SDevin Teske# 123*3636c235SDevin Teske# Get all keymap information for kbdmap(5) entries both in the database and 124*3636c235SDevin Teske# loosely existing in $DEFAULT_KEYMAP_DIR. 125*3636c235SDevin Teske# 126*3636c235SDevin Teskef_keymap_get_all() 127*3636c235SDevin Teske{ 128*3636c235SDevin Teske local fname=f_keymap_get_all 129*3636c235SDevin Teske local lang="${LC_ALL:-${LC_CTYPE:-${LANG:-$DEFAULT_LANG}}}" 130*3636c235SDevin Teske [ "$lang" = "C" ] && lang="$DEFAULT_LANG" 131*3636c235SDevin Teske 132*3636c235SDevin Teske f_dprintf "%s: Looking for keymap files..." $fname 133*3636c235SDevin Teske f_dialog_info "$msg_looking_for_keymap_files" 134*3636c235SDevin Teske f_dprintf "DEFAULT_LANG=[%s]" "$DEFAULT_LANG" 135*3636c235SDevin Teske 136*3636c235SDevin Teske eval "$( awk -F: -v lang="$lang" -v lang_default="$DEFAULT_LANG" ' 137*3636c235SDevin Teske BEGIN { 138*3636c235SDevin Teske # en_US.ISO8859-1 -> en_..\.ISO8859-1 139*3636c235SDevin Teske dialect = lang 140*3636c235SDevin Teske if (length(dialect) >= 6 && 141*3636c235SDevin Teske substr(dialect, 3, 1) == "_") 142*3636c235SDevin Teske dialect = substr(dialect, 1, 3) ".." \ 143*3636c235SDevin Teske substr(dialect, 6) 144*3636c235SDevin Teske printf "f_dprintf \"dialect=[%%s]\" \"%s\";\n", dialect 145*3636c235SDevin Teske 146*3636c235SDevin Teske # en_US.ISO8859-1 -> en 147*3636c235SDevin Teske lang_abk = lang 148*3636c235SDevin Teske if (length(lang_abk) >= 3 && 149*3636c235SDevin Teske substr(lang_abk, 3, 1) == "_") 150*3636c235SDevin Teske lang_abk = substr(lang_abk, 1, 2) 151*3636c235SDevin Teske printf "f_dprintf \"lang_abk=[%%s]\" \"%s\";\n", 152*3636c235SDevin Teske lang_abk 153*3636c235SDevin Teske } 154*3636c235SDevin Teske function find_token(buffer, token) 155*3636c235SDevin Teske { 156*3636c235SDevin Teske if (split(buffer, tokens, /,/) == 0) return 0 157*3636c235SDevin Teske found = 0 158*3636c235SDevin Teske for (t in tokens) 159*3636c235SDevin Teske if (token == tokens[t]) { found = 1; break } 160*3636c235SDevin Teske return found 161*3636c235SDevin Teske } 162*3636c235SDevin Teske function add_keymap(desc,mark,keym) 163*3636c235SDevin Teske { 164*3636c235SDevin Teske marks[keym] = mark 165*3636c235SDevin Teske name = keym 166*3636c235SDevin Teske gsub(/[^[:alnum:]_]/, "_", name) 167*3636c235SDevin Teske gsub(/'\''/, "'\''\\'\'''\''", desc); 168*3636c235SDevin Teske printf "f_keymap_checkfile %s && " \ 169*3636c235SDevin Teske "f_keymap_register %s '\'%s\'' %s %u\n", 170*3636c235SDevin Teske keym, name, desc, keym, mark 171*3636c235SDevin Teske } 172*3636c235SDevin Teske !/^[[:space:]]*(#|$)/ { 173*3636c235SDevin Teske sub(/^[[:space:]]*/, "", $0) 174*3636c235SDevin Teske keym = $1 175*3636c235SDevin Teske if (keym ~ /^(MENU|FONT)$/) next 176*3636c235SDevin Teske lg = ($2 == "" ? lang_default : $2) 177*3636c235SDevin Teske 178*3636c235SDevin Teske # Match the entry and store the type of match we made 179*3636c235SDevin Teske # as the mark value (so that if we make a better match 180*3636c235SDevin Teske # later on with a higher mark, it overwrites previous) 181*3636c235SDevin Teske 182*3636c235SDevin Teske mark = marks[keym]; 183*3636c235SDevin Teske if (find_token(lg, lang)) 184*3636c235SDevin Teske add_keymap($3, 4, keym) # Best match 185*3636c235SDevin Teske else if (mark <= 3 && find_token(lg, dialect)) 186*3636c235SDevin Teske add_keymap($3, 3, keym) 187*3636c235SDevin Teske else if (mark <= 2 && find_token(lg, lang_abk)) 188*3636c235SDevin Teske add_keymap($3, 2, keym) 189*3636c235SDevin Teske else if (mark <= 1 && find_token(lg, lang_default)) 190*3636c235SDevin Teske add_keymap($3, 1, keym) 191*3636c235SDevin Teske else if (mark <= 0) 192*3636c235SDevin Teske add_keymap($3, 0, keym) 193*3636c235SDevin Teske } 194*3636c235SDevin Teske ' "$DEFAULT_KEYMAP_DIR/INDEX.${DEFAULT_KEYMAP_DIR##*/}" )" 195*3636c235SDevin Teske 196*3636c235SDevin Teske 197*3636c235SDevin Teske # 198*3636c235SDevin Teske # Look for keymaps not in database 199*3636c235SDevin Teske # 200*3636c235SDevin Teske local direntry keym name 201*3636c235SDevin Teske set +f # glob 202*3636c235SDevin Teske for direntry in "$DEFAULT_KEYMAP_DIR"/*; do 203*3636c235SDevin Teske [ "${direntry##*.}" = ".kbd" ] || continue 204*3636c235SDevin Teske keym="${direntry##*/}" 205*3636c235SDevin Teske f_str2varname "$keym" name 206*3636c235SDevin Teske f_struct keymap_$name && continue 207*3636c235SDevin Teske f_keymap_checkfile "$keym" && 208*3636c235SDevin Teske f_keymap_register $name "${keym%.*}" "$keym" 0 209*3636c235SDevin Teske f_dprintf "%s: not in kbdmap(5) database" "$keym" 210*3636c235SDevin Teske done 211*3636c235SDevin Teske 212*3636c235SDevin Teske # 213*3636c235SDevin Teske # Sort the items by their descriptions 214*3636c235SDevin Teske # 215*3636c235SDevin Teske f_dprintf "%s: Sorting keymap entries by description..." $fname 216*3636c235SDevin Teske KEYMAPS=$( 217*3636c235SDevin Teske for k in $KEYMAPS; do 218*3636c235SDevin Teske echo -n "$k " 219*3636c235SDevin Teske # NOTE: Translate '8x8' to '8x08' before sending to 220*3636c235SDevin Teske # sort(1) so that things work out as we might expect. 221*3636c235SDevin Teske debug= keymap_$k get desc | sed -e 's/8x8/8x08/g' 222*3636c235SDevin Teske done | sort -k2 | awk '{ 223*3636c235SDevin Teske printf "%s%s", (started ? " " : ""), $1; started = 1 224*3636c235SDevin Teske }' 225*3636c235SDevin Teske ) 226*3636c235SDevin Teske 227*3636c235SDevin Teske return $SUCCESS 228*3636c235SDevin Teske} 229*3636c235SDevin Teske 230*3636c235SDevin Teske# f_keymap_kbdcontrol $keymap 231*3636c235SDevin Teske# 232*3636c235SDevin Teske# Install keyboard map file from $keymap. 233*3636c235SDevin Teske# 234*3636c235SDevin Teskef_keymap_kbdcontrol() 235*3636c235SDevin Teske{ 236*3636c235SDevin Teske local keymap="$1" 237*3636c235SDevin Teske 238*3636c235SDevin Teske [ "$keymap" ] || return $SUCCESS 239*3636c235SDevin Teske 240*3636c235SDevin Teske # Fixup keymap if it doesn't already contain at least one `/' 241*3636c235SDevin Teske [ "${keymap#*/}" = "$keymap" ] && keymap="$DEFAULT_KEYMAP_DIR/$keymap" 242*3636c235SDevin Teske 243*3636c235SDevin Teske [ "$USE_XDIALOG" ] || kbdcontrol -l "$keymap" 244*3636c235SDevin Teske} 245*3636c235SDevin Teske 246*3636c235SDevin Teske############################################################ MAIN 247*3636c235SDevin Teske 248*3636c235SDevin Teske# 249*3636c235SDevin Teske# Scan for keymaps unless requeted otherwise 250*3636c235SDevin Teske# 251*3636c235SDevin Teskef_dprintf "%s: KEYMAP_SELF_SCAN_ALL=[%s]" keymap.subr "$KEYMAP_SELF_SCAN_ALL" 252*3636c235SDevin Teskecase "$KEYMAP_SELF_SCAN_ALL" in 253*3636c235SDevin Teske""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;; 254*3636c235SDevin Teske*) f_keymap_get_all 255*3636c235SDevin Teskeesac 256*3636c235SDevin Teske 257*3636c235SDevin Teskef_dprintf "%s: Found %u keymap file(s)." keymap.subr \ 258*3636c235SDevin Teske "$( set -- $KEYMAPS; echo $# )" 259*3636c235SDevin Teske 260*3636c235SDevin Teskef_dprintf "%s: Successfully loaded." keymap.subr 261*3636c235SDevin Teske 262*3636c235SDevin Teskefi # ! $_KEYMAP_SUBR 263