1 if [ ! "$_KEYMAP_SUBR" ]; then _KEYMAP_SUBR=1
3 # Copyright (c) 2013-2015 Devin Teske
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
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.
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
29 ############################################################ INCLUDES
31 BSDCFG_SHARE="/usr/share/bsdconfig"
32 . $BSDCFG_SHARE/common.subr || exit 1
33 f_dprintf "%s: loading includes..." keymap.subr
34 f_include $BSDCFG_SHARE/struct.subr
36 ############################################################ CONFIGURATION
39 # Defaults taken from usr.sbin/kbdmap/kbdmap.h
42 case "$( sysctl -n kern.vty )" in
43 vt) : ${DEFAULT_KEYMAP_DIR:=/usr/share/vt/keymaps} ;;
44 *) : ${DEFAULT_KEYMAP_DIR:=/usr/share/syscons/keymaps} ;;
47 ############################################################ GLOBALS
52 # A "keymap" from kbdmap's point of view
53 f_struct_define KEYMAP \
59 # Default behavior is to call f_keymap_get_all() automatically when loaded.
61 : ${KEYMAP_SELF_SCAN_ALL=1}
63 ############################################################ FUNCTIONS
65 # f_keymap_register $name $desc $keym $mark
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).
72 # If not already registered, the keymap is then appended to the KEYMAPS
73 # environment variable, a space-separated list of all registered keymaps.
77 local name="$1" desc="$2" keym="$3" mark="$4"
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"
84 # Scan our global register to see if needs ammending
87 [ "$k" = "$name" ] || continue
90 [ "$found" ] || KEYMAPS="$KEYMAPS $name"
95 # f_keymap_checkfile $keymap
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.
106 # Fixup keymap if it doesn't already contain at least one `/'
107 [ "${keym#*/}" = "$keym" ] && keym="$DEFAULT_KEYMAP_DIR/$keym"
110 [ -f "$keym" -a -r "$keym" ] && return $SUCCESS
111 f_debugging || return $FAILURE
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"
127 # Get all keymap information for kbdmap(5) entries both in the database and
128 # loosely existing in $DEFAULT_KEYMAP_DIR.
132 local fname=f_keymap_get_all
133 local lang="${LC_ALL:-${LC_CTYPE:-${LANG:-$DEFAULT_LANG}}}"
134 [ "$lang" = "C" ] && lang="$DEFAULT_LANG"
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"
140 eval "$( awk -F: -v lang="$lang" -v lang_default="$DEFAULT_LANG" '
142 # en_US.ISO8859-1 -> en_..\.ISO8859-1
144 if (length(dialect) >= 6 &&
145 substr(dialect, 3, 1) == "_")
146 dialect = substr(dialect, 1, 3) ".." \
148 printf "f_dprintf \"dialect=[%%s]\" \"%s\";\n", dialect
150 # en_US.ISO8859-1 -> en
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",
158 function find_token(buffer, token)
160 if (split(buffer, tokens, /,/) == 0) return 0
163 if (token == tokens[t]) { found = 1; break }
166 function add_keymap(desc,mark,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
176 !/^[[:space:]]*(#|$)/ {
177 sub(/^[[:space:]]*/, "", $0)
179 if (keym ~ /^(MENU|FONT)$/) next
180 lg = ($2 == "" ? lang_default : $2)
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)
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)
196 add_keymap($3, 0, keym)
198 ' "$DEFAULT_KEYMAP_DIR/INDEX.${DEFAULT_KEYMAP_DIR##*/}" )"
202 # Look for keymaps not in database
204 local direntry keym name
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"
217 # Sort the items by their descriptions
219 f_dprintf "%s: Sorting keymap entries by description..." $fname
221 for k in $KEYMAPS; do
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
234 # f_keymap_kbdcontrol $keymap
236 # Install keyboard map file from $keymap.
238 f_keymap_kbdcontrol()
242 [ "$keymap" ] || return $SUCCESS
244 # Fixup keymap if it doesn't already contain at least one `/'
245 [ "${keymap#*/}" = "$keymap" ] && keymap="$DEFAULT_KEYMAP_DIR/$keymap"
247 [ "$USE_XDIALOG" ] || kbdcontrol -l "$keymap"
250 ############################################################ MAIN
253 # Scan for keymaps unless requeted otherwise
255 f_dprintf "%s: KEYMAP_SELF_SCAN_ALL=[%s]" keymap.subr "$KEYMAP_SELF_SCAN_ALL"
256 case "$KEYMAP_SELF_SCAN_ALL" in
257 ""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
261 f_count NKEYMAPS $KEYMAPS
262 f_dprintf "%s: Found %u keymap file(s)." keymap.subr $NKEYMAPS
264 f_dprintf "%s: Successfully loaded." keymap.subr