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