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.
53 #include "xkbcommon/xkbcommon.h"
56 #include "ks_tables.h"
58 static inline const char *
59 get_name(const struct name_keysym *entry)
61 return keysym_names + entry->offset;
65 xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
67 if (ks > XKB_KEYSYM_MAX) {
68 snprintf(buffer, size, "Invalid");
72 int32_t lo = 0, hi = ARRAY_SIZE(keysym_to_name) - 1;
74 int32_t mid = (lo + hi) / 2;
75 if (ks > keysym_to_name[mid].keysym) {
77 } else if (ks < keysym_to_name[mid].keysym) {
80 return snprintf(buffer, size, "%s", get_name(&keysym_to_name[mid]));
84 /* Unnamed Unicode codepoint. */
85 if (ks >= 0x01000100 && ks <= 0x0110ffff) {
86 const int width = (ks & 0xff0000UL) ? 8 : 4;
87 return snprintf(buffer, size, "U%0*lX", width, ks & 0xffffffUL);
90 /* Unnamed, non-Unicode, symbol (shouldn't generally happen). */
91 return snprintf(buffer, size, "0x%08x", ks);
95 * Parse the numeric part of a 0xXXXX and UXXXX keysym.
96 * Not using strtoul -- it's slower and accepts a bunch of stuff
97 * we don't want to allow, like signs, spaces, even locale stuff.
100 parse_keysym_hex(const char *s, uint32_t *out)
104 for (i = 0; i < 8 && s[i] != '\0'; i++) {
106 if ('0' <= s[i] && s[i] <= '9')
107 result += s[i] - '0';
108 else if ('a' <= s[i] && s[i] <= 'f')
109 result += 10 + s[i] - 'a';
110 else if ('A' <= s[i] && s[i] <= 'F')
111 result += 10 + s[i] - 'A';
116 return s[i] == '\0' && i > 0;
119 XKB_EXPORT xkb_keysym_t
120 xkb_keysym_from_name(const char *name, enum xkb_keysym_flags flags)
122 const struct name_keysym *entry = NULL;
125 bool icase = (flags & XKB_KEYSYM_CASE_INSENSITIVE);
127 if (flags & ~XKB_KEYSYM_CASE_INSENSITIVE)
128 return XKB_KEY_NoSymbol;
131 * We need to !icase case to be fast, for e.g. Compose file parsing.
132 * So do it in a fast path.
135 size_t pos = keysym_name_perfect_hash(name);
136 if (pos < ARRAY_SIZE(name_to_keysym)) {
137 const char *s = get_name(&name_to_keysym[pos]);
138 if (strcmp(name, s) == 0)
139 return name_to_keysym[pos].keysym;
143 * Find the correct keysym for case-insensitive match.
145 * The name_to_keysym table is sorted by istrcmp(). So the binary
146 * search may return _any_ of all possible case-insensitive duplicates. This
147 * code searches the entry, all previous and all next entries that match by
148 * case-insensitive comparison and returns the "best" case-insensitive
151 * The "best" case-insensitive match is the lower-case keysym which we find
152 * with the help of xkb_keysym_is_lower(). The only keysyms that only differ
153 * by letter-case are keysyms that are available as lower-case and
154 * upper-case variant (like KEY_a and KEY_A). So returning the first
155 * lower-case match is enough in this case.
158 int32_t lo = 0, hi = ARRAY_SIZE(name_to_keysym) - 1;
160 int32_t mid = (lo + hi) / 2;
161 int cmp = istrcmp(name, get_name(&name_to_keysym[mid]));
164 } else if (cmp < 0) {
167 entry = &name_to_keysym[mid];
172 const struct name_keysym *iter, *last;
174 if (icase && xkb_keysym_is_lower(entry->keysym))
175 return entry->keysym;
177 for (iter = entry - 1; iter >= name_to_keysym; --iter) {
178 if (istrcmp(get_name(iter), get_name(entry)) != 0)
180 if (xkb_keysym_is_lower(iter->keysym))
184 last = name_to_keysym + ARRAY_SIZE(name_to_keysym);
185 for (iter = entry + 1; iter < last; ++iter) {
186 if (istrcmp(get_name(iter), get_name(entry)) != 0)
188 if (xkb_keysym_is_lower(iter->keysym))
192 return entry->keysym;
196 if (*name == 'U' || (icase && *name == 'u')) {
197 if (!parse_keysym_hex(&name[1], &val))
198 return XKB_KEY_NoSymbol;
200 if (val < 0x20 || (val > 0x7e && val < 0xa0))
201 return XKB_KEY_NoSymbol;
203 return (xkb_keysym_t) val;
205 return XKB_KEY_NoSymbol;
206 return (xkb_keysym_t) val | 0x01000000;
208 else if (name[0] == '0' && (name[1] == 'x' || (icase && name[1] == 'X'))) {
209 if (!parse_keysym_hex(&name[2], &val))
210 return XKB_KEY_NoSymbol;
211 if (val > XKB_KEYSYM_MAX)
212 return XKB_KEY_NoSymbol;
213 return (xkb_keysym_t) val;
216 /* Stupid inconsistency between the headers and XKeysymDB: the former has
217 * no separating underscore, while some XF86* syms in the latter did.
218 * As a last ditch effort, try without. */
219 if (strncmp(name, "XF86_", 5) == 0 ||
220 (icase && istrncmp(name, "XF86_", 5) == 0)) {
224 return XKB_KEY_NoSymbol;
225 memmove(&tmp[4], &tmp[5], strlen(name) - 5 + 1);
226 ret = xkb_keysym_from_name(tmp, flags);
231 return XKB_KEY_NoSymbol;
235 xkb_keysym_is_keypad(xkb_keysym_t keysym)
237 return keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_Equal;
242 xkb_keysym_is_modifier(xkb_keysym_t keysym)
245 (keysym >= XKB_KEY_Shift_L && keysym <= XKB_KEY_Hyper_R) ||
246 /* libX11 only goes upto XKB_KEY_ISO_Level5_Lock. */
247 (keysym >= XKB_KEY_ISO_Lock && keysym <= XKB_KEY_ISO_Last_Group_Lock) ||
248 keysym == XKB_KEY_Mode_switch ||
249 keysym == XKB_KEY_Num_Lock;
253 XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper);
256 xkb_keysym_is_lower(xkb_keysym_t ks)
258 xkb_keysym_t lower, upper;
260 XConvertCase(ks, &lower, &upper);
265 return (ks == lower ? true : false);
269 xkb_keysym_is_upper(xkb_keysym_t ks)
271 xkb_keysym_t lower, upper;
273 XConvertCase(ks, &lower, &upper);
278 return (ks == upper ? true : false);
281 XKB_EXPORT xkb_keysym_t
282 xkb_keysym_to_lower(xkb_keysym_t ks)
284 xkb_keysym_t lower, upper;
286 XConvertCase(ks, &lower, &upper);
291 XKB_EXPORT xkb_keysym_t
292 xkb_keysym_to_upper(xkb_keysym_t ks)
294 xkb_keysym_t lower, upper;
296 XConvertCase(ks, &lower, &upper);
302 * The following is copied verbatim from libX11:src/KeyBind.c, commit
303 * d45b3fc19fbe95c41afc4e51d768df6d42332010, with the following changes:
304 * - unsigned -> uint32_t
305 * - unsigend short -> uint16_t
308 * XXX: If newlocale() and iswlower_l()/iswupper_l() interface ever
309 * become portable, we should use that in conjunction with
310 * xkb_keysym_to_utf32(), instead of all this stuff. We should
311 * be sure to give the same results as libX11, though, and be
312 * locale independent; this information is used by xkbcomp to
313 * find the automatic type to assign to key groups.
317 UCSConvertCase(uint32_t code, xkb_keysym_t *lower, xkb_keysym_t *upper)
319 /* Case conversion for UCS, as in Unicode Data version 4.0.0 */
320 /* NB: Only converts simple one-to-one mappings. */
322 /* Tables are used where they take less space than */
323 /* the code to work out the mappings. Zero values mean */
324 /* undefined code points. */
326 static uint16_t const IPAExt_upper_mapping[] = { /* part only */
327 0x0181, 0x0186, 0x0255, 0x0189, 0x018A,
328 0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,
329 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
330 0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C,
331 0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277,
332 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F,
333 0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,
334 0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F,
335 0x0290, 0x0291, 0x01B7
338 static uint16_t const LatinExtB_upper_mapping[] = { /* first part only */
339 0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
340 0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,
341 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197,
342 0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F,
343 0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,
344 0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,
345 0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,
346 0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7,
347 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7,
348 0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA
351 static uint16_t const LatinExtB_lower_mapping[] = { /* first part only */
352 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
353 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
354 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
355 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
356 0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x0280, 0x01A8,
357 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0,
358 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
359 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
360 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
361 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC
364 static uint16_t const Greek_upper_mapping[] = {
365 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
366 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
367 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x0386, 0x0387,
368 0x0388, 0x0389, 0x038A, 0x0000, 0x038C, 0x0000, 0x038E, 0x038F,
369 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
370 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
371 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
372 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,
373 0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
374 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
375 0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
376 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x0000,
377 0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03D7,
378 0x03D8, 0x03D8, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE,
379 0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6,
380 0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,
381 0x039A, 0x03A1, 0x03F9, 0x03F3, 0x03F4, 0x0395, 0x03F6, 0x03F7,
382 0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x0000, 0x0000, 0x0000, 0x0000
385 static uint16_t const Greek_lower_mapping[] = {
386 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
387 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
388 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x03AC, 0x0387,
389 0x03AD, 0x03AE, 0x03AF, 0x0000, 0x03CC, 0x0000, 0x03CD, 0x03CE,
390 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
391 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
392 0x03C0, 0x03C1, 0x0000, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
393 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
394 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
395 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
396 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
397 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000,
398 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
399 0x03D9, 0x03D9, 0x03DB, 0x03DB, 0x03DD, 0x03DD, 0x03DF, 0x03DF,
400 0x03E1, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
401 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
402 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03B8, 0x03F5, 0x03F6, 0x03F8,
403 0x03F8, 0x03F2, 0x03FB, 0x03FB, 0x0000, 0x0000, 0x0000, 0x0000
406 static uint16_t const GreekExt_lower_mapping[] = {
407 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
408 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
409 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
410 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
411 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
412 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
413 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
414 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
415 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
416 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
417 0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57,
418 0x0000, 0x1F51, 0x0000, 0x1F53, 0x0000, 0x1F55, 0x0000, 0x1F57,
419 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
420 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
421 0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77,
422 0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x0000, 0x0000,
423 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
424 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
425 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
426 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
427 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
428 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
429 0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
430 0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1FBD, 0x1FBE, 0x1FBF,
431 0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
432 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF,
433 0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
434 0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
435 0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7,
436 0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF,
437 0x0000, 0x0000, 0x1FF2, 0x1FF3, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
438 0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x1FFD, 0x1FFE, 0x0000
441 static uint16_t const GreekExt_upper_mapping[] = {
442 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
443 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
444 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
445 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
446 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
447 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
448 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
449 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
450 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
451 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
452 0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F,
453 0x0000, 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F,
454 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
455 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
456 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB,
457 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x0000, 0x0000,
458 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
459 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
460 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
461 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
462 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
463 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
464 0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
465 0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x0399, 0x1FBF,
466 0x1FC0, 0x1FC1, 0x1FC2, 0x1FCC, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
467 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF,
468 0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
469 0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
470 0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7,
471 0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF,
472 0x0000, 0x0000, 0x1FF2, 0x1FFC, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
473 0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x0000
479 /* Basic Latin and Latin-1 Supplement, U+0000 to U+00FF */
480 if (code <= 0x00ff) {
481 if (code >= 0x0041 && code <= 0x005a) /* A-Z */
483 else if (code >= 0x0061 && code <= 0x007a) /* a-z */
485 else if ( (code >= 0x00c0 && code <= 0x00d6) ||
486 (code >= 0x00d8 && code <= 0x00de) )
488 else if ( (code >= 0x00e0 && code <= 0x00f6) ||
489 (code >= 0x00f8 && code <= 0x00fe) )
491 else if (code == 0x00ff) /* y with diaeresis */
493 else if (code == 0x00b5) /* micro sign */
495 else if (code == 0x00df) /* ssharp */
500 /* Latin Extended-A, U+0100 to U+017F */
501 if (code >= 0x0100 && code <= 0x017f) {
502 if ( (code >= 0x0100 && code <= 0x012f) ||
503 (code >= 0x0132 && code <= 0x0137) ||
504 (code >= 0x014a && code <= 0x0177) ) {
508 else if ( (code >= 0x0139 && code <= 0x0148) ||
509 (code >= 0x0179 && code <= 0x017e) ) {
515 else if (code == 0x0130)
517 else if (code == 0x0131)
519 else if (code == 0x0178)
521 else if (code == 0x017f)
526 /* Latin Extended-B, U+0180 to U+024F */
527 if (code >= 0x0180 && code <= 0x024f) {
528 if (code >= 0x01cd && code <= 0x01dc) {
534 else if ( (code >= 0x01de && code <= 0x01ef) ||
535 (code >= 0x01f4 && code <= 0x01f5) ||
536 (code >= 0x01f8 && code <= 0x021f) ||
537 (code >= 0x0222 && code <= 0x0233) ) {
541 else if (code >= 0x0180 && code <= 0x01cc) {
542 *lower = LatinExtB_lower_mapping[code - 0x0180];
543 *upper = LatinExtB_upper_mapping[code - 0x0180];
545 else if (code == 0x01dd)
547 else if (code == 0x01f1 || code == 0x01f2) {
551 else if (code == 0x01f3)
553 else if (code == 0x01f6)
555 else if (code == 0x01f7)
557 else if (code == 0x0220)
562 /* IPA Extensions, U+0250 to U+02AF */
563 if (code >= 0x0253 && code <= 0x0292) {
564 *upper = IPAExt_upper_mapping[code - 0x0253];
567 /* Combining Diacritical Marks, U+0300 to U+036F */
568 if (code == 0x0345) {
572 /* Greek and Coptic, U+0370 to U+03FF */
573 if (code >= 0x0370 && code <= 0x03ff) {
574 *lower = Greek_lower_mapping[code - 0x0370];
575 *upper = Greek_upper_mapping[code - 0x0370];
582 /* Cyrillic and Cyrillic Supplementary, U+0400 to U+052F */
583 if ( (code >= 0x0400 && code <= 0x04ff) ||
584 (code >= 0x0500 && code <= 0x052f) ) {
585 if (code >= 0x0400 && code <= 0x040f)
587 else if (code >= 0x0410 && code <= 0x042f)
589 else if (code >= 0x0430 && code <= 0x044f)
591 else if (code >= 0x0450 && code <= 0x045f)
593 else if ( (code >= 0x0460 && code <= 0x0481) ||
594 (code >= 0x048a && code <= 0x04bf) ||
595 (code >= 0x04d0 && code <= 0x04f5) ||
596 (code >= 0x04f8 && code <= 0x04f9) ||
597 (code >= 0x0500 && code <= 0x050f) ) {
601 else if (code >= 0x04c1 && code <= 0x04ce) {
609 /* Armenian, U+0530 to U+058F */
610 if (code >= 0x0530 && code <= 0x058f) {
611 if (code >= 0x0531 && code <= 0x0556)
613 else if (code >=0x0561 && code <= 0x0586)
617 /* Latin Extended Additional, U+1E00 to U+1EFF */
618 if (code >= 0x1e00 && code <= 0x1eff) {
619 if ( (code >= 0x1e00 && code <= 0x1e95) ||
620 (code >= 0x1ea0 && code <= 0x1ef9) ) {
624 else if (code == 0x1e9b)
626 else if (code == 0x1e9e)
627 *lower = 0x00df; /* ssharp */
630 /* Greek Extended, U+1F00 to U+1FFF */
631 if (code >= 0x1f00 && code <= 0x1fff) {
632 *lower = GreekExt_lower_mapping[code - 0x1f00];
633 *upper = GreekExt_upper_mapping[code - 0x1f00];
640 /* Letterlike Symbols, U+2100 to U+214F */
641 if (code >= 0x2100 && code <= 0x214f) {
643 case 0x2126: *lower = 0x03c9; break;
644 case 0x212a: *lower = 0x006b; break;
645 case 0x212b: *lower = 0x00e5; break;
648 /* Number Forms, U+2150 to U+218F */
649 else if (code >= 0x2160 && code <= 0x216f)
651 else if (code >= 0x2170 && code <= 0x217f)
653 /* Enclosed Alphanumerics, U+2460 to U+24FF */
654 else if (code >= 0x24b6 && code <= 0x24cf)
656 else if (code >= 0x24d0 && code <= 0x24e9)
658 /* Halfwidth and Fullwidth Forms, U+FF00 to U+FFEF */
659 else if (code >= 0xff21 && code <= 0xff3a)
661 else if (code >= 0xff41 && code <= 0xff5a)
663 /* Deseret, U+10400 to U+104FF */
664 else if (code >= 0x10400 && code <= 0x10427)
666 else if (code >= 0x10428 && code <= 0x1044f)
671 XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper)
675 UCSConvertCase(sym, lower, upper);
680 if ((sym & 0xff000000) == 0x01000000) {
681 UCSConvertCase((sym & 0x00ffffff), lower, upper);
682 *upper |= 0x01000000;
683 *lower |= 0x01000000;
693 case 1: /* Latin 2 */
694 /* Assume the KeySym is a legal value (ignore discontinuities) */
695 if (sym == XKB_KEY_Aogonek)
696 *lower = XKB_KEY_aogonek;
697 else if (sym >= XKB_KEY_Lstroke && sym <= XKB_KEY_Sacute)
698 *lower += (XKB_KEY_lstroke - XKB_KEY_Lstroke);
699 else if (sym >= XKB_KEY_Scaron && sym <= XKB_KEY_Zacute)
700 *lower += (XKB_KEY_scaron - XKB_KEY_Scaron);
701 else if (sym >= XKB_KEY_Zcaron && sym <= XKB_KEY_Zabovedot)
702 *lower += (XKB_KEY_zcaron - XKB_KEY_Zcaron);
703 else if (sym == XKB_KEY_aogonek)
704 *upper = XKB_KEY_Aogonek;
705 else if (sym >= XKB_KEY_lstroke && sym <= XKB_KEY_sacute)
706 *upper -= (XKB_KEY_lstroke - XKB_KEY_Lstroke);
707 else if (sym >= XKB_KEY_scaron && sym <= XKB_KEY_zacute)
708 *upper -= (XKB_KEY_scaron - XKB_KEY_Scaron);
709 else if (sym >= XKB_KEY_zcaron && sym <= XKB_KEY_zabovedot)
710 *upper -= (XKB_KEY_zcaron - XKB_KEY_Zcaron);
711 else if (sym >= XKB_KEY_Racute && sym <= XKB_KEY_Tcedilla)
712 *lower += (XKB_KEY_racute - XKB_KEY_Racute);
713 else if (sym >= XKB_KEY_racute && sym <= XKB_KEY_tcedilla)
714 *upper -= (XKB_KEY_racute - XKB_KEY_Racute);
716 case 2: /* Latin 3 */
717 /* Assume the KeySym is a legal value (ignore discontinuities) */
718 if (sym >= XKB_KEY_Hstroke && sym <= XKB_KEY_Hcircumflex)
719 *lower += (XKB_KEY_hstroke - XKB_KEY_Hstroke);
720 else if (sym >= XKB_KEY_Gbreve && sym <= XKB_KEY_Jcircumflex)
721 *lower += (XKB_KEY_gbreve - XKB_KEY_Gbreve);
722 else if (sym >= XKB_KEY_hstroke && sym <= XKB_KEY_hcircumflex)
723 *upper -= (XKB_KEY_hstroke - XKB_KEY_Hstroke);
724 else if (sym >= XKB_KEY_gbreve && sym <= XKB_KEY_jcircumflex)
725 *upper -= (XKB_KEY_gbreve - XKB_KEY_Gbreve);
726 else if (sym >= XKB_KEY_Cabovedot && sym <= XKB_KEY_Scircumflex)
727 *lower += (XKB_KEY_cabovedot - XKB_KEY_Cabovedot);
728 else if (sym >= XKB_KEY_cabovedot && sym <= XKB_KEY_scircumflex)
729 *upper -= (XKB_KEY_cabovedot - XKB_KEY_Cabovedot);
731 case 3: /* Latin 4 */
732 /* Assume the KeySym is a legal value (ignore discontinuities) */
733 if (sym >= XKB_KEY_Rcedilla && sym <= XKB_KEY_Tslash)
734 *lower += (XKB_KEY_rcedilla - XKB_KEY_Rcedilla);
735 else if (sym >= XKB_KEY_rcedilla && sym <= XKB_KEY_tslash)
736 *upper -= (XKB_KEY_rcedilla - XKB_KEY_Rcedilla);
737 else if (sym == XKB_KEY_ENG)
738 *lower = XKB_KEY_eng;
739 else if (sym == XKB_KEY_eng)
740 *upper = XKB_KEY_ENG;
741 else if (sym >= XKB_KEY_Amacron && sym <= XKB_KEY_Umacron)
742 *lower += (XKB_KEY_amacron - XKB_KEY_Amacron);
743 else if (sym >= XKB_KEY_amacron && sym <= XKB_KEY_umacron)
744 *upper -= (XKB_KEY_amacron - XKB_KEY_Amacron);
746 case 6: /* Cyrillic */
747 /* Assume the KeySym is a legal value (ignore discontinuities) */
748 if (sym >= XKB_KEY_Serbian_DJE && sym <= XKB_KEY_Cyrillic_DZHE)
749 *lower -= (XKB_KEY_Serbian_DJE - XKB_KEY_Serbian_dje);
750 else if (sym >= XKB_KEY_Serbian_dje && sym <= XKB_KEY_Cyrillic_dzhe)
751 *upper += (XKB_KEY_Serbian_DJE - XKB_KEY_Serbian_dje);
752 else if (sym >= XKB_KEY_Cyrillic_YU && sym <= XKB_KEY_Cyrillic_HARDSIGN)
753 *lower -= (XKB_KEY_Cyrillic_YU - XKB_KEY_Cyrillic_yu);
754 else if (sym >= XKB_KEY_Cyrillic_yu && sym <= XKB_KEY_Cyrillic_hardsign)
755 *upper += (XKB_KEY_Cyrillic_YU - XKB_KEY_Cyrillic_yu);
758 /* Assume the KeySym is a legal value (ignore discontinuities) */
759 if (sym >= XKB_KEY_Greek_ALPHAaccent && sym <= XKB_KEY_Greek_OMEGAaccent)
760 *lower += (XKB_KEY_Greek_alphaaccent - XKB_KEY_Greek_ALPHAaccent);
761 else if (sym >= XKB_KEY_Greek_alphaaccent && sym <= XKB_KEY_Greek_omegaaccent &&
762 sym != XKB_KEY_Greek_iotaaccentdieresis &&
763 sym != XKB_KEY_Greek_upsilonaccentdieresis)
764 *upper -= (XKB_KEY_Greek_alphaaccent - XKB_KEY_Greek_ALPHAaccent);
765 else if (sym >= XKB_KEY_Greek_ALPHA && sym <= XKB_KEY_Greek_OMEGA)
766 *lower += (XKB_KEY_Greek_alpha - XKB_KEY_Greek_ALPHA);
767 else if (sym >= XKB_KEY_Greek_alpha && sym <= XKB_KEY_Greek_omega &&
768 sym != XKB_KEY_Greek_finalsmallsigma)
769 *upper -= (XKB_KEY_Greek_alpha - XKB_KEY_Greek_ALPHA);
771 case 0x13: /* Latin 9 */
772 if (sym == XKB_KEY_OE)
774 else if (sym == XKB_KEY_oe)
776 else if (sym == XKB_KEY_Ydiaeresis)
777 *lower = XKB_KEY_ydiaeresis;