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