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