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