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