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