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