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