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