1 | /* $NetBSD: wskbdutil.c,v 1.18 2010/02/05 18:26:38 drochner 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.18 2010/02/05 18:26:38 drochner 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 sizeof(compose_tab)/sizeof(compose_tab[0]) |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 == sizeof(stack)/sizeof(stack[0])) |
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 | |