1 /*        $NetBSD: wskbdutil.c,v 1.19 2017/11/03 19:20:27 maya Exp $  */
2 
3 /*-
4  * Copyright (c) 1997 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Juergen Hannken-Illjes.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: wskbdutil.c,v 1.19 2017/11/03 19:20:27 maya Exp $");
34 
35 #include <sys/param.h>
36 #include <sys/errno.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <dev/wscons/wsksymdef.h>
40 #include <dev/wscons/wsksymvar.h>
41 
42 static struct compose_tab_s {
43           keysym_t elem[2];
44           keysym_t result;
45 } compose_tab[] = {
46           { { KS_plus,                            KS_plus },                    KS_numbersign },
47           { { KS_a,                     KS_a },                       KS_at },
48           { { KS_parenleft,             KS_parenleft },               KS_bracketleft },
49           { { KS_slash,                           KS_slash },                   KS_backslash },
50           { { KS_parenright,            KS_parenright },    KS_bracketright },
51           { { KS_parenleft,             KS_minus },                   KS_braceleft },
52           { { KS_slash,                           KS_minus },                   KS_bar },
53           { { KS_parenright,            KS_minus },                   KS_braceright },
54           { { KS_exclam,                          KS_exclam },                  KS_exclamdown },
55           { { KS_c,                     KS_slash },                   KS_cent },
56           { { KS_l,                     KS_minus },                   KS_sterling },
57           { { KS_y,                     KS_minus },                   KS_yen },
58           { { KS_s,                     KS_o },                       KS_section },
59           { { KS_x,                     KS_o },                       KS_currency },
60           { { KS_c,                     KS_o },                       KS_copyright },
61           { { KS_less,                            KS_less },                    KS_guillemotleft },
62           { { KS_greater,                         KS_greater },                 KS_guillemotright },
63           { { KS_question,              KS_question },                KS_questiondown },
64           { { KS_dead_acute,            KS_space },                   KS_acute },
65           { { KS_dead_grave,            KS_space },                   KS_grave },
66           { { KS_dead_tilde,            KS_space },                   KS_asciitilde },
67           { { KS_dead_circumflex,                 KS_space },                   KS_asciicircum },
68           { { KS_dead_circumflex,                 KS_A },                       KS_Acircumflex },
69           { { KS_dead_diaeresis,                  KS_A },                       KS_Adiaeresis },
70           { { KS_dead_grave,            KS_A },                       KS_Agrave },
71           { { KS_dead_abovering,                  KS_A },                       KS_Aring },
72           { { KS_dead_tilde,            KS_A },                       KS_Atilde },
73           { { KS_dead_cedilla,                    KS_C },                       KS_Ccedilla },
74           { { KS_dead_acute,            KS_E },                       KS_Eacute },
75           { { KS_dead_circumflex,                 KS_E },                       KS_Ecircumflex },
76           { { KS_dead_diaeresis,                  KS_E },                       KS_Ediaeresis },
77           { { KS_dead_grave,            KS_E },                       KS_Egrave },
78           { { KS_dead_acute,            KS_I },                       KS_Iacute },
79           { { KS_dead_circumflex,                 KS_I },                       KS_Icircumflex },
80           { { KS_dead_diaeresis,                  KS_I },                       KS_Idiaeresis },
81           { { KS_dead_grave,            KS_I },                       KS_Igrave },
82           { { KS_dead_tilde,            KS_N },                       KS_Ntilde },
83           { { KS_dead_acute,            KS_O },                       KS_Oacute },
84           { { KS_dead_circumflex,                 KS_O },                       KS_Ocircumflex },
85           { { KS_dead_diaeresis,                  KS_O },                       KS_Odiaeresis },
86           { { KS_dead_grave,            KS_O },                       KS_Ograve },
87           { { KS_dead_tilde,            KS_O },                       KS_Otilde },
88           { { KS_dead_acute,            KS_U },                       KS_Uacute },
89           { { KS_dead_circumflex,                 KS_U },                       KS_Ucircumflex },
90           { { KS_dead_diaeresis,                  KS_U },                       KS_Udiaeresis },
91           { { KS_dead_grave,            KS_U },                       KS_Ugrave },
92           { { KS_dead_acute,            KS_Y },                       KS_Yacute },
93           { { KS_dead_acute,            KS_a },                       KS_aacute },
94           { { KS_dead_circumflex,                 KS_a },                       KS_acircumflex },
95           { { KS_dead_diaeresis,                  KS_a },                       KS_adiaeresis },
96           { { KS_dead_grave,            KS_a },                       KS_agrave },
97           { { KS_dead_abovering,                  KS_a },                       KS_aring },
98           { { KS_dead_tilde,            KS_a },                       KS_atilde },
99           { { KS_dead_cedilla,                    KS_c },                       KS_ccedilla },
100           { { KS_dead_acute,            KS_e },                       KS_eacute },
101           { { KS_dead_circumflex,                 KS_e },                       KS_ecircumflex },
102           { { KS_dead_diaeresis,                  KS_e },                       KS_ediaeresis },
103           { { KS_dead_grave,            KS_e },                       KS_egrave },
104           { { KS_dead_acute,            KS_i },                       KS_iacute },
105           { { KS_dead_circumflex,                 KS_i },                       KS_icircumflex },
106           { { KS_dead_diaeresis,                  KS_i },                       KS_idiaeresis },
107           { { KS_dead_grave,            KS_i },                       KS_igrave },
108           { { KS_dead_tilde,            KS_n },                       KS_ntilde },
109           { { KS_dead_acute,            KS_o },                       KS_oacute },
110           { { KS_dead_circumflex,                 KS_o },                       KS_ocircumflex },
111           { { KS_dead_diaeresis,                  KS_o },                       KS_odiaeresis },
112           { { KS_dead_grave,            KS_o },                       KS_ograve },
113           { { KS_dead_tilde,            KS_o },                       KS_otilde },
114           { { KS_dead_acute,            KS_u },                       KS_uacute },
115           { { KS_dead_circumflex,                 KS_u },                       KS_ucircumflex },
116           { { KS_dead_diaeresis,                  KS_u },                       KS_udiaeresis },
117           { { KS_dead_grave,            KS_u },                       KS_ugrave },
118           { { KS_dead_acute,            KS_y },                       KS_yacute },
119           { { KS_dead_diaeresis,                  KS_y },                       KS_ydiaeresis },
120           { { KS_quotedbl,              KS_A },                       KS_Adiaeresis },
121           { { KS_quotedbl,              KS_E },                       KS_Ediaeresis },
122           { { KS_quotedbl,              KS_I },                       KS_Idiaeresis },
123           { { KS_quotedbl,              KS_O },                       KS_Odiaeresis },
124           { { KS_quotedbl,              KS_U },                       KS_Udiaeresis },
125           { { KS_quotedbl,              KS_a },                       KS_adiaeresis },
126           { { KS_quotedbl,              KS_e },                       KS_ediaeresis },
127           { { KS_quotedbl,              KS_i },                       KS_idiaeresis },
128           { { KS_quotedbl,              KS_o },                       KS_odiaeresis },
129           { { KS_quotedbl,              KS_u },                       KS_udiaeresis },
130           { { KS_quotedbl,              KS_y },                       KS_ydiaeresis },
131           { { KS_acute,                           KS_A },                       KS_Aacute },
132           { { KS_asciicircum,           KS_A },                       KS_Acircumflex },
133           { { KS_grave,                           KS_A },                       KS_Agrave },
134           { { KS_asterisk,              KS_A },                       KS_Aring },
135           { { KS_asciitilde,            KS_A },                       KS_Atilde },
136           { { KS_cedilla,                         KS_C },                       KS_Ccedilla },
137           { { KS_acute,                           KS_E },                       KS_Eacute },
138           { { KS_asciicircum,           KS_E },                       KS_Ecircumflex },
139           { { KS_grave,                           KS_E },                       KS_Egrave },
140           { { KS_acute,                           KS_I },                       KS_Iacute },
141           { { KS_asciicircum,           KS_I },                       KS_Icircumflex },
142           { { KS_grave,                           KS_I },                       KS_Igrave },
143           { { KS_asciitilde,            KS_N },                       KS_Ntilde },
144           { { KS_acute,                           KS_O },                       KS_Oacute },
145           { { KS_asciicircum,           KS_O },                       KS_Ocircumflex },
146           { { KS_grave,                           KS_O },                       KS_Ograve },
147           { { KS_asciitilde,            KS_O },                       KS_Otilde },
148           { { KS_acute,                           KS_U },                       KS_Uacute },
149           { { KS_asciicircum,           KS_U },                       KS_Ucircumflex },
150           { { KS_grave,                           KS_U },                       KS_Ugrave },
151           { { KS_acute,                           KS_Y },                       KS_Yacute },
152           { { KS_acute,                           KS_a },                       KS_aacute },
153           { { KS_asciicircum,           KS_a },                       KS_acircumflex },
154           { { KS_grave,                           KS_a },                       KS_agrave },
155           { { KS_asterisk,              KS_a },                       KS_aring },
156           { { KS_asciitilde,            KS_a },                       KS_atilde },
157           { { KS_cedilla,                         KS_c },                       KS_ccedilla },
158           { { KS_acute,                           KS_e },                       KS_eacute },
159           { { KS_asciicircum,           KS_e },                       KS_ecircumflex },
160           { { KS_grave,                           KS_e },                       KS_egrave },
161           { { KS_acute,                           KS_i },                       KS_iacute },
162           { { KS_asciicircum,           KS_i },                       KS_icircumflex },
163           { { KS_grave,                           KS_i },                       KS_igrave },
164           { { KS_asciitilde,            KS_n },                       KS_ntilde },
165           { { KS_acute,                           KS_o },                       KS_oacute },
166           { { KS_asciicircum,           KS_o },                       KS_ocircumflex },
167           { { KS_grave,                           KS_o },                       KS_ograve },
168           { { KS_asciitilde,            KS_o },                       KS_otilde },
169           { { KS_acute,                           KS_u },                       KS_uacute },
170           { { KS_asciicircum,           KS_u },                       KS_ucircumflex },
171           { { KS_grave,                           KS_u },                       KS_ugrave },
172           { { KS_acute,                           KS_y },                       KS_yacute },
173           { { KS_dead_semi,             KS_gr_A },                    KS_gr_At  },
174           { { KS_dead_semi,             KS_gr_E },                    KS_gr_Et  },
175           { { KS_dead_semi,             KS_gr_H },                    KS_gr_Ht  },
176           { { KS_dead_semi,             KS_gr_I },                    KS_gr_It  },
177           { { KS_dead_semi,             KS_gr_O },                    KS_gr_Ot  },
178           { { KS_dead_semi,             KS_gr_Y },                    KS_gr_Yt  },
179           { { KS_dead_semi,             KS_gr_V },                    KS_gr_Vt  },
180           { { KS_dead_colon,            KS_gr_I },                    KS_gr_Id  },
181           { { KS_dead_colon,            KS_gr_Y },                    KS_gr_Yd  },
182           { { KS_dead_semi,             KS_gr_a },                    KS_gr_at  },
183           { { KS_dead_semi,             KS_gr_e },                    KS_gr_et  },
184           { { KS_dead_semi,             KS_gr_h },                    KS_gr_ht  },
185           { { KS_dead_semi,             KS_gr_i },                    KS_gr_it  },
186           { { KS_dead_semi,             KS_gr_o },                    KS_gr_ot  },
187           { { KS_dead_semi,             KS_gr_y },                    KS_gr_yt  },
188           { { KS_dead_semi,             KS_gr_v },                    KS_gr_vt  },
189           { { KS_dead_colon,            KS_gr_i },                    KS_gr_id  },
190           { { KS_dead_colon,            KS_gr_y },                    KS_gr_yd  },
191 
192           /* Latin 2*/
193 
194         { { KS_dead_acute,              KS_S },                       KS_Sacute },
195           { { KS_dead_acute,            KS_Z },                       KS_Zacute },
196           { { KS_dead_acute,            KS_s },                       KS_sacute },
197           { { KS_dead_acute,            KS_z },                       KS_zacute },
198           { { KS_dead_acute,            KS_R },                       KS_Racute },
199           { { KS_dead_acute,            KS_A },                       KS_Aacute },
200           { { KS_dead_acute,            KS_L },                       KS_Lacute },
201           { { KS_dead_acute,            KS_C },                       KS_Cacute },
202           { { KS_dead_acute,            KS_E },                       KS_Eacute },
203           { { KS_dead_acute,            KS_I },                       KS_Iacute },
204           { { KS_dead_acute,            KS_N },                       KS_Nacute },
205           { { KS_dead_acute,            KS_O },                       KS_Oacute },
206           { { KS_dead_acute,            KS_U },                       KS_Uacute },
207           { { KS_dead_acute,            KS_Y },                       KS_Yacute },
208           { { KS_dead_acute,            KS_r },                       KS_racute },
209           { { KS_dead_acute,            KS_a },                       KS_aacute },
210           { { KS_dead_acute,            KS_l },                       KS_lacute },
211           { { KS_dead_acute,            KS_c },                       KS_cacute },
212           { { KS_dead_acute,            KS_e },                       KS_eacute },
213           { { KS_dead_acute,            KS_i },                       KS_iacute },
214           { { KS_dead_acute,            KS_n },                       KS_nacute },
215           { { KS_dead_acute,            KS_o },                       KS_oacute },
216           { { KS_dead_acute,            KS_u },                       KS_uacute },
217           { { KS_dead_acute,            KS_y },                       KS_yacute },
218           { { KS_dead_breve,            KS_A },                       KS_Abreve },
219           { { KS_dead_breve,            KS_a },                       KS_abreve },
220           { { KS_dead_caron,            KS_L },                       KS_Lcaron },
221           { { KS_dead_caron,            KS_S },                       KS_Scaron },
222           { { KS_dead_caron,            KS_T },                       KS_Tcaron },
223           { { KS_dead_caron,            KS_Z },                       KS_Zcaron },
224           { { KS_dead_caron,            KS_l },                       KS_lcaron },
225           { { KS_dead_caron,            KS_s },                       KS_scaron },
226           { { KS_dead_caron,            KS_t },                       KS_tcaron },
227           { { KS_dead_caron,            KS_z },                       KS_zcaron },
228           { { KS_dead_caron,            KS_C },                       KS_Ccaron },
229           { { KS_dead_caron,            KS_E },                       KS_Ecaron },
230           { { KS_dead_caron,            KS_D },                       KS_Dcaron },
231           { { KS_dead_caron,            KS_N },                       KS_Ncaron },
232           { { KS_dead_caron,            KS_R },                       KS_Rcaron },
233           { { KS_dead_caron,            KS_c },                       KS_ccaron },
234           { { KS_dead_caron,            KS_e },                       KS_ecaron },
235           { { KS_dead_caron,            KS_d },                       KS_dcaron },
236           { { KS_dead_caron,            KS_n },                       KS_ncaron },
237           { { KS_dead_caron,            KS_r },                       KS_rcaron },
238           { { KS_dead_cedilla,                    KS_S },                       KS_Scedilla },
239           { { KS_dead_cedilla,                    KS_s },                       KS_scedilla },
240           { { KS_dead_cedilla,                    KS_C },                       KS_Ccedilla },
241           { { KS_dead_cedilla,                    KS_T },                       KS_Tcedilla },
242           { { KS_dead_cedilla,                    KS_c },                       KS_ccedilla },
243           { { KS_dead_cedilla,                    KS_t },                       KS_tcedilla },
244           { { KS_dead_circumflex,                 KS_A },                       KS_Acircumflex },
245           { { KS_dead_circumflex,                 KS_I },                       KS_Icircumflex },
246           { { KS_dead_circumflex,                 KS_O },                       KS_Ocircumflex },
247           { { KS_dead_circumflex,                 KS_a },                       KS_acircumflex },
248           { { KS_dead_circumflex,                 KS_i },                       KS_icircumflex },
249           { { KS_dead_circumflex,                 KS_o },                       KS_ocircumflex },
250           { { KS_dead_diaeresis,                  KS_A },                       KS_Adiaeresis },
251           { { KS_dead_diaeresis,                  KS_E },                       KS_Ediaeresis },
252           { { KS_dead_diaeresis,                  KS_O },                       KS_Odiaeresis },
253           { { KS_dead_diaeresis,                  KS_U },                       KS_Udiaeresis },
254           { { KS_dead_diaeresis,                  KS_a },                       KS_adiaeresis },
255           { { KS_dead_diaeresis,                  KS_e },                       KS_ediaeresis },
256           { { KS_dead_diaeresis,                  KS_o },                       KS_odiaeresis },
257           { { KS_dead_diaeresis,                  KS_u },                       KS_udiaeresis },
258           { { KS_dead_dotaccent,                  KS_Z },                       KS_Zabovedot },
259           { { KS_dead_dotaccent,                  KS_z },                       KS_zabovedot },
260           { { KS_dead_hungarumlaut,     KS_O },                       KS_Odoubleacute },
261           { { KS_dead_hungarumlaut,     KS_U },                       KS_Udoubleacute },
262           { { KS_dead_hungarumlaut,     KS_o },                       KS_odoubleacute },
263           { { KS_dead_hungarumlaut,     KS_u },                       KS_udoubleacute },
264           { { KS_dead_ogonek,           KS_A },                       KS_Aogonek },
265           { { KS_dead_ogonek,           KS_a },                       KS_aogonek },
266           { { KS_dead_ogonek,           KS_E },                       KS_Eogonek },
267           { { KS_dead_ogonek,           KS_e },                       KS_eogonek },
268           { { KS_dead_abovering,                  KS_U },                       KS_Uabovering },
269           { { KS_dead_abovering,                  KS_u },                       KS_uabovering },
270           { { KS_dead_slash,            KS_L },                       KS_Lstroke },
271           { { KS_dead_slash,            KS_l },                       KS_lstroke }
272 };
273 
274 #define COMPOSE_SIZE          __arraycount(compose_tab)
275 
276 static int compose_tab_inorder = 0;
277 
278 static inline int compose_tab_cmp(struct compose_tab_s *, struct compose_tab_s *);
279 static keysym_t ksym_upcase(keysym_t);
280 static void fillmapentry(const keysym_t *, int, struct wscons_keymap *);
281 
282 static inline int
compose_tab_cmp(struct compose_tab_s * i,struct compose_tab_s * j)283 compose_tab_cmp(struct compose_tab_s *i, struct compose_tab_s *j)
284 {
285           if (i->elem[0] == j->elem[0])
286                     return(i->elem[1] - j->elem[1]);
287           else
288                     return(i->elem[0] - j->elem[0]);
289 }
290 
291 keysym_t
wskbd_compose_value(keysym_t * compose_buf)292 wskbd_compose_value(keysym_t *compose_buf)
293 {
294           int i, j, r;
295           struct compose_tab_s v;
296 
297           if (! compose_tab_inorder) {
298                     /* Insertion sort. */
299                     for (i = 1; i < COMPOSE_SIZE; i++) {
300                               v = compose_tab[i];
301                               /* find correct slot, moving others up */
302                               for (j = i; --j >= 0 && compose_tab_cmp(& v, & compose_tab[j]) < 0; )
303                                         compose_tab[j + 1] = compose_tab[j];
304                               compose_tab[j + 1] = v;
305                     }
306                     compose_tab_inorder = 1;
307           }
308 
309           for (j = 0, i = COMPOSE_SIZE; i != 0; i /= 2) {
310                     if (compose_tab[j + i/2].elem[0] == compose_buf[0]) {
311                               if (compose_tab[j + i/2].elem[1] == compose_buf[1])
312                                         return(compose_tab[j + i/2].result);
313                               r = compose_tab[j + i/2].elem[1] < compose_buf[1];
314                     } else
315                               r = compose_tab[j + i/2].elem[0] < compose_buf[0];
316                     if (r) {
317                               j += i/2 + 1;
318                               i--;
319                     }
320           }
321 
322           return(KS_voidSymbol);
323 }
324 
325 static const u_char latin1_to_upper[256] = {
326 /*      0  8  1  9  2  a  3  b  4  c  5  d  6  e  7  f               */
327           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 0 */
328           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 0 */
329           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 1 */
330           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 1 */
331           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 2 */
332           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 2 */
333           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 3 */
334           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 3 */
335           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 4 */
336           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 4 */
337           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 5 */
338           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 5 */
339           0x00,  'A',  'B',  'C',  'D',  'E',  'F',  'G',             /* 6 */
340            'H',  'I',  'J',  'K',  'L',  'M',  'N',  'O',             /* 6 */
341            'P',  'Q',  'R',  'S',  'T',  'U',  'V',  'W',             /* 7 */
342            'X',  'Y',  'Z', 0x00, 0x00, 0x00, 0x00, 0x00,             /* 7 */
343           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 8 */
344           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 8 */
345           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 9 */
346           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* 9 */
347           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* a */
348           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* a */
349           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* b */
350           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* b */
351           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* c */
352           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* c */
353           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* d */
354           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,             /* d */
355           0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,             /* e */
356           0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,             /* e */
357           0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00,             /* f */
358           0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00,             /* f */
359 };
360 
361 static keysym_t
ksym_upcase(keysym_t ksym)362 ksym_upcase(keysym_t ksym)
363 {
364           if (ksym >= KS_f1 && ksym <= KS_f20)
365                     return(KS_F1 - KS_f1 + ksym);
366 
367           if (KS_GROUP(ksym) == KS_GROUP_Plain && ksym <= 0xff &&
368               latin1_to_upper[ksym] != 0x00)
369                     return(latin1_to_upper[ksym]);
370 
371           return(ksym);
372 }
373 
374 static void
fillmapentry(const keysym_t * kp,int len,struct wscons_keymap * mapentry)375 fillmapentry(const keysym_t *kp, int len, struct wscons_keymap *mapentry)
376 {
377           switch (len) {
378           case 0:
379                     mapentry->group1[0] = KS_voidSymbol;
380                     mapentry->group1[1] = KS_voidSymbol;
381                     mapentry->group2[0] = KS_voidSymbol;
382                     mapentry->group2[1] = KS_voidSymbol;
383                     break;
384 
385           case 1:
386                     mapentry->group1[0] = kp[0];
387                     mapentry->group1[1] = ksym_upcase(kp[0]);
388                     mapentry->group2[0] = mapentry->group1[0];
389                     mapentry->group2[1] = mapentry->group1[1];
390                     break;
391 
392           case 2:
393                     mapentry->group1[0] = kp[0];
394                     mapentry->group1[1] = kp[1];
395                     mapentry->group2[0] = mapentry->group1[0];
396                     mapentry->group2[1] = mapentry->group1[1];
397                     break;
398 
399           case 3:
400                     mapentry->group1[0] = kp[0];
401                     mapentry->group1[1] = kp[1];
402                     mapentry->group2[0] = kp[2];
403                     mapentry->group2[1] = ksym_upcase(kp[2]);
404                     break;
405 
406           case 4:
407                     mapentry->group1[0] = kp[0];
408                     mapentry->group1[1] = kp[1];
409                     mapentry->group2[0] = kp[2];
410                     mapentry->group2[1] = kp[3];
411                     break;
412 
413           }
414 }
415 
416 void
wskbd_get_mapentry(const struct wskbd_mapdata * mapdata,int kc,struct wscons_keymap * mapentry)417 wskbd_get_mapentry(const struct wskbd_mapdata *mapdata, int kc,
418           struct wscons_keymap *mapentry)
419 {
420           kbd_t cur;
421           const keysym_t *kp;
422           const struct wscons_keydesc *mp;
423           int l;
424 
425           mapentry->command = KS_voidSymbol;
426           mapentry->group1[0] = KS_voidSymbol;
427           mapentry->group1[1] = KS_voidSymbol;
428           mapentry->group2[0] = KS_voidSymbol;
429           mapentry->group2[1] = KS_voidSymbol;
430 
431           for (cur = mapdata->layout & ~KB_HANDLEDBYWSKBD; cur != 0; ) {
432                     mp = mapdata->keydesc;
433                     while (mp->map_size > 0) {
434                               if (mp->name == cur)
435                                         break;
436                               mp++;
437                     }
438 
439                     /* If map not found, return */
440                     if (mp->map_size <= 0)
441                               return;
442 
443                     for (kp = mp->map; kp < mp->map + mp->map_size; kp++)
444                               if (KS_GROUP(*kp) == KS_GROUP_Keycode &&
445                                   KS_VALUE(*kp) == kc) {
446                                         /* First skip keycode and possible command */
447                                         kp++;
448                                         if (KS_GROUP(*kp) == KS_GROUP_Command ||
449                                             *kp == KS_Cmd || *kp == KS_Cmd1 || *kp == KS_Cmd2)
450                                                   mapentry->command = *kp++;
451 
452                                         for (l = 0; kp + l < mp->map + mp->map_size; l++)
453                                                   if (KS_GROUP(kp[l]) == KS_GROUP_Keycode)
454                                                             break;
455                                         if (l > 4)
456                                                   panic("wskbd_get_mapentry: %d(%d): bad entry",
457                                                         mp->name, *kp);
458                                         fillmapentry(kp, l, mapentry);
459                                         return;
460                               }
461 
462                     cur = mp->base;
463           }
464 }
465 
466 void
wskbd_init_keymap(int newlen,struct wscons_keymap ** map,int * maplen)467 wskbd_init_keymap(int newlen, struct wscons_keymap **map, int *maplen)
468 {
469           int i;
470 
471           if (newlen != *maplen) {
472                     if (*maplen > 0)
473                               free(*map, M_TEMP);
474                     *maplen = newlen;
475                     *map = malloc(newlen*sizeof(struct wscons_keymap),
476                                     M_TEMP, M_WAITOK);
477           }
478 
479           for (i = 0; i < *maplen; i++) {
480                     (*map)[i].command = KS_voidSymbol;
481                     (*map)[i].group1[0] = KS_voidSymbol;
482                     (*map)[i].group1[1] = KS_voidSymbol;
483                     (*map)[i].group2[0] = KS_voidSymbol;
484                     (*map)[i].group2[1] = KS_voidSymbol;
485           }
486 }
487 
488 int
wskbd_load_keymap(const struct wskbd_mapdata * mapdata,struct wscons_keymap ** map,int * maplen)489 wskbd_load_keymap(const struct wskbd_mapdata *mapdata,
490           struct wscons_keymap **map, int *maplen)
491 {
492           int i, s, kc, stack_ptr;
493           const keysym_t *kp;
494           const struct wscons_keydesc *mp, *stack[10];
495           kbd_t cur;
496 
497           for (cur = mapdata->layout & ~KB_HANDLEDBYWSKBD, stack_ptr = 0;
498                cur != 0; stack_ptr++) {
499                     mp = mapdata->keydesc;
500                     while (mp->map_size > 0) {
501                               if (cur == 0 || mp->name == cur) {
502                                         break;
503                               }
504                               mp++;
505                     }
506 
507                     if (stack_ptr == __arraycount(stack))
508                               panic("wskbd_load_keymap: %d: recursion too deep",
509                                     mapdata->layout);
510                     if (mp->map_size <= 0)
511                               return(EINVAL);
512 
513                     stack[stack_ptr] = mp;
514                     cur = mp->base;
515           }
516 
517           for (i = 0, s = stack_ptr - 1; s >= 0; s--) {
518                     mp = stack[s];
519                     for (kp = mp->map; kp < mp->map + mp->map_size; kp++)
520                               if (KS_GROUP(*kp) == KS_GROUP_Keycode && KS_VALUE(*kp) > i)
521                                         i = KS_VALUE(*kp);
522           }
523 
524           wskbd_init_keymap(i + 1, map, maplen);
525 
526           for (s = stack_ptr - 1; s >= 0; s--) {
527                     mp = stack[s];
528                     for (kp = mp->map; kp < mp->map + mp->map_size; ) {
529                               if (KS_GROUP(*kp) != KS_GROUP_Keycode)
530                                         panic("wskbd_load_keymap: %d(%d): bad entry",
531                                               mp->name, *kp);
532 
533                               kc = KS_VALUE(*kp);
534                               kp++;
535 
536                               if (KS_GROUP(*kp) == KS_GROUP_Command ||
537                                   *kp == KS_Cmd || *kp == KS_Cmd1 || *kp == KS_Cmd2) {
538                                         (*map)[kc].command = *kp;
539                                         kp++;
540                               }
541 
542                               for (i = 0; kp + i < mp->map + mp->map_size; i++)
543                                         if (KS_GROUP(kp[i]) == KS_GROUP_Keycode)
544                                                   break;
545 
546                               if (i > 4)
547                                         panic("wskbd_load_keymap: %d(%d): bad entry",
548                                               mp->name, *kp);
549 
550                               fillmapentry(kp, i, &(*map)[kc]);
551                               kp += i;
552                     }
553           }
554 
555           return(0);
556 }
557