makekeys: replace helper with python script and binary search
[platform/upstream/libxkbcommon.git] / src / keysym.c
1 /*
2  * Copyright 1985, 1987, 1990, 1998  The Open Group
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
18  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20  *
21  * Except as contained in this notice, the names of the authors or their
22  * institutions shall not be used in advertising or otherwise to promote the
23  * sale, use or other dealings in this Software without prior written
24  * authorization from the authors.
25  */
26
27 /*
28  * Copyright © 2009 Dan Nicholson
29  *
30  * Permission is hereby granted, free of charge, to any person obtaining a
31  * copy of this software and associated documentation files (the "Software"),
32  * to deal in the Software without restriction, including without limitation
33  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
34  * and/or sell copies of the Software, and to permit persons to whom the
35  * Software is furnished to do so, subject to the following conditions:
36  *
37  * The above copyright notice and this permission notice (including the next
38  * paragraph) shall be included in all copies or substantial portions of the
39  * Software.
40  *
41  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
44  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
46  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
47  * DEALINGS IN THE SOFTWARE.
48  */
49
50 #include <stdlib.h>
51 #include "xkbcommon/xkbcommon.h"
52 #include "utils.h"
53 #include "keysym.h"
54 #include "ks_tables.h"
55
56 static int
57 compare_by_keysym(const void *a, const void *b)
58 {
59     const struct name_keysym *key = a, *entry = b;
60     return key->keysym - (int32_t)entry->keysym;
61 }
62
63 static int
64 compare_by_name(const void *a, const void *b)
65 {
66     const struct name_keysym *key = a, *entry = b;
67     return strcmp(key->name, entry->name);
68 }
69
70 XKB_EXPORT int
71 xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
72 {
73     const struct name_keysym search = { .name = NULL, .keysym = ks };
74     const struct name_keysym *entry;
75
76     if ((ks & ((unsigned long) ~0x1fffffff)) != 0) {
77         snprintf(buffer, size, "Invalid");
78         return -1;
79     }
80
81     entry = bsearch(&search, keysym_to_name,
82                     sizeof(keysym_to_name) / sizeof(*keysym_to_name),
83                     sizeof(*keysym_to_name),
84                     compare_by_keysym);
85     if (entry)
86         return snprintf(buffer, size, "%s", entry->name);
87
88     if (ks >= 0x01000100 && ks <= 0x0110ffff)
89         /* Unnamed Unicode codepoint. */
90         return snprintf(buffer, size, "U%lx", ks & 0xffffffUL);
91
92     /* Unnamed, non-Unicode, symbol (shouldn't generally happen). */
93     return snprintf(buffer, size, "0x%08x", ks);
94 }
95
96 XKB_EXPORT xkb_keysym_t
97 xkb_keysym_from_name(const char *s)
98 {
99     const struct name_keysym search = { .name = s, .keysym = 0 };
100     const struct name_keysym *entry;
101     char *tmp;
102     xkb_keysym_t val;
103
104     entry = bsearch(&search, name_to_keysym,
105                     sizeof(name_to_keysym) / sizeof(*name_to_keysym),
106                     sizeof(*name_to_keysym),
107                     compare_by_name);
108     if (entry)
109         return entry->keysym;
110
111     if (*s == 'U') {
112         val = strtoul(&s[1], &tmp, 16);
113         if (tmp && *tmp != '\0')
114             return XKB_KEY_NoSymbol;
115
116         if (val < 0x20 || (val > 0x7e && val < 0xa0))
117             return XKB_KEY_NoSymbol;
118         if (val < 0x100)
119             return val;
120         if (val > 0x10ffff)
121             return XKB_KEY_NoSymbol;
122         return val | 0x01000000;
123     }
124     else if (s[0] == '0' && s[1] == 'x') {
125         val = strtoul(&s[2], &tmp, 16);
126         if (tmp && *tmp != '\0')
127             return XKB_KEY_NoSymbol;
128
129         return val;
130     }
131
132     /* Stupid inconsistency between the headers and XKeysymDB: the former has
133      * no separating underscore, while some XF86* syms in the latter did.
134      * As a last ditch effort, try without. */
135     if (strncmp(s, "XF86_", 5) == 0) {
136         xkb_keysym_t ret;
137         tmp = strdup(s);
138         if (!tmp)
139             return XKB_KEY_NoSymbol;
140         memmove(&tmp[4], &tmp[5], strlen(s) - 5 + 1);
141         ret = xkb_keysym_from_name(tmp);
142         free(tmp);
143         return ret;
144     }
145
146     return XKB_KEY_NoSymbol;
147 }
148
149 bool
150 xkb_keysym_is_keypad(xkb_keysym_t keysym)
151 {
152     return keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_Equal;
153 }
154
155 static void
156 XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper);
157
158 bool
159 xkb_keysym_is_lower(xkb_keysym_t ks)
160 {
161     xkb_keysym_t lower, upper;
162
163     XConvertCase(ks, &lower, &upper);
164
165     if (lower == upper)
166         return false;
167
168     return (ks == lower ? true : false);
169 }
170
171 bool
172 xkb_keysym_is_upper(xkb_keysym_t ks)
173 {
174     xkb_keysym_t lower, upper;
175
176     XConvertCase(ks, &lower, &upper);
177
178     if (lower == upper)
179         return false;
180
181     return (ks == upper ? true : false);
182 }
183
184 /*
185  * The following is copied verbatim from libX11:src/KeyBind.c, commit
186  * d45b3fc19fbe95c41afc4e51d768df6d42332010, with the following changes:
187  *  - unsigned -> uint32_t
188  *  - unsigend short -> uint16_t
189  *  - s/XK_/XKB_KEY_
190  *
191  * XXX: If newlocale() and iswlower_l()/iswupper_l() interface ever
192  *      become portable, we should use that in conjunction with
193  *      xkb_keysym_to_utf32(), instead of all this stuff.  We should
194  *      be sure to give the same results as libX11, though, and be
195  *      locale independent; this information is used by xkbcomp to
196  *      find the automatic type to assign to key groups.
197  */
198
199 static void
200 UCSConvertCase(uint32_t code, xkb_keysym_t *lower, xkb_keysym_t *upper)
201 {
202     /* Case conversion for UCS, as in Unicode Data version 4.0.0 */
203     /* NB: Only converts simple one-to-one mappings. */
204
205     /* Tables are used where they take less space than     */
206     /* the code to work out the mappings. Zero values mean */
207     /* undefined code points.                              */
208
209     static uint16_t const IPAExt_upper_mapping[] = { /* part only */
210                             0x0181, 0x0186, 0x0255, 0x0189, 0x018A,
211     0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,
212     0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
213     0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C,
214     0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277,
215     0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F,
216     0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,
217     0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F,
218     0x0290, 0x0291, 0x01B7
219     };
220
221     static uint16_t const LatinExtB_upper_mapping[] = { /* first part only */
222     0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
223     0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,
224     0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197,
225     0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F,
226     0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,
227     0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,
228     0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,
229     0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7,
230     0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7,
231     0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA
232     };
233
234     static uint16_t const LatinExtB_lower_mapping[] = { /* first part only */
235     0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
236     0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
237     0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
238     0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
239     0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x0280, 0x01A8,
240     0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0,
241     0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
242     0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
243     0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
244     0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC
245     };
246
247     static uint16_t const Greek_upper_mapping[] = {
248     0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
249     0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
250     0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x0386, 0x0387,
251     0x0388, 0x0389, 0x038A, 0x0000, 0x038C, 0x0000, 0x038E, 0x038F,
252     0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
253     0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
254     0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
255     0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,
256     0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
257     0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
258     0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
259     0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x0000,
260     0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03D7,
261     0x03D8, 0x03D8, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE,
262     0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6,
263     0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,
264     0x039A, 0x03A1, 0x03F9, 0x03F3, 0x03F4, 0x0395, 0x03F6, 0x03F7,
265     0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x0000, 0x0000, 0x0000, 0x0000
266     };
267
268     static uint16_t const Greek_lower_mapping[] = {
269     0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
270     0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
271     0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x03AC, 0x0387,
272     0x03AD, 0x03AE, 0x03AF, 0x0000, 0x03CC, 0x0000, 0x03CD, 0x03CE,
273     0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
274     0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
275     0x03C0, 0x03C1, 0x0000, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
276     0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
277     0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
278     0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
279     0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
280     0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000,
281     0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
282     0x03D9, 0x03D9, 0x03DB, 0x03DB, 0x03DD, 0x03DD, 0x03DF, 0x03DF,
283     0x03E1, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
284     0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
285     0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03B8, 0x03F5, 0x03F6, 0x03F8,
286     0x03F8, 0x03F2, 0x03FB, 0x03FB, 0x0000, 0x0000, 0x0000, 0x0000
287     };
288
289     static uint16_t const GreekExt_lower_mapping[] = {
290     0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
291     0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
292     0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
293     0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
294     0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
295     0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
296     0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
297     0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
298     0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
299     0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
300     0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57,
301     0x0000, 0x1F51, 0x0000, 0x1F53, 0x0000, 0x1F55, 0x0000, 0x1F57,
302     0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
303     0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
304     0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77,
305     0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x0000, 0x0000,
306     0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
307     0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
308     0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
309     0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
310     0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
311     0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
312     0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
313     0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1FBD, 0x1FBE, 0x1FBF,
314     0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
315     0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF,
316     0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
317     0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
318     0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7,
319     0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF,
320     0x0000, 0x0000, 0x1FF2, 0x1FF3, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
321     0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x1FFD, 0x1FFE, 0x0000
322     };
323
324     static uint16_t const GreekExt_upper_mapping[] = {
325     0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
326     0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
327     0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
328     0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
329     0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
330     0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
331     0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
332     0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
333     0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
334     0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
335     0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F,
336     0x0000, 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F,
337     0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
338     0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
339     0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB,
340     0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x0000, 0x0000,
341     0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
342     0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
343     0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
344     0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
345     0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
346     0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
347     0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
348     0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x0399, 0x1FBF,
349     0x1FC0, 0x1FC1, 0x1FC2, 0x1FCC, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
350     0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF,
351     0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
352     0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
353     0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7,
354     0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF,
355     0x0000, 0x0000, 0x1FF2, 0x1FFC, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
356     0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x0000
357     };
358
359     *lower = code;
360     *upper = code;
361
362     /* Basic Latin and Latin-1 Supplement, U+0000 to U+00FF */
363     if (code <= 0x00ff) {
364         if (code >= 0x0041 && code <= 0x005a)             /* A-Z */
365             *lower += 0x20;
366         else if (code >= 0x0061 && code <= 0x007a)        /* a-z */
367             *upper -= 0x20;
368         else if ( (code >= 0x00c0 && code <= 0x00d6) ||
369                   (code >= 0x00d8 && code <= 0x00de) )
370             *lower += 0x20;
371         else if ( (code >= 0x00e0 && code <= 0x00f6) ||
372                   (code >= 0x00f8 && code <= 0x00fe) )
373             *upper -= 0x20;
374         else if (code == 0x00ff)      /* y with diaeresis */
375             *upper = 0x0178;
376         else if (code == 0x00b5)      /* micro sign */
377             *upper = 0x039c;
378         return;
379     }
380
381     /* Latin Extended-A, U+0100 to U+017F */
382     if (code >= 0x0100 && code <= 0x017f) {
383         if ( (code >= 0x0100 && code <= 0x012f) ||
384              (code >= 0x0132 && code <= 0x0137) ||
385              (code >= 0x014a && code <= 0x0177) ) {
386             *upper = code & ~1;
387             *lower = code | 1;
388         }
389         else if ( (code >= 0x0139 && code <= 0x0148) ||
390                   (code >= 0x0179 && code <= 0x017e) ) {
391             if (code & 1)
392                 *lower += 1;
393             else
394                 *upper -= 1;
395         }
396         else if (code == 0x0130)
397             *lower = 0x0069;
398         else if (code == 0x0131)
399             *upper = 0x0049;
400         else if (code == 0x0178)
401             *lower = 0x00ff;
402         else if (code == 0x017f)
403             *upper = 0x0053;
404         return;
405     }
406
407     /* Latin Extended-B, U+0180 to U+024F */
408     if (code >= 0x0180 && code <= 0x024f) {
409         if (code >= 0x01cd && code <= 0x01dc) {
410             if (code & 1)
411                *lower += 1;
412             else
413                *upper -= 1;
414         }
415         else if ( (code >= 0x01de && code <= 0x01ef) ||
416                   (code >= 0x01f4 && code <= 0x01f5) ||
417                   (code >= 0x01f8 && code <= 0x021f) ||
418                   (code >= 0x0222 && code <= 0x0233) ) {
419             *lower |= 1;
420             *upper &= ~1;
421         }
422         else if (code >= 0x0180 && code <= 0x01cc) {
423             *lower = LatinExtB_lower_mapping[code - 0x0180];
424             *upper = LatinExtB_upper_mapping[code - 0x0180];
425         }
426         else if (code == 0x01dd)
427             *upper = 0x018e;
428         else if (code == 0x01f1 || code == 0x01f2) {
429             *lower = 0x01f3;
430             *upper = 0x01f1;
431         }
432         else if (code == 0x01f3)
433             *upper = 0x01f1;
434         else if (code == 0x01f6)
435             *lower = 0x0195;
436         else if (code == 0x01f7)
437             *lower = 0x01bf;
438         else if (code == 0x0220)
439             *lower = 0x019e;
440         return;
441     }
442
443     /* IPA Extensions, U+0250 to U+02AF */
444     if (code >= 0x0253 && code <= 0x0292) {
445         *upper = IPAExt_upper_mapping[code - 0x0253];
446     }
447
448     /* Combining Diacritical Marks, U+0300 to U+036F */
449     if (code == 0x0345) {
450         *upper = 0x0399;
451     }
452
453     /* Greek and Coptic, U+0370 to U+03FF */
454     if (code >= 0x0370 && code <= 0x03ff) {
455         *lower = Greek_lower_mapping[code - 0x0370];
456         *upper = Greek_upper_mapping[code - 0x0370];
457         if (*upper == 0)
458             *upper = code;
459         if (*lower == 0)
460             *lower = code;
461     }
462
463     /* Cyrillic and Cyrillic Supplementary, U+0400 to U+052F */
464     if ( (code >= 0x0400 && code <= 0x04ff) ||
465          (code >= 0x0500 && code <= 0x052f) ) {
466         if (code >= 0x0400 && code <= 0x040f)
467             *lower += 0x50;
468         else if (code >= 0x0410 && code <= 0x042f)
469             *lower += 0x20;
470         else if (code >= 0x0430 && code <= 0x044f)
471             *upper -= 0x20;
472         else if (code >= 0x0450 && code <= 0x045f)
473             *upper -= 0x50;
474         else if ( (code >= 0x0460 && code <= 0x0481) ||
475                   (code >= 0x048a && code <= 0x04bf) ||
476                   (code >= 0x04d0 && code <= 0x04f5) ||
477                   (code >= 0x04f8 && code <= 0x04f9) ||
478                   (code >= 0x0500 && code <= 0x050f) ) {
479             *upper &= ~1;
480             *lower |= 1;
481         }
482         else if (code >= 0x04c1 && code <= 0x04ce) {
483             if (code & 1)
484                 *lower += 1;
485             else
486                 *upper -= 1;
487         }
488     }
489
490     /* Armenian, U+0530 to U+058F */
491     if (code >= 0x0530 && code <= 0x058f) {
492         if (code >= 0x0531 && code <= 0x0556)
493             *lower += 0x30;
494         else if (code >=0x0561 && code <= 0x0586)
495             *upper -= 0x30;
496     }
497
498     /* Latin Extended Additional, U+1E00 to U+1EFF */
499     if (code >= 0x1e00 && code <= 0x1eff) {
500         if ( (code >= 0x1e00 && code <= 0x1e95) ||
501              (code >= 0x1ea0 && code <= 0x1ef9) ) {
502             *upper &= ~1;
503             *lower |= 1;
504         }
505         else if (code == 0x1e9b)
506             *upper = 0x1e60;
507     }
508
509     /* Greek Extended, U+1F00 to U+1FFF */
510     if (code >= 0x1f00 && code <= 0x1fff) {
511         *lower = GreekExt_lower_mapping[code - 0x1f00];
512         *upper = GreekExt_upper_mapping[code - 0x1f00];
513         if (*upper == 0)
514             *upper = code;
515         if (*lower == 0)
516             *lower = code;
517     }
518
519     /* Letterlike Symbols, U+2100 to U+214F */
520     if (code >= 0x2100 && code <= 0x214f) {
521         switch (code) {
522         case 0x2126: *lower = 0x03c9; break;
523         case 0x212a: *lower = 0x006b; break;
524         case 0x212b: *lower = 0x00e5; break;
525         }
526     }
527     /* Number Forms, U+2150 to U+218F */
528     else if (code >= 0x2160 && code <= 0x216f)
529         *lower += 0x10;
530     else if (code >= 0x2170 && code <= 0x217f)
531         *upper -= 0x10;
532     /* Enclosed Alphanumerics, U+2460 to U+24FF */
533     else if (code >= 0x24b6 && code <= 0x24cf)
534         *lower += 0x1a;
535     else if (code >= 0x24d0 && code <= 0x24e9)
536         *upper -= 0x1a;
537     /* Halfwidth and Fullwidth Forms, U+FF00 to U+FFEF */
538     else if (code >= 0xff21 && code <= 0xff3a)
539         *lower += 0x20;
540     else if (code >= 0xff41 && code <= 0xff5a)
541         *upper -= 0x20;
542     /* Deseret, U+10400 to U+104FF */
543     else if (code >= 0x10400 && code <= 0x10427)
544         *lower += 0x28;
545     else if (code >= 0x10428 && code <= 0x1044f)
546         *upper -= 0x28;
547 }
548
549 static void
550 XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper)
551 {
552     /* Latin 1 keysym */
553     if (sym < 0x100) {
554         UCSConvertCase(sym, lower, upper);
555         return;
556     }
557
558     /* Unicode keysym */
559     if ((sym & 0xff000000) == 0x01000000) {
560         UCSConvertCase((sym & 0x00ffffff), lower, upper);
561         *upper |= 0x01000000;
562         *lower |= 0x01000000;
563         return;
564     }
565
566     /* Legacy keysym */
567
568     *lower = sym;
569     *upper = sym;
570
571     switch(sym >> 8) {
572     case 1: /* Latin 2 */
573         /* Assume the KeySym is a legal value (ignore discontinuities) */
574         if (sym == XKB_KEY_Aogonek)
575             *lower = XKB_KEY_aogonek;
576         else if (sym >= XKB_KEY_Lstroke && sym <= XKB_KEY_Sacute)
577             *lower += (XKB_KEY_lstroke - XKB_KEY_Lstroke);
578         else if (sym >= XKB_KEY_Scaron && sym <= XKB_KEY_Zacute)
579             *lower += (XKB_KEY_scaron - XKB_KEY_Scaron);
580         else if (sym >= XKB_KEY_Zcaron && sym <= XKB_KEY_Zabovedot)
581             *lower += (XKB_KEY_zcaron - XKB_KEY_Zcaron);
582         else if (sym == XKB_KEY_aogonek)
583             *upper = XKB_KEY_Aogonek;
584         else if (sym >= XKB_KEY_lstroke && sym <= XKB_KEY_sacute)
585             *upper -= (XKB_KEY_lstroke - XKB_KEY_Lstroke);
586         else if (sym >= XKB_KEY_scaron && sym <= XKB_KEY_zacute)
587             *upper -= (XKB_KEY_scaron - XKB_KEY_Scaron);
588         else if (sym >= XKB_KEY_zcaron && sym <= XKB_KEY_zabovedot)
589             *upper -= (XKB_KEY_zcaron - XKB_KEY_Zcaron);
590         else if (sym >= XKB_KEY_Racute && sym <= XKB_KEY_Tcedilla)
591             *lower += (XKB_KEY_racute - XKB_KEY_Racute);
592         else if (sym >= XKB_KEY_racute && sym <= XKB_KEY_tcedilla)
593             *upper -= (XKB_KEY_racute - XKB_KEY_Racute);
594         break;
595     case 2: /* Latin 3 */
596         /* Assume the KeySym is a legal value (ignore discontinuities) */
597         if (sym >= XKB_KEY_Hstroke && sym <= XKB_KEY_Hcircumflex)
598             *lower += (XKB_KEY_hstroke - XKB_KEY_Hstroke);
599         else if (sym >= XKB_KEY_Gbreve && sym <= XKB_KEY_Jcircumflex)
600             *lower += (XKB_KEY_gbreve - XKB_KEY_Gbreve);
601         else if (sym >= XKB_KEY_hstroke && sym <= XKB_KEY_hcircumflex)
602             *upper -= (XKB_KEY_hstroke - XKB_KEY_Hstroke);
603         else if (sym >= XKB_KEY_gbreve && sym <= XKB_KEY_jcircumflex)
604             *upper -= (XKB_KEY_gbreve - XKB_KEY_Gbreve);
605         else if (sym >= XKB_KEY_Cabovedot && sym <= XKB_KEY_Scircumflex)
606             *lower += (XKB_KEY_cabovedot - XKB_KEY_Cabovedot);
607         else if (sym >= XKB_KEY_cabovedot && sym <= XKB_KEY_scircumflex)
608             *upper -= (XKB_KEY_cabovedot - XKB_KEY_Cabovedot);
609         break;
610     case 3: /* Latin 4 */
611         /* Assume the KeySym is a legal value (ignore discontinuities) */
612         if (sym >= XKB_KEY_Rcedilla && sym <= XKB_KEY_Tslash)
613             *lower += (XKB_KEY_rcedilla - XKB_KEY_Rcedilla);
614         else if (sym >= XKB_KEY_rcedilla && sym <= XKB_KEY_tslash)
615             *upper -= (XKB_KEY_rcedilla - XKB_KEY_Rcedilla);
616         else if (sym == XKB_KEY_ENG)
617             *lower = XKB_KEY_eng;
618         else if (sym == XKB_KEY_eng)
619             *upper = XKB_KEY_ENG;
620         else if (sym >= XKB_KEY_Amacron && sym <= XKB_KEY_Umacron)
621             *lower += (XKB_KEY_amacron - XKB_KEY_Amacron);
622         else if (sym >= XKB_KEY_amacron && sym <= XKB_KEY_umacron)
623             *upper -= (XKB_KEY_amacron - XKB_KEY_Amacron);
624         break;
625     case 6: /* Cyrillic */
626         /* Assume the KeySym is a legal value (ignore discontinuities) */
627         if (sym >= XKB_KEY_Serbian_DJE && sym <= XKB_KEY_Serbian_DZE)
628             *lower -= (XKB_KEY_Serbian_DJE - XKB_KEY_Serbian_dje);
629         else if (sym >= XKB_KEY_Serbian_dje && sym <= XKB_KEY_Serbian_dze)
630             *upper += (XKB_KEY_Serbian_DJE - XKB_KEY_Serbian_dje);
631         else if (sym >= XKB_KEY_Cyrillic_YU && sym <= XKB_KEY_Cyrillic_HARDSIGN)
632             *lower -= (XKB_KEY_Cyrillic_YU - XKB_KEY_Cyrillic_yu);
633         else if (sym >= XKB_KEY_Cyrillic_yu && sym <= XKB_KEY_Cyrillic_hardsign)
634             *upper += (XKB_KEY_Cyrillic_YU - XKB_KEY_Cyrillic_yu);
635         break;
636     case 7: /* Greek */
637         /* Assume the KeySym is a legal value (ignore discontinuities) */
638         if (sym >= XKB_KEY_Greek_ALPHAaccent && sym <= XKB_KEY_Greek_OMEGAaccent)
639             *lower += (XKB_KEY_Greek_alphaaccent - XKB_KEY_Greek_ALPHAaccent);
640         else if (sym >= XKB_KEY_Greek_alphaaccent && sym <= XKB_KEY_Greek_omegaaccent &&
641                  sym != XKB_KEY_Greek_iotaaccentdieresis &&
642                  sym != XKB_KEY_Greek_upsilonaccentdieresis)
643             *upper -= (XKB_KEY_Greek_alphaaccent - XKB_KEY_Greek_ALPHAaccent);
644         else if (sym >= XKB_KEY_Greek_ALPHA && sym <= XKB_KEY_Greek_OMEGA)
645             *lower += (XKB_KEY_Greek_alpha - XKB_KEY_Greek_ALPHA);
646         else if (sym >= XKB_KEY_Greek_alpha && sym <= XKB_KEY_Greek_omega &&
647                  sym != XKB_KEY_Greek_finalsmallsigma)
648             *upper -= (XKB_KEY_Greek_alpha - XKB_KEY_Greek_ALPHA);
649         break;
650     case 0x13: /* Latin 9 */
651         if (sym == XKB_KEY_OE)
652             *lower = XKB_KEY_oe;
653         else if (sym == XKB_KEY_oe)
654             *upper = XKB_KEY_OE;
655         else if (sym == XKB_KEY_Ydiaeresis)
656             *lower = XKB_KEY_ydiaeresis;
657         break;
658     }
659 }