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