]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/bsdconfig/share/keymap.subr
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / bsdconfig / share / keymap.subr
1 if [ ! "$_KEYMAP_SUBR" ]; then _KEYMAP_SUBR=1
2 #
3 # Copyright (c) 2013 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
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
35
36 ############################################################ CONFIGURATION
37
38 #
39 # Defaults taken from usr.sbin/kbdmap/kbdmap.h
40 #
41 : ${DEFAULT_LANG:=en}
42 : ${DEFAULT_KEYMAP_DIR:=/usr/share/syscons/keymaps}
43
44 ############################################################ GLOBALS
45
46 KEYMAPS=
47
48 # A "keymap" from kbdmap's point of view
49 f_struct_define KEYMAP \
50         desc \
51         keym \
52         mark
53
54 #
55 # Default behavior is to call f_keymap_get_all() automatically when loaded.
56 #
57 : ${KEYMAP_SELF_SCAN_ALL=1}
58
59 ############################################################ FUNCTIONS
60
61 # f_keymap_register $name $desc $keym $mark
62 #
63 # Register a keymap. A `structure' (see struct.subr) is created with the name
64 # keymap_$name (so make sure $name contains only alpha-numeric characters or
65 # the underscore, `_'). The remaining arguments after $name correspond to the
66 # propertise of the `KEYMAP' structure-type (defined above).
67 #
68 # If not already registered, the keymap is then appended to the KEYMAPS
69 # environment variable, a space-separated list of all registered keymaps.
70 #
71 f_keymap_register()
72 {
73         local name="$1" desc="$2" keym="$3" mark="$4"
74
75         f_struct_new KEYMAP "keymap_$name" || return $FAILURE
76         keymap_$name set desc "$desc"
77         keymap_$name set keym "$keym"
78         keymap_$name set mark "$mark"
79
80         # Scan our global register to see if needs ammending
81         local k found=
82         for k in $KEYMAPS; do
83                 [ "$k" = "$name" ] || continue
84                 found=1 && break
85         done
86         [ "$found" ] || KEYMAPS="$KEYMAPS $name"
87
88         return $SUCCESS
89 }
90
91 # f_keymap_checkfile $keymap
92 #
93 # Check that $keymap is a readable kbdmap(5) file. Returns success if $keymap
94 # is a file, is readable, and exists in $DEFAULT_KEYMAP_DIR; otherwise failure.
95 # If debugging is enabled, an appropriate debug error message is printed if
96 # $keymap is not available.
97 #
98 f_keymap_checkfile()
99 {
100         local keym="$1"
101         
102         # Fixup keymap if it doesn't already contain at least one `/'
103         [ "${keym#*/}" = "$keym" ] && keym="$DEFAULT_KEYMAP_DIR/$keym"
104
105         # Short-cuts
106         [ -f "$keym" -a -r "$keym" ] && return $SUCCESS
107         f_debugging || return $FAILURE
108
109         # Print an appropriate debug error message
110         if [ ! -e "$keym" ]; then
111                 f_dprintf "%s: No such file or directory" "$keym"
112         elif [ ! -f "$keym" ]; then
113                 f_dprintf "%s: Not a file!" "$keym"
114         elif [ ! -r "$keym" ]; then
115                 f_dprintf "%s: Permission denied" "$keym"
116         fi
117
118         return $FAILURE
119 }
120
121 # f_keymap_get_all
122 #
123 # Get all keymap information for kbdmap(5) entries both in the database and
124 # loosely existing in $DEFAULT_KEYMAP_DIR.
125 #
126 f_keymap_get_all()
127 {
128         local fname=f_keymap_get_all
129         local lang="${LC_ALL:-${LC_CTYPE:-${LANG:-$DEFAULT_LANG}}}"
130         [ "$lang" = "C" ] && lang="$DEFAULT_LANG"
131
132         f_dprintf "%s: Looking for keymap files..." $fname
133         f_dialog_info "$msg_looking_for_keymap_files"
134         f_dprintf "DEFAULT_LANG=[%s]" "$DEFAULT_LANG"
135
136         eval "$( awk -F: -v lang="$lang" -v lang_default="$DEFAULT_LANG" '
137                 BEGIN {
138                         # en_US.ISO8859-1 -> en_..\.ISO8859-1
139                         dialect = lang
140                         if (length(dialect) >= 6 &&
141                             substr(dialect, 3, 1) == "_")
142                                 dialect = substr(dialect, 1, 3) ".." \
143                                           substr(dialect, 6)
144                         printf "f_dprintf \"dialect=[%%s]\" \"%s\";\n", dialect
145
146                         # en_US.ISO8859-1 -> en
147                         lang_abk = lang
148                         if (length(lang_abk) >= 3 &&
149                             substr(lang_abk, 3, 1) == "_")
150                                 lang_abk = substr(lang_abk, 1, 2)
151                         printf "f_dprintf \"lang_abk=[%%s]\" \"%s\";\n",
152                                lang_abk
153                 }
154                 function find_token(buffer, token)
155                 {
156                         if (split(buffer, tokens, /,/) == 0) return 0
157                         found = 0
158                         for (t in tokens)
159                                 if (token == tokens[t]) { found = 1; break }
160                         return found
161                 }
162                 function add_keymap(desc,mark,keym)
163                 {
164                         marks[keym] = mark
165                         name = keym
166                         gsub(/[^[:alnum:]_]/, "_", name)
167                         gsub(/'\''/, "'\''\\'\'''\''", desc);
168                         printf "f_keymap_checkfile %s && " \
169                                "f_keymap_register %s '\'%s\'' %s %u\n",
170                                keym, name, desc, keym, mark
171                 }
172                 !/^[[:space:]]*(#|$)/ {
173                         sub(/^[[:space:]]*/, "", $0)
174                         keym = $1
175                         if (keym ~ /^(MENU|FONT)$/) next
176                         lg = ($2 == "" ? lang_default : $2)
177
178                         # Match the entry and store the type of match we made
179                         # as the mark value (so that if we make a better match
180                         # later on with a higher mark, it overwrites previous)
181
182                         mark = marks[keym];
183                         if (find_token(lg, lang))
184                                 add_keymap($3, 4, keym) # Best match
185                         else if (mark <= 3 && find_token(lg, dialect))
186                                 add_keymap($3, 3, keym)
187                         else if (mark <= 2 && find_token(lg, lang_abk))
188                                 add_keymap($3, 2, keym)
189                         else if (mark <= 1 && find_token(lg, lang_default))
190                                 add_keymap($3, 1, keym)
191                         else if (mark <= 0)
192                                 add_keymap($3, 0, keym)
193                 }
194         ' "$DEFAULT_KEYMAP_DIR/INDEX.${DEFAULT_KEYMAP_DIR##*/}" )"
195
196
197         #
198         # Look for keymaps not in database
199         #
200         local direntry keym name
201         set +f # glob
202         for direntry in "$DEFAULT_KEYMAP_DIR"/*; do
203                 [ "${direntry##*.}" = ".kbd" ] || continue
204                 keym="${direntry##*/}"
205                 f_str2varname "$keym" name
206                 f_struct keymap_$name && continue
207                 f_keymap_checkfile "$keym" &&
208                         f_keymap_register $name "${keym%.*}" "$keym" 0
209                 f_dprintf "%s: not in kbdmap(5) database" "$keym"
210         done
211
212         #
213         # Sort the items by their descriptions
214         #
215         f_dprintf "%s: Sorting keymap entries by description..." $fname
216         KEYMAPS=$(
217                 for k in $KEYMAPS; do
218                         echo -n "$k "
219                         # NOTE: Translate '8x8' to '8x08' before sending to
220                         # sort(1) so that things work out as we might expect.
221                         debug= keymap_$k get desc | sed -e 's/8x8/8x08/g'
222                 done | sort -k2 | awk '{
223                         printf "%s%s", (started ? " " : ""), $1; started = 1
224                 }'
225         )
226
227         return $SUCCESS
228 }
229
230 # f_keymap_kbdcontrol $keymap
231 #
232 # Install keyboard map file from $keymap.
233 #
234 f_keymap_kbdcontrol()
235 {
236         local keymap="$1"
237
238         [ "$keymap" ] || return $SUCCESS
239
240         # Fixup keymap if it doesn't already contain at least one `/'
241         [ "${keymap#*/}" = "$keymap" ] && keymap="$DEFAULT_KEYMAP_DIR/$keymap"
242
243         [ "$USE_XDIALOG" ] || kbdcontrol -l "$keymap"
244 }
245
246 ############################################################ MAIN
247
248 #
249 # Scan for keymaps unless requeted otherwise
250 #
251 f_dprintf "%s: KEYMAP_SELF_SCAN_ALL=[%s]" keymap.subr "$KEYMAP_SELF_SCAN_ALL"
252 case "$KEYMAP_SELF_SCAN_ALL" in
253 ""|0|[Nn][Oo]|[Oo][Ff][Ff]|[Ff][Aa][Ll][Ss][Ee]) : do nothing ;;
254 *) f_keymap_get_all
255 esac
256
257 f_dprintf "%s: Found %u keymap file(s)." keymap.subr \
258           "$( set -- $KEYMAPS; echo $# )"
259
260 f_dprintf "%s: Successfully loaded." keymap.subr
261
262 fi # ! $_KEYMAP_SUBR