xref: /freebsd/usr.sbin/bsdconfig/console/keymap (revision 734e82fe33aa764367791a7d603b383996c6b40b)
1#!/bin/sh
2#-
3# Copyright (c) 2012-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#
28############################################################ INCLUDES
29
30BSDCFG_SHARE="/usr/share/bsdconfig"
31. $BSDCFG_SHARE/common.subr || exit 1
32f_dprintf "%s: loading includes..." "$0"
33f_include $BSDCFG_SHARE/dialog.subr
34f_include $BSDCFG_SHARE/mustberoot.subr
35f_include $BSDCFG_SHARE/sysrc.subr
36
37BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="080.console"
38f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
39
40f_index_menusel_keyword $BSDCFG_LIBE/$APP_DIR/INDEX "$pgm" ipgm &&
41	pgm="${ipgm:-$pgm}"
42
43############################################################ CONFIGURATION
44
45#
46# List of keymap names
47#
48KEYMAP_NAMES="
49	belgian                  brazil_cp850             brazil_iso
50	brazil_iso_accent        bulgarian_bds            bulgarian_phonetic
51	central_european_iso     croatian_iso             czech_iso_accent
52	danish_cp865             danish_iso               estonian_cp850
53	estonian_iso             estonian_iso_15          finnish_cp850
54	finnish_iso              french_iso               french_iso_accent
55	french_iso_macbook       german_cp850             german_iso
56	greek_101                greek_104                greek_elot
57	hungarian_101            hungarian_102            icelandic
58	icelandic_accent         italian                  japanese_106
59	latin_american           latin_american_accent    norway_iso
60	polish_iso               portuguese               portuguese_accent
61	russia_koi8_r            slovak                   slovenian
62	spanish                  spanish_accent           swedish_cp850
63	swedish_iso              swiss_french_cp850       swiss_french_iso
64	swiss_french_iso_accent  swiss_german_cp850       swiss_german_iso
65	swiss_german_iso_accent  uk_cp850                 uk_iso
66	ukrainian_koi8_u         ukrainian_koi8_u_koi8_r  usa_capslock_ctrl
67	usa_dvorak               usa_dvorak_left          usa_dvorak_right
68	usa_emacs                usa_iso                  usa_unix
69" # END-QUOTE
70
71############################################################ FUNCTIONS
72
73# dialog_menu_main
74#
75# Display the dialog(1)-based application main menu.
76#
77dialog_menu_main()
78{
79	local prompt="$msg_keymap_menu_text"
80	local menu_list defaultitem= # Calculated below
81	local hline="$hline_choose_a_keyboard_map"
82
83	#
84	# Export variables for awk(1) ENVIRON visibility
85	#
86	local name
87	for name in $KEYMAP_NAMES; do
88		export msg_$name msg_${name}_desc
89	done
90
91	#
92	# Generate a sorted list of keymaps. If the first letter of the keymap
93	# name is unique (case-insensitive) then it is used as the tag to allow
94	# the user to jump to that entry.
95	#
96	menu_list=$(
97		for name in $KEYMAP_NAMES; do
98			eval echo \"\$msg_$name\" msg_$name
99		done | sort | awk 'BEGIN { prefix = "" }
100		{
101			cur_prefix = tolower(substr(ENVIRON[$NF], 1, 1))
102			printf "'\''"
103			if ( prefix != cur_prefix )
104				prefix = cur_prefix
105			else
106				printf " "
107			printf "%s'\'' '\''%s'\''\n",
108			       ENVIRON[$NF], ENVIRON[$NF"_desc"]
109		}'
110	)
111
112	local height width rows
113	eval f_dialog_menu_size height width rows \
114	                        \"\$DIALOG_TITLE\"     \
115	                        \"\$DIALOG_BACKTITLE\" \
116	                        \"\$prompt\"           \
117	                        \"\$hline\"            \
118	                        $menu_list
119
120	case "$( f_sysrc_get keymap )" in
121	be.iso)                defaultitem="$msg_belgian"                 ;;
122	br275.cp850)           defaultitem="$msg_brazil_cp850"            ;;
123	br275.iso)             defaultitem="$msg_brazil_iso"              ;;
124	br275.iso.acc)         defaultitem="$msg_brazil_iso_accent"       ;;
125	bg.bds.ctrlcaps)       defaultitem="$msg_bulgarian_bds"           ;;
126	bg.phonetic.ctrlcaps)  defaultitem="$msg_bulgarian_phonetic"      ;;
127	ce.iso2)               defaultitem="$msg_central_european_iso"    ;;
128	hr.iso)                defaultitem="$msg_croatian_iso"            ;;
129	cs.latin2.qwertz)      defaultitem="$msg_czech_iso_accent"        ;;
130	danish.cp865)          defaultitem="$msg_danish_cp865"            ;;
131	danish.iso)            defaultitem="$msg_danish_iso"              ;;
132	estonian.cp850)        defaultitem="$msg_estonian_cp850"          ;;
133	estonian.iso)          defaultitem="$msg_estonian_iso"            ;;
134	estonian.iso15)        defaultitem="$msg_estonian_iso_15"         ;;
135	finnish.cp850)         defaultitem="$msg_finnish_cp850"           ;;
136	finnish.iso)           defaultitem="$msg_finnish_iso"             ;;
137	fr.iso)                defaultitem="$msg_french_iso"              ;;
138	fr.iso.acc)            defaultitem="$msg_french_iso_accent"       ;;
139	fr.macbook.acc)        defaultitem="$msg_french_iso_macbook"      ;;
140	german.cp850)          defaultitem="$msg_german_cp850"            ;;
141	german.iso)            defaultitem="$msg_german_iso"              ;;
142	gr.us101.acc)          defaultitem="$msg_greek_101"               ;;
143	el.iso07)              defaultitem="$msg_greek_104"               ;;
144	gr.elot.acc)           defaultitem="$msg_greek_elot"              ;;
145	hu.iso2.101keys)       defaultitem="$msg_hungarian_101"           ;;
146	hu.iso2.102keys)       defaultitem="$msg_hungarian_102"           ;;
147	icelandic.iso)         defaultitem="$msg_icelandic"               ;;
148	icelandic.iso.acc)     defaultitem="$msg_icelandic_accent"        ;;
149	it.iso)                defaultitem="$msg_italian"                 ;;
150	jp.106)                defaultitem="$msg_japanese_106"            ;;
151	latinamerican)         defaultitem="$msg_latin_american"          ;;
152	latinamerican.iso.acc) defaultitem="$msg_latin_american_accent"   ;;
153	norwegian.iso)         defaultitem="$msg_norway_iso"              ;;
154	pl_PL.ISO8859-2)       defaultitem="$msg_polish_iso"              ;;
155	pt.iso)                defaultitem="$msg_portuguese"              ;;
156	pt.iso.acc)            defaultitem="$msg_portuguese_accent"       ;;
157	ru.koi8-r)             defaultitem="$msg_russia_koi8_r"           ;;
158	sk.iso2)               defaultitem="$msg_slovak"                  ;;
159	si.iso)                defaultitem="$msg_slovenian"               ;;
160	spanish.iso)           defaultitem="$msg_spanish"                 ;;
161	spanish.iso.acc)       defaultitem="$msg_spanish_accent"          ;;
162	swedish.cp850)         defaultitem="$msg_swedish_cp850"           ;;
163	swedish.iso)           defaultitem="$msg_swedish_iso"             ;;
164	swissfrench.cp850)     defaultitem="$msg_swiss_french_cp850"      ;;
165	swissfrench.iso)       defaultitem="$msg_swiss_french_iso"        ;;
166	swissfrench.iso.acc)   defaultitem="$msg_swiss_french_iso_accent" ;;
167	swissgerman.cp850)     defaultitem="$msg_swiss_german_cp850"      ;;
168	swissgerman.iso)       defaultitem="$msg_swiss_german_iso"        ;;
169	swissgerman.iso.acc)   defaultitem="$msg_swiss_german_iso_accent" ;;
170	uk.cp850)              defaultitem="$msg_uk_cp850"                ;;
171	uk.iso)                defaultitem="$msg_uk_iso"                  ;;
172	ua.koi8-u)             defaultitem="$msg_ukrainian_koi8_u"        ;;
173	ua.koi8-u.shift.alt)   defaultitem="$msg_ukrainian_koi8_u_koi8_r" ;;
174	us.ctrl)               defaultitem="$msg_usa_capslock_ctrl"       ;;
175	us.pc-ctrl)            defaultitem="$msg_usa_capslock_ctrl"       ;;
176	us.dvorak)             defaultitem="$msg_usa_dvorak"              ;;
177	us.dvorakl)            defaultitem="$msg_usa_dvorak_left"         ;;
178	us.dvorakr)            defaultitem="$msg_usa_dvorak_right"        ;;
179	us.emacs)              defaultitem="$msg_usa_emacs"               ;;
180	us.iso)                defaultitem="$msg_usa_iso"                 ;;
181	us.unix)               defaultitem="$msg_usa_unix"                ;;
182	esac
183
184	# The defaultitem may have to be indented to match the menu_list
185	if [ "$defaultitem" ]; then
186		( eval set -- $menu_list
187		  while [ $# -gt 0 ]; do
188		  	[ "$defaultitem" = "$1" ] && break
189		  	[ " $defaultitem" = "$1" ] && exit 0
190		  	shift 2 # tag/item
191		  done
192		  exit 1 # No modification needed
193		) && defaultitem=" $defaultitem"
194	fi
195
196	local menu_choice
197	menu_choice=$( eval $DIALOG \
198		--title \"\$DIALOG_TITLE\"         \
199		--backtitle \"\$DIALOG_BACKTITLE\" \
200		--hline \"\$hline\"                \
201		--ok-label \"\$msg_ok\"            \
202		--cancel-label \"\$msg_cancel\"    \
203		--default-item \"\$defaultitem\"   \
204		--menu \"\$prompt\"                \
205		$height $width $rows               \
206		$menu_list                         \
207		2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
208	)
209	local retval=$?
210	f_dialog_menutag_store -s "$menu_choice"
211	return $retval
212}
213
214############################################################ MAIN
215
216# Incorporate rc-file if it exists
217[ -f "$HOME/.bsdconfigrc" ] && f_include "$HOME/.bsdconfigrc"
218
219#
220# Process command-line arguments
221#
222while getopts h$GETOPTS_STDARGS flag; do
223	case "$flag" in
224	h|\?) f_usage $BSDCFG_LIBE/$APP_DIR/USAGE "PROGRAM_NAME" "$pgm" ;;
225	esac
226done
227shift $(( $OPTIND - 1 ))
228
229#
230# Initialize
231#
232f_dialog_title "$msg_system_console_keymap"
233f_dialog_backtitle "${ipgm:+bsdconfig }$pgm"
234f_mustberoot_init
235
236#
237# Launch application main menu
238#
239while :; do
240	dialog_menu_main || f_die
241	f_dialog_menutag_fetch mtag
242
243	#
244	# Reverse the users choice into the variable name
245	#
246	keymap_name=
247	mtag="${mtag# }" # remove single leading-space if-present
248	for name in $KEYMAP_NAMES; do
249		debug= f_getvar msg_$name msg
250		[ "$msg" = "$mtag" ] && keymap_name="$name" break
251	done
252
253	[ "$keymap_name" ] || continue
254
255	keymap_to_set=
256	case "$keymap_name" in
257	belgian)                 keymap_to_set="be.iso"                ;;
258	brazil_cp850)            keymap_to_set="br275.cp850"           ;;
259	brazil_iso)              keymap_to_set="br275.iso"             ;;
260	brazil_iso_accent)       keymap_to_set="br275.iso.acc"         ;;
261	bulgarian_bds)           keymap_to_set="bg.bds.ctrlcaps"       ;;
262	bulgarian_phonetic)      keymap_to_set="bg.phonetic.ctrlcaps"  ;;
263	central_european_iso)    keymap_to_set="ce.iso2"               ;;
264	croatian_iso)            keymap_to_set="hr.iso"                ;;
265	czech_iso_accent)        keymap_to_set="cs.latin2.qwertz"      ;;
266	danish_cp865)            keymap_to_set="danish.cp865"          ;;
267	danish_iso)              keymap_to_set="danish.iso"            ;;
268	estonian_cp850)          keymap_to_set="estonian.cp850"        ;;
269	estonian_iso)            keymap_to_set="estonian.iso"          ;;
270	estonian_iso_15)         keymap_to_set="estonian.iso15"        ;;
271	finnish_cp850)           keymap_to_set="finnish.cp850"         ;;
272	finnish_iso)             keymap_to_set="finnish.iso"           ;;
273	french_iso)              keymap_to_set="fr.iso"                ;;
274	french_iso_accent)       keymap_to_set="fr.iso.acc"            ;;
275	french_iso_macbook)      keymap_to_set="fr.macbook.acc"        ;;
276	german_cp850)            keymap_to_set="german.cp850"          ;;
277	german_iso)              keymap_to_set="german.iso"            ;;
278	greek_101)               keymap_to_set="gr.us101.acc"          ;;
279	greek_104)               keymap_to_set="el.iso07"              ;;
280	greek_elot)              keymap_to_set="gr.elot.acc"           ;;
281	hungarian_101)           keymap_to_set="hu.iso2.101keys"       ;;
282	hungarian_102)           keymap_to_set="hu.iso2.102keys"       ;;
283	icelandic)               keymap_to_set="icelandic.iso"         ;;
284	icelandic_accent)        keymap_to_set="icelandic.iso.acc"     ;;
285	italian)                 keymap_to_set="it.iso"                ;;
286	japanese_106)            keymap_to_set="jp.106"                ;;
287	latin_american)          keymap_to_set="latinamerican"         ;;
288	latin_american_accent)   keymap_to_set="latinamerican.iso.acc" ;;
289	norway_iso)              keymap_to_set="norwegian.iso"         ;;
290	polish_iso)              keymap_to_set="pl_PL.ISO8859-2"       ;;
291	portuguese)              keymap_to_set="pt.iso"                ;;
292	portuguese_accent)       keymap_to_set="pt.iso.acc"            ;;
293	russia_koi8_r)           keymap_to_set="ru.koi8-r"             ;;
294	slovak)                  keymap_to_set="sk.iso2"               ;;
295	slovenian)               keymap_to_set="si.iso"                ;;
296	spanish)                 keymap_to_set="spanish.iso"           ;;
297	spanish_accent)          keymap_to_set="spanish.iso.acc"       ;;
298	swedish_cp850)           keymap_to_set="swedish.cp850"         ;;
299	swedish_iso)             keymap_to_set="swedish.iso"           ;;
300	swiss_french_cp850)      keymap_to_set="swissfrench.cp850"     ;;
301	swiss_french_iso)        keymap_to_set="swissfrench.iso"       ;;
302	swiss_french_iso_accent) keymap_to_set="swissfrench.iso.acc"   ;;
303	swiss_german_cp850)      keymap_to_set="swissgerman.cp850"     ;;
304	swiss_german_iso)        keymap_to_set="swissgerman.iso"       ;;
305	swiss_german_iso_accent) keymap_to_set="swissgerman.iso.acc"   ;;
306	uk_cp850)                keymap_to_set="uk.cp850"              ;;
307	uk_iso)                  keymap_to_set="uk.iso"                ;;
308	ukrainian_koi8_u)        keymap_to_set="ua.koi8-u"             ;;
309	ukrainian_koi8_u_koi8_r) keymap_to_set="ua.koi8-u.shift.alt"   ;;
310	usa_capslock_ctrl)
311		case "$( sysctl -n kern.vty )" in
312		vt)              keymap_to_set="us.ctrl"               ;;
313		*)               keymap_to_set="us.pc-ctrl"            ;;
314		esac
315		;;
316	usa_dvorak)              keymap_to_set="us.dvorak"             ;;
317	usa_dvorak_left)         keymap_to_set="us.dvorakl"            ;;
318	usa_dvorak_right)        keymap_to_set="us.dvorakr"            ;;
319	usa_emacs)               keymap_to_set="us.emacs"              ;;
320	usa_iso)                 keymap_to_set="us.iso"                ;;
321	usa_unix)                keymap_to_set="us.unix"               ;;
322	esac
323
324	if [ "$keymap_to_set" ]; then
325		f_eval_catch "$0" f_sysrc_set \
326			'f_sysrc_set keymap "%s"' "$keymap_to_set" || f_die
327		break
328	else
329		f_die 1 "$msg_unknown_keymap"
330	fi
331done
332
333exit $SUCCESS
334
335################################################################################
336# END
337################################################################################
338