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