1*97aa5823Smaya /* $NetBSD: wskbdutil.c,v 1.19 2017/11/03 19:20:27 maya Exp $ */
264f1bb73Shannken
364f1bb73Shannken /*-
464f1bb73Shannken * Copyright (c) 1997 The NetBSD Foundation, Inc.
564f1bb73Shannken * All rights reserved.
664f1bb73Shannken *
764f1bb73Shannken * This code is derived from software contributed to The NetBSD Foundation
864f1bb73Shannken * by Juergen Hannken-Illjes.
964f1bb73Shannken *
1064f1bb73Shannken * Redistribution and use in source and binary forms, with or without
1164f1bb73Shannken * modification, are permitted provided that the following conditions
1264f1bb73Shannken * are met:
1364f1bb73Shannken * 1. Redistributions of source code must retain the above copyright
1464f1bb73Shannken * notice, this list of conditions and the following disclaimer.
1564f1bb73Shannken * 2. Redistributions in binary form must reproduce the above copyright
1664f1bb73Shannken * notice, this list of conditions and the following disclaimer in the
1764f1bb73Shannken * documentation and/or other materials provided with the distribution.
1864f1bb73Shannken *
1964f1bb73Shannken * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2064f1bb73Shannken * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2164f1bb73Shannken * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2264f1bb73Shannken * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2364f1bb73Shannken * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2464f1bb73Shannken * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2564f1bb73Shannken * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2664f1bb73Shannken * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2764f1bb73Shannken * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2864f1bb73Shannken * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2964f1bb73Shannken * POSSIBILITY OF SUCH DAMAGE.
3064f1bb73Shannken */
3164f1bb73Shannken
32139747fbSlukem #include <sys/cdefs.h>
33*97aa5823Smaya __KERNEL_RCSID(0, "$NetBSD: wskbdutil.c,v 1.19 2017/11/03 19:20:27 maya Exp $");
34139747fbSlukem
3564f1bb73Shannken #include <sys/param.h>
3664f1bb73Shannken #include <sys/errno.h>
3764f1bb73Shannken #include <sys/systm.h>
3864f1bb73Shannken #include <sys/malloc.h>
3964f1bb73Shannken #include <dev/wscons/wsksymdef.h>
4064f1bb73Shannken #include <dev/wscons/wsksymvar.h>
4164f1bb73Shannken
4264f1bb73Shannken static struct compose_tab_s {
4364f1bb73Shannken keysym_t elem[2];
4464f1bb73Shannken keysym_t result;
4564f1bb73Shannken } compose_tab[] = {
4664f1bb73Shannken { { KS_plus, KS_plus }, KS_numbersign },
4764f1bb73Shannken { { KS_a, KS_a }, KS_at },
4864f1bb73Shannken { { KS_parenleft, KS_parenleft }, KS_bracketleft },
4964f1bb73Shannken { { KS_slash, KS_slash }, KS_backslash },
5064f1bb73Shannken { { KS_parenright, KS_parenright }, KS_bracketright },
5164f1bb73Shannken { { KS_parenleft, KS_minus }, KS_braceleft },
5264f1bb73Shannken { { KS_slash, KS_minus }, KS_bar },
5364f1bb73Shannken { { KS_parenright, KS_minus }, KS_braceright },
5464f1bb73Shannken { { KS_exclam, KS_exclam }, KS_exclamdown },
5564f1bb73Shannken { { KS_c, KS_slash }, KS_cent },
5664f1bb73Shannken { { KS_l, KS_minus }, KS_sterling },
5764f1bb73Shannken { { KS_y, KS_minus }, KS_yen },
5864f1bb73Shannken { { KS_s, KS_o }, KS_section },
5964f1bb73Shannken { { KS_x, KS_o }, KS_currency },
6064f1bb73Shannken { { KS_c, KS_o }, KS_copyright },
6164f1bb73Shannken { { KS_less, KS_less }, KS_guillemotleft },
6264f1bb73Shannken { { KS_greater, KS_greater }, KS_guillemotright },
6364f1bb73Shannken { { KS_question, KS_question }, KS_questiondown },
6464f1bb73Shannken { { KS_dead_acute, KS_space }, KS_acute },
6564f1bb73Shannken { { KS_dead_grave, KS_space }, KS_grave },
6664f1bb73Shannken { { KS_dead_tilde, KS_space }, KS_asciitilde },
6764f1bb73Shannken { { KS_dead_circumflex, KS_space }, KS_asciicircum },
6864f1bb73Shannken { { KS_dead_circumflex, KS_A }, KS_Acircumflex },
6964f1bb73Shannken { { KS_dead_diaeresis, KS_A }, KS_Adiaeresis },
7064f1bb73Shannken { { KS_dead_grave, KS_A }, KS_Agrave },
7164f1bb73Shannken { { KS_dead_abovering, KS_A }, KS_Aring },
7264f1bb73Shannken { { KS_dead_tilde, KS_A }, KS_Atilde },
7364f1bb73Shannken { { KS_dead_cedilla, KS_C }, KS_Ccedilla },
7464f1bb73Shannken { { KS_dead_acute, KS_E }, KS_Eacute },
7564f1bb73Shannken { { KS_dead_circumflex, KS_E }, KS_Ecircumflex },
7664f1bb73Shannken { { KS_dead_diaeresis, KS_E }, KS_Ediaeresis },
7764f1bb73Shannken { { KS_dead_grave, KS_E }, KS_Egrave },
7864f1bb73Shannken { { KS_dead_acute, KS_I }, KS_Iacute },
7964f1bb73Shannken { { KS_dead_circumflex, KS_I }, KS_Icircumflex },
8064f1bb73Shannken { { KS_dead_diaeresis, KS_I }, KS_Idiaeresis },
8164f1bb73Shannken { { KS_dead_grave, KS_I }, KS_Igrave },
8264f1bb73Shannken { { KS_dead_tilde, KS_N }, KS_Ntilde },
8364f1bb73Shannken { { KS_dead_acute, KS_O }, KS_Oacute },
8464f1bb73Shannken { { KS_dead_circumflex, KS_O }, KS_Ocircumflex },
8564f1bb73Shannken { { KS_dead_diaeresis, KS_O }, KS_Odiaeresis },
8664f1bb73Shannken { { KS_dead_grave, KS_O }, KS_Ograve },
8764f1bb73Shannken { { KS_dead_tilde, KS_O }, KS_Otilde },
8864f1bb73Shannken { { KS_dead_acute, KS_U }, KS_Uacute },
8964f1bb73Shannken { { KS_dead_circumflex, KS_U }, KS_Ucircumflex },
9064f1bb73Shannken { { KS_dead_diaeresis, KS_U }, KS_Udiaeresis },
9164f1bb73Shannken { { KS_dead_grave, KS_U }, KS_Ugrave },
9264f1bb73Shannken { { KS_dead_acute, KS_Y }, KS_Yacute },
9364f1bb73Shannken { { KS_dead_acute, KS_a }, KS_aacute },
9464f1bb73Shannken { { KS_dead_circumflex, KS_a }, KS_acircumflex },
9564f1bb73Shannken { { KS_dead_diaeresis, KS_a }, KS_adiaeresis },
9664f1bb73Shannken { { KS_dead_grave, KS_a }, KS_agrave },
9764f1bb73Shannken { { KS_dead_abovering, KS_a }, KS_aring },
9864f1bb73Shannken { { KS_dead_tilde, KS_a }, KS_atilde },
9964f1bb73Shannken { { KS_dead_cedilla, KS_c }, KS_ccedilla },
10064f1bb73Shannken { { KS_dead_acute, KS_e }, KS_eacute },
10164f1bb73Shannken { { KS_dead_circumflex, KS_e }, KS_ecircumflex },
10264f1bb73Shannken { { KS_dead_diaeresis, KS_e }, KS_ediaeresis },
10364f1bb73Shannken { { KS_dead_grave, KS_e }, KS_egrave },
10464f1bb73Shannken { { KS_dead_acute, KS_i }, KS_iacute },
10564f1bb73Shannken { { KS_dead_circumflex, KS_i }, KS_icircumflex },
10664f1bb73Shannken { { KS_dead_diaeresis, KS_i }, KS_idiaeresis },
10764f1bb73Shannken { { KS_dead_grave, KS_i }, KS_igrave },
10864f1bb73Shannken { { KS_dead_tilde, KS_n }, KS_ntilde },
10964f1bb73Shannken { { KS_dead_acute, KS_o }, KS_oacute },
11064f1bb73Shannken { { KS_dead_circumflex, KS_o }, KS_ocircumflex },
11164f1bb73Shannken { { KS_dead_diaeresis, KS_o }, KS_odiaeresis },
11264f1bb73Shannken { { KS_dead_grave, KS_o }, KS_ograve },
11364f1bb73Shannken { { KS_dead_tilde, KS_o }, KS_otilde },
11464f1bb73Shannken { { KS_dead_acute, KS_u }, KS_uacute },
11564f1bb73Shannken { { KS_dead_circumflex, KS_u }, KS_ucircumflex },
11664f1bb73Shannken { { KS_dead_diaeresis, KS_u }, KS_udiaeresis },
11764f1bb73Shannken { { KS_dead_grave, KS_u }, KS_ugrave },
11864f1bb73Shannken { { KS_dead_acute, KS_y }, KS_yacute },
11964f1bb73Shannken { { KS_dead_diaeresis, KS_y }, KS_ydiaeresis },
12064f1bb73Shannken { { KS_quotedbl, KS_A }, KS_Adiaeresis },
12164f1bb73Shannken { { KS_quotedbl, KS_E }, KS_Ediaeresis },
12264f1bb73Shannken { { KS_quotedbl, KS_I }, KS_Idiaeresis },
12364f1bb73Shannken { { KS_quotedbl, KS_O }, KS_Odiaeresis },
12464f1bb73Shannken { { KS_quotedbl, KS_U }, KS_Udiaeresis },
12564f1bb73Shannken { { KS_quotedbl, KS_a }, KS_adiaeresis },
12664f1bb73Shannken { { KS_quotedbl, KS_e }, KS_ediaeresis },
12764f1bb73Shannken { { KS_quotedbl, KS_i }, KS_idiaeresis },
12864f1bb73Shannken { { KS_quotedbl, KS_o }, KS_odiaeresis },
12964f1bb73Shannken { { KS_quotedbl, KS_u }, KS_udiaeresis },
13064f1bb73Shannken { { KS_quotedbl, KS_y }, KS_ydiaeresis },
13164f1bb73Shannken { { KS_acute, KS_A }, KS_Aacute },
13264f1bb73Shannken { { KS_asciicircum, KS_A }, KS_Acircumflex },
13364f1bb73Shannken { { KS_grave, KS_A }, KS_Agrave },
13464f1bb73Shannken { { KS_asterisk, KS_A }, KS_Aring },
13564f1bb73Shannken { { KS_asciitilde, KS_A }, KS_Atilde },
13664f1bb73Shannken { { KS_cedilla, KS_C }, KS_Ccedilla },
13764f1bb73Shannken { { KS_acute, KS_E }, KS_Eacute },
13864f1bb73Shannken { { KS_asciicircum, KS_E }, KS_Ecircumflex },
13964f1bb73Shannken { { KS_grave, KS_E }, KS_Egrave },
14064f1bb73Shannken { { KS_acute, KS_I }, KS_Iacute },
14164f1bb73Shannken { { KS_asciicircum, KS_I }, KS_Icircumflex },
14264f1bb73Shannken { { KS_grave, KS_I }, KS_Igrave },
14364f1bb73Shannken { { KS_asciitilde, KS_N }, KS_Ntilde },
14464f1bb73Shannken { { KS_acute, KS_O }, KS_Oacute },
14564f1bb73Shannken { { KS_asciicircum, KS_O }, KS_Ocircumflex },
14664f1bb73Shannken { { KS_grave, KS_O }, KS_Ograve },
14764f1bb73Shannken { { KS_asciitilde, KS_O }, KS_Otilde },
14864f1bb73Shannken { { KS_acute, KS_U }, KS_Uacute },
14964f1bb73Shannken { { KS_asciicircum, KS_U }, KS_Ucircumflex },
15064f1bb73Shannken { { KS_grave, KS_U }, KS_Ugrave },
15164f1bb73Shannken { { KS_acute, KS_Y }, KS_Yacute },
15264f1bb73Shannken { { KS_acute, KS_a }, KS_aacute },
15364f1bb73Shannken { { KS_asciicircum, KS_a }, KS_acircumflex },
15464f1bb73Shannken { { KS_grave, KS_a }, KS_agrave },
15564f1bb73Shannken { { KS_asterisk, KS_a }, KS_aring },
15664f1bb73Shannken { { KS_asciitilde, KS_a }, KS_atilde },
15764f1bb73Shannken { { KS_cedilla, KS_c }, KS_ccedilla },
15864f1bb73Shannken { { KS_acute, KS_e }, KS_eacute },
15964f1bb73Shannken { { KS_asciicircum, KS_e }, KS_ecircumflex },
16064f1bb73Shannken { { KS_grave, KS_e }, KS_egrave },
16164f1bb73Shannken { { KS_acute, KS_i }, KS_iacute },
16264f1bb73Shannken { { KS_asciicircum, KS_i }, KS_icircumflex },
16364f1bb73Shannken { { KS_grave, KS_i }, KS_igrave },
16464f1bb73Shannken { { KS_asciitilde, KS_n }, KS_ntilde },
16564f1bb73Shannken { { KS_acute, KS_o }, KS_oacute },
16664f1bb73Shannken { { KS_asciicircum, KS_o }, KS_ocircumflex },
16764f1bb73Shannken { { KS_grave, KS_o }, KS_ograve },
16864f1bb73Shannken { { KS_asciitilde, KS_o }, KS_otilde },
16964f1bb73Shannken { { KS_acute, KS_u }, KS_uacute },
17064f1bb73Shannken { { KS_asciicircum, KS_u }, KS_ucircumflex },
17164f1bb73Shannken { { KS_grave, KS_u }, KS_ugrave },
17289bc0d78Schristos { { KS_acute, KS_y }, KS_yacute },
17389bc0d78Schristos { { KS_dead_semi, KS_gr_A }, KS_gr_At },
17489bc0d78Schristos { { KS_dead_semi, KS_gr_E }, KS_gr_Et },
17589bc0d78Schristos { { KS_dead_semi, KS_gr_H }, KS_gr_Ht },
17689bc0d78Schristos { { KS_dead_semi, KS_gr_I }, KS_gr_It },
17789bc0d78Schristos { { KS_dead_semi, KS_gr_O }, KS_gr_Ot },
17889bc0d78Schristos { { KS_dead_semi, KS_gr_Y }, KS_gr_Yt },
17989bc0d78Schristos { { KS_dead_semi, KS_gr_V }, KS_gr_Vt },
18089bc0d78Schristos { { KS_dead_colon, KS_gr_I }, KS_gr_Id },
18189bc0d78Schristos { { KS_dead_colon, KS_gr_Y }, KS_gr_Yd },
18289bc0d78Schristos { { KS_dead_semi, KS_gr_a }, KS_gr_at },
18389bc0d78Schristos { { KS_dead_semi, KS_gr_e }, KS_gr_et },
18489bc0d78Schristos { { KS_dead_semi, KS_gr_h }, KS_gr_ht },
18589bc0d78Schristos { { KS_dead_semi, KS_gr_i }, KS_gr_it },
18689bc0d78Schristos { { KS_dead_semi, KS_gr_o }, KS_gr_ot },
18789bc0d78Schristos { { KS_dead_semi, KS_gr_y }, KS_gr_yt },
18889bc0d78Schristos { { KS_dead_semi, KS_gr_v }, KS_gr_vt },
18989bc0d78Schristos { { KS_dead_colon, KS_gr_i }, KS_gr_id },
190ff12b9feSmkirby { { KS_dead_colon, KS_gr_y }, KS_gr_yd },
191ff12b9feSmkirby
192ff12b9feSmkirby /* Latin 2*/
193ff12b9feSmkirby
194ff12b9feSmkirby { { KS_dead_acute, KS_S }, KS_Sacute },
195ff12b9feSmkirby { { KS_dead_acute, KS_Z }, KS_Zacute },
196ff12b9feSmkirby { { KS_dead_acute, KS_s }, KS_sacute },
197ff12b9feSmkirby { { KS_dead_acute, KS_z }, KS_zacute },
198ff12b9feSmkirby { { KS_dead_acute, KS_R }, KS_Racute },
199ff12b9feSmkirby { { KS_dead_acute, KS_A }, KS_Aacute },
200ff12b9feSmkirby { { KS_dead_acute, KS_L }, KS_Lacute },
201ff12b9feSmkirby { { KS_dead_acute, KS_C }, KS_Cacute },
202ff12b9feSmkirby { { KS_dead_acute, KS_E }, KS_Eacute },
203ff12b9feSmkirby { { KS_dead_acute, KS_I }, KS_Iacute },
204ff12b9feSmkirby { { KS_dead_acute, KS_N }, KS_Nacute },
205ff12b9feSmkirby { { KS_dead_acute, KS_O }, KS_Oacute },
206ff12b9feSmkirby { { KS_dead_acute, KS_U }, KS_Uacute },
207ff12b9feSmkirby { { KS_dead_acute, KS_Y }, KS_Yacute },
208ff12b9feSmkirby { { KS_dead_acute, KS_r }, KS_racute },
209ff12b9feSmkirby { { KS_dead_acute, KS_a }, KS_aacute },
210ff12b9feSmkirby { { KS_dead_acute, KS_l }, KS_lacute },
211ff12b9feSmkirby { { KS_dead_acute, KS_c }, KS_cacute },
212ff12b9feSmkirby { { KS_dead_acute, KS_e }, KS_eacute },
213ff12b9feSmkirby { { KS_dead_acute, KS_i }, KS_iacute },
214ff12b9feSmkirby { { KS_dead_acute, KS_n }, KS_nacute },
215ff12b9feSmkirby { { KS_dead_acute, KS_o }, KS_oacute },
216ff12b9feSmkirby { { KS_dead_acute, KS_u }, KS_uacute },
217ff12b9feSmkirby { { KS_dead_acute, KS_y }, KS_yacute },
218ff12b9feSmkirby { { KS_dead_breve, KS_A }, KS_Abreve },
219ff12b9feSmkirby { { KS_dead_breve, KS_a }, KS_abreve },
220ff12b9feSmkirby { { KS_dead_caron, KS_L }, KS_Lcaron },
221ff12b9feSmkirby { { KS_dead_caron, KS_S }, KS_Scaron },
222ff12b9feSmkirby { { KS_dead_caron, KS_T }, KS_Tcaron },
223ff12b9feSmkirby { { KS_dead_caron, KS_Z }, KS_Zcaron },
224ff12b9feSmkirby { { KS_dead_caron, KS_l }, KS_lcaron },
225ff12b9feSmkirby { { KS_dead_caron, KS_s }, KS_scaron },
226ff12b9feSmkirby { { KS_dead_caron, KS_t }, KS_tcaron },
227ff12b9feSmkirby { { KS_dead_caron, KS_z }, KS_zcaron },
228ff12b9feSmkirby { { KS_dead_caron, KS_C }, KS_Ccaron },
229ff12b9feSmkirby { { KS_dead_caron, KS_E }, KS_Ecaron },
230ff12b9feSmkirby { { KS_dead_caron, KS_D }, KS_Dcaron },
231ff12b9feSmkirby { { KS_dead_caron, KS_N }, KS_Ncaron },
232ff12b9feSmkirby { { KS_dead_caron, KS_R }, KS_Rcaron },
233ff12b9feSmkirby { { KS_dead_caron, KS_c }, KS_ccaron },
234ff12b9feSmkirby { { KS_dead_caron, KS_e }, KS_ecaron },
235ff12b9feSmkirby { { KS_dead_caron, KS_d }, KS_dcaron },
236ff12b9feSmkirby { { KS_dead_caron, KS_n }, KS_ncaron },
237ff12b9feSmkirby { { KS_dead_caron, KS_r }, KS_rcaron },
238ff12b9feSmkirby { { KS_dead_cedilla, KS_S }, KS_Scedilla },
239ff12b9feSmkirby { { KS_dead_cedilla, KS_s }, KS_scedilla },
240ff12b9feSmkirby { { KS_dead_cedilla, KS_C }, KS_Ccedilla },
241ff12b9feSmkirby { { KS_dead_cedilla, KS_T }, KS_Tcedilla },
242ff12b9feSmkirby { { KS_dead_cedilla, KS_c }, KS_ccedilla },
243ff12b9feSmkirby { { KS_dead_cedilla, KS_t }, KS_tcedilla },
244ff12b9feSmkirby { { KS_dead_circumflex, KS_A }, KS_Acircumflex },
245ff12b9feSmkirby { { KS_dead_circumflex, KS_I }, KS_Icircumflex },
246ff12b9feSmkirby { { KS_dead_circumflex, KS_O }, KS_Ocircumflex },
247ff12b9feSmkirby { { KS_dead_circumflex, KS_a }, KS_acircumflex },
248ff12b9feSmkirby { { KS_dead_circumflex, KS_i }, KS_icircumflex },
249ff12b9feSmkirby { { KS_dead_circumflex, KS_o }, KS_ocircumflex },
250ff12b9feSmkirby { { KS_dead_diaeresis, KS_A }, KS_Adiaeresis },
251ff12b9feSmkirby { { KS_dead_diaeresis, KS_E }, KS_Ediaeresis },
252ff12b9feSmkirby { { KS_dead_diaeresis, KS_O }, KS_Odiaeresis },
253ff12b9feSmkirby { { KS_dead_diaeresis, KS_U }, KS_Udiaeresis },
254ff12b9feSmkirby { { KS_dead_diaeresis, KS_a }, KS_adiaeresis },
255ff12b9feSmkirby { { KS_dead_diaeresis, KS_e }, KS_ediaeresis },
256ff12b9feSmkirby { { KS_dead_diaeresis, KS_o }, KS_odiaeresis },
257ff12b9feSmkirby { { KS_dead_diaeresis, KS_u }, KS_udiaeresis },
258f4b5ad99Sdrochner { { KS_dead_dotaccent, KS_Z }, KS_Zabovedot },
259f4b5ad99Sdrochner { { KS_dead_dotaccent, KS_z }, KS_zabovedot },
260f4b5ad99Sdrochner { { KS_dead_hungarumlaut, KS_O }, KS_Odoubleacute },
261f4b5ad99Sdrochner { { KS_dead_hungarumlaut, KS_U }, KS_Udoubleacute },
262f4b5ad99Sdrochner { { KS_dead_hungarumlaut, KS_o }, KS_odoubleacute },
263f4b5ad99Sdrochner { { KS_dead_hungarumlaut, KS_u }, KS_udoubleacute },
264ff12b9feSmkirby { { KS_dead_ogonek, KS_A }, KS_Aogonek },
265ff12b9feSmkirby { { KS_dead_ogonek, KS_a }, KS_aogonek },
266ff12b9feSmkirby { { KS_dead_ogonek, KS_E }, KS_Eogonek },
267f4b5ad99Sdrochner { { KS_dead_ogonek, KS_e }, KS_eogonek },
268f4b5ad99Sdrochner { { KS_dead_abovering, KS_U }, KS_Uabovering },
269f4b5ad99Sdrochner { { KS_dead_abovering, KS_u }, KS_uabovering },
270f4b5ad99Sdrochner { { KS_dead_slash, KS_L }, KS_Lstroke },
271f4b5ad99Sdrochner { { KS_dead_slash, KS_l }, KS_lstroke }
27264f1bb73Shannken };
27364f1bb73Shannken
274*97aa5823Smaya #define COMPOSE_SIZE __arraycount(compose_tab)
27564f1bb73Shannken
27664f1bb73Shannken static int compose_tab_inorder = 0;
27764f1bb73Shannken
27882e5e6abSaugustss static inline int compose_tab_cmp(struct compose_tab_s *, struct compose_tab_s *);
27982e5e6abSaugustss static keysym_t ksym_upcase(keysym_t);
28082e5e6abSaugustss static void fillmapentry(const keysym_t *, int, struct wscons_keymap *);
28164f1bb73Shannken
28264f1bb73Shannken static inline int
compose_tab_cmp(struct compose_tab_s * i,struct compose_tab_s * j)28382e5e6abSaugustss compose_tab_cmp(struct compose_tab_s *i, struct compose_tab_s *j)
28464f1bb73Shannken {
28564f1bb73Shannken if (i->elem[0] == j->elem[0])
28664f1bb73Shannken return(i->elem[1] - j->elem[1]);
28764f1bb73Shannken else
28864f1bb73Shannken return(i->elem[0] - j->elem[0]);
28964f1bb73Shannken }
29064f1bb73Shannken
29164f1bb73Shannken keysym_t
wskbd_compose_value(keysym_t * compose_buf)29282e5e6abSaugustss wskbd_compose_value(keysym_t *compose_buf)
29364f1bb73Shannken {
29464f1bb73Shannken int i, j, r;
29564f1bb73Shannken struct compose_tab_s v;
29664f1bb73Shannken
29764f1bb73Shannken if (! compose_tab_inorder) {
29864f1bb73Shannken /* Insertion sort. */
29964f1bb73Shannken for (i = 1; i < COMPOSE_SIZE; i++) {
30064f1bb73Shannken v = compose_tab[i];
30164f1bb73Shannken /* find correct slot, moving others up */
30264f1bb73Shannken for (j = i; --j >= 0 && compose_tab_cmp(& v, & compose_tab[j]) < 0; )
30364f1bb73Shannken compose_tab[j + 1] = compose_tab[j];
30464f1bb73Shannken compose_tab[j + 1] = v;
30564f1bb73Shannken }
30664f1bb73Shannken compose_tab_inorder = 1;
30764f1bb73Shannken }
30864f1bb73Shannken
30964f1bb73Shannken for (j = 0, i = COMPOSE_SIZE; i != 0; i /= 2) {
31064f1bb73Shannken if (compose_tab[j + i/2].elem[0] == compose_buf[0]) {
31164f1bb73Shannken if (compose_tab[j + i/2].elem[1] == compose_buf[1])
31264f1bb73Shannken return(compose_tab[j + i/2].result);
31364f1bb73Shannken r = compose_tab[j + i/2].elem[1] < compose_buf[1];
31464f1bb73Shannken } else
31564f1bb73Shannken r = compose_tab[j + i/2].elem[0] < compose_buf[0];
31664f1bb73Shannken if (r) {
31764f1bb73Shannken j += i/2 + 1;
31864f1bb73Shannken i--;
31964f1bb73Shannken }
32064f1bb73Shannken }
32164f1bb73Shannken
32264f1bb73Shannken return(KS_voidSymbol);
32364f1bb73Shannken }
32464f1bb73Shannken
32564f1bb73Shannken static const u_char latin1_to_upper[256] = {
32664f1bb73Shannken /* 0 8 1 9 2 a 3 b 4 c 5 d 6 e 7 f */
32764f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */
32864f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */
32964f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */
33064f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */
33164f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 2 */
33264f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 2 */
33364f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */
33464f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */
33564f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */
33664f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */
33764f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */
33864f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */
33964f1bb73Shannken 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 6 */
34064f1bb73Shannken 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 6 */
34164f1bb73Shannken 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 7 */
34264f1bb73Shannken 'X', 'Y', 'Z', 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */
34364f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */
34464f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */
34564f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */
34664f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */
34764f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */
34864f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */
34964f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */
35064f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */
35164f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */
35264f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */
35364f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */
35464f1bb73Shannken 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */
35564f1bb73Shannken 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* e */
35664f1bb73Shannken 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* e */
35764f1bb73Shannken 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, /* f */
35864f1bb73Shannken 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* f */
35964f1bb73Shannken };
36064f1bb73Shannken
36164f1bb73Shannken static keysym_t
ksym_upcase(keysym_t ksym)36282e5e6abSaugustss ksym_upcase(keysym_t ksym)
36364f1bb73Shannken {
36464f1bb73Shannken if (ksym >= KS_f1 && ksym <= KS_f20)
36564f1bb73Shannken return(KS_F1 - KS_f1 + ksym);
36664f1bb73Shannken
36725fb8de0Sdrochner if (KS_GROUP(ksym) == KS_GROUP_Plain && ksym <= 0xff &&
3683cdf7f66Shannken latin1_to_upper[ksym] != 0x00)
3693cdf7f66Shannken return(latin1_to_upper[ksym]);
37064f1bb73Shannken
37164f1bb73Shannken return(ksym);
37264f1bb73Shannken }
37364f1bb73Shannken
374311e3001Shannken static void
fillmapentry(const keysym_t * kp,int len,struct wscons_keymap * mapentry)37582e5e6abSaugustss fillmapentry(const keysym_t *kp, int len, struct wscons_keymap *mapentry)
376311e3001Shannken {
377311e3001Shannken switch (len) {
378311e3001Shannken case 0:
379311e3001Shannken mapentry->group1[0] = KS_voidSymbol;
380311e3001Shannken mapentry->group1[1] = KS_voidSymbol;
381311e3001Shannken mapentry->group2[0] = KS_voidSymbol;
382311e3001Shannken mapentry->group2[1] = KS_voidSymbol;
383311e3001Shannken break;
384311e3001Shannken
385311e3001Shannken case 1:
386311e3001Shannken mapentry->group1[0] = kp[0];
387311e3001Shannken mapentry->group1[1] = ksym_upcase(kp[0]);
388311e3001Shannken mapentry->group2[0] = mapentry->group1[0];
389311e3001Shannken mapentry->group2[1] = mapentry->group1[1];
390311e3001Shannken break;
391311e3001Shannken
392311e3001Shannken case 2:
393311e3001Shannken mapentry->group1[0] = kp[0];
394311e3001Shannken mapentry->group1[1] = kp[1];
395311e3001Shannken mapentry->group2[0] = mapentry->group1[0];
396311e3001Shannken mapentry->group2[1] = mapentry->group1[1];
397311e3001Shannken break;
398311e3001Shannken
399311e3001Shannken case 3:
400311e3001Shannken mapentry->group1[0] = kp[0];
401311e3001Shannken mapentry->group1[1] = kp[1];
402311e3001Shannken mapentry->group2[0] = kp[2];
403311e3001Shannken mapentry->group2[1] = ksym_upcase(kp[2]);
404311e3001Shannken break;
405311e3001Shannken
406311e3001Shannken case 4:
407311e3001Shannken mapentry->group1[0] = kp[0];
408311e3001Shannken mapentry->group1[1] = kp[1];
409311e3001Shannken mapentry->group2[0] = kp[2];
410311e3001Shannken mapentry->group2[1] = kp[3];
411311e3001Shannken break;
412311e3001Shannken
413311e3001Shannken }
414311e3001Shannken }
415311e3001Shannken
416311e3001Shannken void
wskbd_get_mapentry(const struct wskbd_mapdata * mapdata,int kc,struct wscons_keymap * mapentry)41782e5e6abSaugustss wskbd_get_mapentry(const struct wskbd_mapdata *mapdata, int kc,
41882e5e6abSaugustss struct wscons_keymap *mapentry)
419311e3001Shannken {
420311e3001Shannken kbd_t cur;
421311e3001Shannken const keysym_t *kp;
422311e3001Shannken const struct wscons_keydesc *mp;
423ec9b2072Sdrochner int l;
424311e3001Shannken
425311e3001Shannken mapentry->command = KS_voidSymbol;
426311e3001Shannken mapentry->group1[0] = KS_voidSymbol;
427311e3001Shannken mapentry->group1[1] = KS_voidSymbol;
428311e3001Shannken mapentry->group2[0] = KS_voidSymbol;
429311e3001Shannken mapentry->group2[1] = KS_voidSymbol;
430311e3001Shannken
43154e8bcd2Sdrochner for (cur = mapdata->layout & ~KB_HANDLEDBYWSKBD; cur != 0; ) {
432ec9b2072Sdrochner mp = mapdata->keydesc;
433ec9b2072Sdrochner while (mp->map_size > 0) {
434ec9b2072Sdrochner if (mp->name == cur)
435311e3001Shannken break;
436ec9b2072Sdrochner mp++;
437ec9b2072Sdrochner }
438311e3001Shannken
439311e3001Shannken /* If map not found, return */
440ec9b2072Sdrochner if (mp->map_size <= 0)
441311e3001Shannken return;
442311e3001Shannken
443311e3001Shannken for (kp = mp->map; kp < mp->map + mp->map_size; kp++)
444311e3001Shannken if (KS_GROUP(*kp) == KS_GROUP_Keycode &&
445311e3001Shannken KS_VALUE(*kp) == kc) {
446311e3001Shannken /* First skip keycode and possible command */
447311e3001Shannken kp++;
448311e3001Shannken if (KS_GROUP(*kp) == KS_GROUP_Command ||
449311e3001Shannken *kp == KS_Cmd || *kp == KS_Cmd1 || *kp == KS_Cmd2)
450311e3001Shannken mapentry->command = *kp++;
451311e3001Shannken
452311e3001Shannken for (l = 0; kp + l < mp->map + mp->map_size; l++)
453311e3001Shannken if (KS_GROUP(kp[l]) == KS_GROUP_Keycode)
454311e3001Shannken break;
455311e3001Shannken if (l > 4)
456311e3001Shannken panic("wskbd_get_mapentry: %d(%d): bad entry",
457311e3001Shannken mp->name, *kp);
458311e3001Shannken fillmapentry(kp, l, mapentry);
459311e3001Shannken return;
460311e3001Shannken }
461311e3001Shannken
462ec9b2072Sdrochner cur = mp->base;
463311e3001Shannken }
464311e3001Shannken }
465311e3001Shannken
46664f1bb73Shannken void
wskbd_init_keymap(int newlen,struct wscons_keymap ** map,int * maplen)46782e5e6abSaugustss wskbd_init_keymap(int newlen, struct wscons_keymap **map, int *maplen)
46864f1bb73Shannken {
46964f1bb73Shannken int i;
47064f1bb73Shannken
47164f1bb73Shannken if (newlen != *maplen) {
47264f1bb73Shannken if (*maplen > 0)
47364f1bb73Shannken free(*map, M_TEMP);
47464f1bb73Shannken *maplen = newlen;
47564f1bb73Shannken *map = malloc(newlen*sizeof(struct wscons_keymap),
47664f1bb73Shannken M_TEMP, M_WAITOK);
47764f1bb73Shannken }
47864f1bb73Shannken
47964f1bb73Shannken for (i = 0; i < *maplen; i++) {
48064f1bb73Shannken (*map)[i].command = KS_voidSymbol;
48164f1bb73Shannken (*map)[i].group1[0] = KS_voidSymbol;
48264f1bb73Shannken (*map)[i].group1[1] = KS_voidSymbol;
48364f1bb73Shannken (*map)[i].group2[0] = KS_voidSymbol;
48464f1bb73Shannken (*map)[i].group2[1] = KS_voidSymbol;
48564f1bb73Shannken }
48664f1bb73Shannken }
48764f1bb73Shannken
48864f1bb73Shannken int
wskbd_load_keymap(const struct wskbd_mapdata * mapdata,struct wscons_keymap ** map,int * maplen)48982e5e6abSaugustss wskbd_load_keymap(const struct wskbd_mapdata *mapdata,
49082e5e6abSaugustss struct wscons_keymap **map, int *maplen)
49164f1bb73Shannken {
492ec9b2072Sdrochner int i, s, kc, stack_ptr;
49364f1bb73Shannken const keysym_t *kp;
494ec9b2072Sdrochner const struct wscons_keydesc *mp, *stack[10];
49564f1bb73Shannken kbd_t cur;
49664f1bb73Shannken
49754e8bcd2Sdrochner for (cur = mapdata->layout & ~KB_HANDLEDBYWSKBD, stack_ptr = 0;
49854e8bcd2Sdrochner cur != 0; stack_ptr++) {
499ec9b2072Sdrochner mp = mapdata->keydesc;
500ec9b2072Sdrochner while (mp->map_size > 0) {
501ec9b2072Sdrochner if (cur == 0 || mp->name == cur) {
50264f1bb73Shannken break;
50364f1bb73Shannken }
504ec9b2072Sdrochner mp++;
505ec9b2072Sdrochner }
50664f1bb73Shannken
507*97aa5823Smaya if (stack_ptr == __arraycount(stack))
5084ee71fe4Sdrochner panic("wskbd_load_keymap: %d: recursion too deep",
5094ee71fe4Sdrochner mapdata->layout);
510ec9b2072Sdrochner if (mp->map_size <= 0)
51164f1bb73Shannken return(EINVAL);
51264f1bb73Shannken
513ec9b2072Sdrochner stack[stack_ptr] = mp;
514ec9b2072Sdrochner cur = mp->base;
51564f1bb73Shannken }
51664f1bb73Shannken
51764f1bb73Shannken for (i = 0, s = stack_ptr - 1; s >= 0; s--) {
518ec9b2072Sdrochner mp = stack[s];
51964f1bb73Shannken for (kp = mp->map; kp < mp->map + mp->map_size; kp++)
52064f1bb73Shannken if (KS_GROUP(*kp) == KS_GROUP_Keycode && KS_VALUE(*kp) > i)
52164f1bb73Shannken i = KS_VALUE(*kp);
52264f1bb73Shannken }
52364f1bb73Shannken
52464f1bb73Shannken wskbd_init_keymap(i + 1, map, maplen);
52564f1bb73Shannken
52664f1bb73Shannken for (s = stack_ptr - 1; s >= 0; s--) {
527ec9b2072Sdrochner mp = stack[s];
52864f1bb73Shannken for (kp = mp->map; kp < mp->map + mp->map_size; ) {
52964f1bb73Shannken if (KS_GROUP(*kp) != KS_GROUP_Keycode)
53064f1bb73Shannken panic("wskbd_load_keymap: %d(%d): bad entry",
53164f1bb73Shannken mp->name, *kp);
53264f1bb73Shannken
53364f1bb73Shannken kc = KS_VALUE(*kp);
53464f1bb73Shannken kp++;
53564f1bb73Shannken
53664f1bb73Shannken if (KS_GROUP(*kp) == KS_GROUP_Command ||
53764f1bb73Shannken *kp == KS_Cmd || *kp == KS_Cmd1 || *kp == KS_Cmd2) {
53864f1bb73Shannken (*map)[kc].command = *kp;
53964f1bb73Shannken kp++;
54064f1bb73Shannken }
54164f1bb73Shannken
54264f1bb73Shannken for (i = 0; kp + i < mp->map + mp->map_size; i++)
54364f1bb73Shannken if (KS_GROUP(kp[i]) == KS_GROUP_Keycode)
54464f1bb73Shannken break;
54564f1bb73Shannken
54664f1bb73Shannken if (i > 4)
54764f1bb73Shannken panic("wskbd_load_keymap: %d(%d): bad entry",
54864f1bb73Shannken mp->name, *kp);
54964f1bb73Shannken
550311e3001Shannken fillmapentry(kp, i, &(*map)[kc]);
55164f1bb73Shannken kp += i;
55264f1bb73Shannken }
55364f1bb73Shannken }
55464f1bb73Shannken
55564f1bb73Shannken return(0);
55664f1bb73Shannken }
557