2 * Copyright (c) 1997 The NetBSD Foundation, Inc.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Juergen Hannken-Illjes.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #include <sys/cdefs.h>
33 #include <sys/errno.h>
37 #include <wiikeyboard/wsksymdef.h>
39 #include "wsksymvar.h"
41 static struct compose_tab_s
{
45 { { KS_plus
, KS_plus
}, KS_numbersign
},
46 { { KS_a
, KS_a
}, KS_at
},
47 { { KS_parenleft
, KS_parenleft
}, KS_bracketleft
},
48 { { KS_slash
, KS_slash
}, KS_backslash
},
49 { { KS_parenright
, KS_parenright
}, KS_bracketright
},
50 { { KS_parenleft
, KS_minus
}, KS_braceleft
},
51 { { KS_slash
, KS_minus
}, KS_bar
},
52 { { KS_parenright
, KS_minus
}, KS_braceright
},
53 { { KS_exclam
, KS_exclam
}, KS_exclamdown
},
54 { { KS_c
, KS_slash
}, KS_cent
},
55 { { KS_l
, KS_minus
}, KS_sterling
},
56 { { KS_y
, KS_minus
}, KS_yen
},
57 { { KS_s
, KS_o
}, KS_section
},
58 { { KS_x
, KS_o
}, KS_currency
},
59 { { KS_c
, KS_o
}, KS_copyright
},
60 { { KS_less
, KS_less
}, KS_guillemotleft
},
61 { { KS_greater
, KS_greater
}, KS_guillemotright
},
62 { { KS_question
, KS_question
}, KS_questiondown
},
63 { { KS_dead_acute
, KS_space
}, KS_apostrophe
},
64 { { KS_dead_grave
, KS_space
}, KS_grave
},
65 { { KS_dead_tilde
, KS_space
}, KS_asciitilde
},
66 { { KS_dead_circumflex
, KS_space
}, KS_asciicircum
},
67 { { KS_dead_diaeresis
, KS_space
}, KS_quotedbl
},
68 { { KS_dead_cedilla
, KS_space
}, KS_comma
},
69 { { KS_dead_circumflex
, KS_A
}, KS_Acircumflex
},
70 { { KS_dead_diaeresis
, KS_A
}, KS_Adiaeresis
},
71 { { KS_dead_grave
, KS_A
}, KS_Agrave
},
72 { { KS_dead_abovering
, KS_A
}, KS_Aring
},
73 { { KS_dead_tilde
, KS_A
}, KS_Atilde
},
74 { { KS_dead_cedilla
, KS_C
}, KS_Ccedilla
},
75 { { KS_dead_acute
, KS_E
}, KS_Eacute
},
76 { { KS_dead_circumflex
, KS_E
}, KS_Ecircumflex
},
77 { { KS_dead_diaeresis
, KS_E
}, KS_Ediaeresis
},
78 { { KS_dead_grave
, KS_E
}, KS_Egrave
},
79 { { KS_dead_acute
, KS_I
}, KS_Iacute
},
80 { { KS_dead_circumflex
, KS_I
}, KS_Icircumflex
},
81 { { KS_dead_diaeresis
, KS_I
}, KS_Idiaeresis
},
82 { { KS_dead_grave
, KS_I
}, KS_Igrave
},
83 { { KS_dead_tilde
, KS_N
}, KS_Ntilde
},
84 { { KS_dead_acute
, KS_O
}, KS_Oacute
},
85 { { KS_dead_circumflex
, KS_O
}, KS_Ocircumflex
},
86 { { KS_dead_diaeresis
, KS_O
}, KS_Odiaeresis
},
87 { { KS_dead_grave
, KS_O
}, KS_Ograve
},
88 { { KS_dead_tilde
, KS_O
}, KS_Otilde
},
89 { { KS_dead_acute
, KS_U
}, KS_Uacute
},
90 { { KS_dead_circumflex
, KS_U
}, KS_Ucircumflex
},
91 { { KS_dead_diaeresis
, KS_U
}, KS_Udiaeresis
},
92 { { KS_dead_grave
, KS_U
}, KS_Ugrave
},
93 { { KS_dead_acute
, KS_Y
}, KS_Yacute
},
94 { { KS_dead_acute
, KS_a
}, KS_aacute
},
95 { { KS_dead_circumflex
, KS_a
}, KS_acircumflex
},
96 { { KS_dead_diaeresis
, KS_a
}, KS_adiaeresis
},
97 { { KS_dead_grave
, KS_a
}, KS_agrave
},
98 { { KS_dead_abovering
, KS_a
}, KS_aring
},
99 { { KS_dead_tilde
, KS_a
}, KS_atilde
},
100 { { KS_dead_cedilla
, KS_c
}, KS_ccedilla
},
101 { { KS_dead_acute
, KS_e
}, KS_eacute
},
102 { { KS_dead_circumflex
, KS_e
}, KS_ecircumflex
},
103 { { KS_dead_diaeresis
, KS_e
}, KS_ediaeresis
},
104 { { KS_dead_grave
, KS_e
}, KS_egrave
},
105 { { KS_dead_acute
, KS_i
}, KS_iacute
},
106 { { KS_dead_circumflex
, KS_i
}, KS_icircumflex
},
107 { { KS_dead_diaeresis
, KS_i
}, KS_idiaeresis
},
108 { { KS_dead_grave
, KS_i
}, KS_igrave
},
109 { { KS_dead_tilde
, KS_n
}, KS_ntilde
},
110 { { KS_dead_acute
, KS_o
}, KS_oacute
},
111 { { KS_dead_circumflex
, KS_o
}, KS_ocircumflex
},
112 { { KS_dead_diaeresis
, KS_o
}, KS_odiaeresis
},
113 { { KS_dead_grave
, KS_o
}, KS_ograve
},
114 { { KS_dead_tilde
, KS_o
}, KS_otilde
},
115 { { KS_dead_acute
, KS_u
}, KS_uacute
},
116 { { KS_dead_circumflex
, KS_u
}, KS_ucircumflex
},
117 { { KS_dead_diaeresis
, KS_u
}, KS_udiaeresis
},
118 { { KS_dead_grave
, KS_u
}, KS_ugrave
},
119 { { KS_dead_acute
, KS_y
}, KS_yacute
},
120 { { KS_dead_diaeresis
, KS_y
}, KS_ydiaeresis
},
121 { { KS_quotedbl
, KS_A
}, KS_Adiaeresis
},
122 { { KS_quotedbl
, KS_E
}, KS_Ediaeresis
},
123 { { KS_quotedbl
, KS_I
}, KS_Idiaeresis
},
124 { { KS_quotedbl
, KS_O
}, KS_Odiaeresis
},
125 { { KS_quotedbl
, KS_U
}, KS_Udiaeresis
},
126 { { KS_quotedbl
, KS_a
}, KS_adiaeresis
},
127 { { KS_quotedbl
, KS_e
}, KS_ediaeresis
},
128 { { KS_quotedbl
, KS_i
}, KS_idiaeresis
},
129 { { KS_quotedbl
, KS_o
}, KS_odiaeresis
},
130 { { KS_quotedbl
, KS_u
}, KS_udiaeresis
},
131 { { KS_quotedbl
, KS_y
}, KS_ydiaeresis
},
132 { { KS_acute
, KS_A
}, KS_Aacute
},
133 { { KS_asciicircum
, KS_A
}, KS_Acircumflex
},
134 { { KS_grave
, KS_A
}, KS_Agrave
},
135 { { KS_asterisk
, KS_A
}, KS_Aring
},
136 { { KS_asciitilde
, KS_A
}, KS_Atilde
},
137 { { KS_cedilla
, KS_C
}, KS_Ccedilla
},
138 { { KS_acute
, KS_E
}, KS_Eacute
},
139 { { KS_asciicircum
, KS_E
}, KS_Ecircumflex
},
140 { { KS_grave
, KS_E
}, KS_Egrave
},
141 { { KS_acute
, KS_I
}, KS_Iacute
},
142 { { KS_asciicircum
, KS_I
}, KS_Icircumflex
},
143 { { KS_grave
, KS_I
}, KS_Igrave
},
144 { { KS_asciitilde
, KS_N
}, KS_Ntilde
},
145 { { KS_acute
, KS_O
}, KS_Oacute
},
146 { { KS_asciicircum
, KS_O
}, KS_Ocircumflex
},
147 { { KS_grave
, KS_O
}, KS_Ograve
},
148 { { KS_asciitilde
, KS_O
}, KS_Otilde
},
149 { { KS_acute
, KS_U
}, KS_Uacute
},
150 { { KS_asciicircum
, KS_U
}, KS_Ucircumflex
},
151 { { KS_grave
, KS_U
}, KS_Ugrave
},
152 { { KS_acute
, KS_Y
}, KS_Yacute
},
153 { { KS_acute
, KS_a
}, KS_aacute
},
154 { { KS_asciicircum
, KS_a
}, KS_acircumflex
},
155 { { KS_grave
, KS_a
}, KS_agrave
},
156 { { KS_asterisk
, KS_a
}, KS_aring
},
157 { { KS_asciitilde
, KS_a
}, KS_atilde
},
158 { { KS_cedilla
, KS_c
}, KS_ccedilla
},
159 { { KS_acute
, KS_e
}, KS_eacute
},
160 { { KS_asciicircum
, KS_e
}, KS_ecircumflex
},
161 { { KS_grave
, KS_e
}, KS_egrave
},
162 { { KS_acute
, KS_i
}, KS_iacute
},
163 { { KS_asciicircum
, KS_i
}, KS_icircumflex
},
164 { { KS_grave
, KS_i
}, KS_igrave
},
165 { { KS_asciitilde
, KS_n
}, KS_ntilde
},
166 { { KS_acute
, KS_o
}, KS_oacute
},
167 { { KS_asciicircum
, KS_o
}, KS_ocircumflex
},
168 { { KS_grave
, KS_o
}, KS_ograve
},
169 { { KS_asciitilde
, KS_o
}, KS_otilde
},
170 { { KS_acute
, KS_u
}, KS_uacute
},
171 { { KS_asciicircum
, KS_u
}, KS_ucircumflex
},
172 { { KS_grave
, KS_u
}, KS_ugrave
},
173 { { KS_acute
, KS_y
}, KS_yacute
}
176 #define COMPOSE_SIZE sizeof(compose_tab)/sizeof(compose_tab[0])
178 static int compose_tab_inorder
= 0;
180 inline int compose_tab_cmp(struct compose_tab_s
*,
181 struct compose_tab_s
*);
182 keysym_t
ksym_upcase(keysym_t
);
183 void fillmapentry(const keysym_t
*, int, struct wscons_keymap
*);
186 compose_tab_cmp(i
, j
)
187 struct compose_tab_s
*i
, *j
;
189 if (i
->elem
[0] == j
->elem
[0])
190 return(i
->elem
[1] - j
->elem
[1]);
192 return(i
->elem
[0] - j
->elem
[0]);
196 wskbd_compose_value(compose_buf
)
197 keysym_t
*compose_buf
;
200 struct compose_tab_s v
;
202 if (! compose_tab_inorder
) {
203 /* Insertion sort. */
204 for (i
= 1; i
< COMPOSE_SIZE
; i
++) {
206 /* find correct slot, moving others up */
207 for (j
= i
; --j
>= 0 && compose_tab_cmp(& v
, & compose_tab
[j
]) < 0; )
208 compose_tab
[j
+ 1] = compose_tab
[j
];
209 compose_tab
[j
+ 1] = v
;
211 compose_tab_inorder
= 1;
214 for (j
= 0, i
= COMPOSE_SIZE
; i
!= 0; i
/= 2) {
215 if (compose_tab
[j
+ i
/2].elem
[0] == compose_buf
[0]) {
216 if (compose_tab
[j
+ i
/2].elem
[1] == compose_buf
[1])
217 return(compose_tab
[j
+ i
/2].result
);
218 r
= compose_tab
[j
+ i
/2].elem
[1] < compose_buf
[1];
220 r
= compose_tab
[j
+ i
/2].elem
[0] < compose_buf
[0];
227 return(KS_voidSymbol
);
230 static const u_char latin1_to_upper
[256] = {
231 /* 0 8 1 9 2 a 3 b 4 c 5 d 6 e 7 f */
232 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */
233 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0 */
234 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */
235 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1 */
236 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 2 */
237 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 2 */
238 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */
239 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3 */
240 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */
241 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 4 */
242 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */
243 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 5 */
244 0x00, 'A', 'B', 'C', 'D', 'E', 'F', 'G', /* 6 */
245 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', /* 6 */
246 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 7 */
247 'X', 'Y', 'Z', 0x00, 0x00, 0x00, 0x00, 0x00, /* 7 */
248 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */
249 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8 */
250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */
251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9 */
252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */
253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a */
254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */
255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b */
256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */
257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c */
258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d */
260 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, /* e */
261 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /* e */
262 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0x00, /* f */
263 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0x00, /* f */
270 if (ksym
>= KS_f1
&& ksym
<= KS_f20
)
271 return(KS_F1
- KS_f1
+ ksym
);
273 if (KS_GROUP(ksym
) == KS_GROUP_Ascii
&& ksym
<= 0xff &&
274 latin1_to_upper
[ksym
] != 0x00)
275 return(latin1_to_upper
[ksym
]);
281 fillmapentry(kp
, len
, mapentry
)
284 struct wscons_keymap
*mapentry
;
288 mapentry
->group1
[0] = KS_voidSymbol
;
289 mapentry
->group1
[1] = KS_voidSymbol
;
290 mapentry
->group2
[0] = KS_voidSymbol
;
291 mapentry
->group2
[1] = KS_voidSymbol
;
295 mapentry
->group1
[0] = kp
[0];
296 mapentry
->group1
[1] = ksym_upcase(kp
[0]);
297 mapentry
->group2
[0] = mapentry
->group1
[0];
298 mapentry
->group2
[1] = mapentry
->group1
[1];
302 mapentry
->group1
[0] = kp
[0];
303 mapentry
->group1
[1] = kp
[1];
304 mapentry
->group2
[0] = mapentry
->group1
[0];
305 mapentry
->group2
[1] = mapentry
->group1
[1];
309 mapentry
->group1
[0] = kp
[0];
310 mapentry
->group1
[1] = kp
[1];
311 mapentry
->group2
[0] = kp
[2];
312 mapentry
->group2
[1] = ksym_upcase(kp
[2]);
316 mapentry
->group1
[0] = kp
[0];
317 mapentry
->group1
[1] = kp
[1];
318 mapentry
->group2
[0] = kp
[2];
319 mapentry
->group2
[1] = kp
[3];
326 wskbd_get_mapentry(mapdata
, kc
, mapentry
)
327 const struct wskbd_mapdata
*mapdata
;
329 struct wscons_keymap
*mapentry
;
333 const struct wscons_keydesc
*mp
;
337 mapentry
->command
= KS_voidSymbol
;
338 mapentry
->group1
[0] = KS_voidSymbol
;
339 mapentry
->group1
[1] = KS_voidSymbol
;
340 mapentry
->group2
[0] = KS_voidSymbol
;
341 mapentry
->group2
[1] = KS_voidSymbol
;
343 for (cur
= mapdata
->layout
& ~KB_HANDLEDBYWSKBD
; cur
!= 0; ) {
344 mp
= mapdata
->keydesc
;
345 while (mp
->map_size
> 0) {
351 /* If map not found, return */
352 if (mp
->map_size
<= 0)
355 for (kp
= mp
->map
; kp
< mp
->map
+ mp
->map_size
; kp
++) {
357 if (ksg
== KS_GROUP_Keycode
&&
358 KS_VALUE(*kp
) == kc
) {
359 /* First skip keycode and possible command */
361 if (KS_GROUP(*kp
) == KS_GROUP_Command
||
362 *kp
== KS_Cmd
|| *kp
== KS_Cmd1
|| *kp
== KS_Cmd2
)
363 mapentry
->command
= *kp
++;
365 for (l
= 0; kp
+ l
< mp
->map
+ mp
->map_size
;
367 ksg
= KS_GROUP(kp
[l
]);
368 if (ksg
== KS_GROUP_Keycode
)
372 fprintf(stderr
, "wskbd_get_mapentry: %d(%d): bad entry",
376 fillmapentry(kp
, l
, mapentry
);
386 wskbd_init_keymap(newlen
, map
, maplen
)
388 struct wscons_keymap
**map
;
393 if (newlen
!= *maplen
) {
397 *map
= malloc(newlen
*sizeof(struct wscons_keymap
));
400 for (i
= 0; i
< *maplen
; i
++) {
401 (*map
)[i
].command
= KS_voidSymbol
;
402 (*map
)[i
].group1
[0] = KS_voidSymbol
;
403 (*map
)[i
].group1
[1] = KS_voidSymbol
;
404 (*map
)[i
].group2
[0] = KS_voidSymbol
;
405 (*map
)[i
].group2
[1] = KS_voidSymbol
;
410 wskbd_load_keymap(mapdata
, map
, maplen
)
411 const struct wskbd_mapdata
*mapdata
;
412 struct wscons_keymap
**map
;
415 int i
, s
, kc
, stack_ptr
;
417 const struct wscons_keydesc
*mp
, *stack
[10];
421 for (cur
= mapdata
->layout
& ~KB_HANDLEDBYWSKBD
, stack_ptr
= 0;
422 cur
!= 0; stack_ptr
++) {
423 mp
= mapdata
->keydesc
;
424 while (mp
->map_size
> 0) {
425 if (cur
== 0 || mp
->name
== cur
) {
431 if (stack_ptr
== sizeof(stack
)/sizeof(stack
[0])) {
432 fprintf(stderr
, "wskbd_load_keymap: %d: recursion too deep",
437 if (mp
->map_size
<= 0)
440 stack
[stack_ptr
] = mp
;
444 for (i
= 0, s
= stack_ptr
- 1; s
>= 0; s
--) {
446 for (kp
= mp
->map
; kp
< mp
->map
+ mp
->map_size
; kp
++) {
448 if (ksg
== KS_GROUP_Keycode
&& KS_VALUE(*kp
) > i
)
453 wskbd_init_keymap(i
+ 1, map
, maplen
);
455 for (s
= stack_ptr
- 1; s
>= 0; s
--) {
457 for (kp
= mp
->map
; kp
< mp
->map
+ mp
->map_size
; ) {
459 if (ksg
!= KS_GROUP_Keycode
) {
460 fprintf(stderr
, "wskbd_load_keymap: %d(%d): bad entry",
468 if (KS_GROUP(*kp
) == KS_GROUP_Command
||
469 *kp
== KS_Cmd
|| *kp
== KS_Cmd1
|| *kp
== KS_Cmd2
) {
470 (*map
)[kc
].command
= *kp
;
474 for (i
= 0; kp
+ i
< mp
->map
+ mp
->map_size
; i
++) {
475 ksg
= KS_GROUP(kp
[i
]);
476 if (ksg
== KS_GROUP_Keycode
)
481 fprintf(stderr
, "wskbd_load_keymap: %d(%d): bad entry",
486 fillmapentry(kp
, i
, &(*map
)[kc
]);