xref: /netbsd-src/sys/dev/wscons/wskbdutil.c (revision 97aa58234891da72f1b6c7a1d99a8efc08f44dea)
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