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 & ((unsigned long) ~0x1fffffff)) != 0) {
68 snprintf(buffer, size, "Invalid");
72 size_t lo = 0, hi = ARRAY_SIZE(keysym_to_name) - 1;
74 size_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 * Find the correct keysym if one case-insensitive match is given.
97 * The name_to_keysym table is sorted by istrcmp(). So the binary search may return
98 * _any_ of all possible case-insensitive duplicates. This function searches the
99 * returned entry @entry, all previous and all next entries that match by
100 * case-insensitive comparison and returns the exact match to @name. If @icase
101 * is true, then this returns the best case-insensitive match instead of a
103 * The "best" case-insensitive match is the lower-case keysym which we find with
104 * the help of xkb_keysym_is_lower().
105 * The only keysyms that only differ by letter-case are keysyms that are
106 * available as lower-case and upper-case variant (like KEY_a and KEY_A). So
107 * returning the first lower-case match is enough in this case.
109 static const struct name_keysym *
110 find_sym(const struct name_keysym *entry, const char *name, bool icase)
112 const struct name_keysym *iter, *last;
113 size_t len = ARRAY_SIZE(name_to_keysym);
118 if (!icase && strcmp(get_name(entry), name) == 0)
120 if (icase && xkb_keysym_is_lower(entry->keysym))
123 for (iter = entry - 1; iter >= name_to_keysym; --iter) {
124 if (!icase && strcmp(get_name(iter), name) == 0)
126 if (istrcmp(get_name(iter), get_name(entry)) != 0)
128 if (icase && xkb_keysym_is_lower(iter->keysym))
132 last = name_to_keysym + len;
133 for (iter = entry + 1; iter < last; ++iter) {
134 if (!icase && strcmp(get_name(iter), name) == 0)
136 if (istrcmp(get_name(iter), get_name(entry)) != 0)
138 if (icase && xkb_keysym_is_lower(iter->keysym))
147 XKB_EXPORT xkb_keysym_t
148 xkb_keysym_from_name(const char *s, enum xkb_keysym_flags flags)
150 const struct name_keysym *entry = NULL;
153 bool icase = (flags & XKB_KEYSYM_CASE_INSENSITIVE);
155 if (flags & ~XKB_KEYSYM_CASE_INSENSITIVE)
156 return XKB_KEY_NoSymbol;
158 size_t lo = 0, hi = ARRAY_SIZE(name_to_keysym) - 1;
160 size_t mid = (lo + hi) / 2;
161 int cmp = istrcmp(s, get_name(&name_to_keysym[mid]));
164 } else if (cmp < 0) {
167 entry = &name_to_keysym[mid];
171 entry = find_sym(entry, s, icase);
173 return entry->keysym;
175 if (*s == 'U' || (icase && *s == 'u')) {
176 val = strtoul(&s[1], &tmp, 16);
177 if (tmp && *tmp != '\0')
178 return XKB_KEY_NoSymbol;
180 if (val < 0x20 || (val > 0x7e && val < 0xa0))
181 return XKB_KEY_NoSymbol;
185 return XKB_KEY_NoSymbol;
186 return val | 0x01000000;
188 else if (s[0] == '0' && (s[1] == 'x' || (icase && s[1] == 'X'))) {
189 val = strtoul(&s[2], &tmp, 16);
190 if (tmp && *tmp != '\0')
191 return XKB_KEY_NoSymbol;
196 /* Stupid inconsistency between the headers and XKeysymDB: the former has
197 * no separating underscore, while some XF86* syms in the latter did.
198 * As a last ditch effort, try without. */
199 if (strncmp(s, "XF86_", 5) == 0 ||
200 (icase && istrncmp(s, "XF86_", 5) == 0)) {
204 return XKB_KEY_NoSymbol;
205 memmove(&tmp[4], &tmp[5], strlen(s) - 5 + 1);
206 ret = xkb_keysym_from_name(tmp, flags);
211 return XKB_KEY_NoSymbol;
215 xkb_keysym_is_keypad(xkb_keysym_t keysym)
217 return keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_Equal;
222 xkb_keysym_is_modifier(xkb_keysym_t keysym)
225 (keysym >= XKB_KEY_Shift_L && keysym <= XKB_KEY_Hyper_R) ||
226 /* libX11 only goes upto XKB_KEY_ISO_Level5_Lock. */
227 (keysym >= XKB_KEY_ISO_Lock && keysym <= XKB_KEY_ISO_Last_Group_Lock) ||
228 keysym == XKB_KEY_Mode_switch ||
229 keysym == XKB_KEY_Num_Lock;
233 XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper);
236 xkb_keysym_is_lower(xkb_keysym_t ks)
238 xkb_keysym_t lower, upper;
240 XConvertCase(ks, &lower, &upper);
245 return (ks == lower ? true : false);
249 xkb_keysym_is_upper(xkb_keysym_t ks)
251 xkb_keysym_t lower, upper;
253 XConvertCase(ks, &lower, &upper);
258 return (ks == upper ? true : false);
261 XKB_EXPORT xkb_keysym_t
262 xkb_keysym_to_lower(xkb_keysym_t ks)
264 xkb_keysym_t lower, upper;
266 XConvertCase(ks, &lower, &upper);
271 XKB_EXPORT xkb_keysym_t
272 xkb_keysym_to_upper(xkb_keysym_t ks)
274 xkb_keysym_t lower, upper;
276 XConvertCase(ks, &lower, &upper);
282 * The following is copied verbatim from libX11:src/KeyBind.c, commit
283 * d45b3fc19fbe95c41afc4e51d768df6d42332010, with the following changes:
284 * - unsigned -> uint32_t
285 * - unsigend short -> uint16_t
288 * XXX: If newlocale() and iswlower_l()/iswupper_l() interface ever
289 * become portable, we should use that in conjunction with
290 * xkb_keysym_to_utf32(), instead of all this stuff. We should
291 * be sure to give the same results as libX11, though, and be
292 * locale independent; this information is used by xkbcomp to
293 * find the automatic type to assign to key groups.
297 UCSConvertCase(uint32_t code, xkb_keysym_t *lower, xkb_keysym_t *upper)
299 /* Case conversion for UCS, as in Unicode Data version 4.0.0 */
300 /* NB: Only converts simple one-to-one mappings. */
302 /* Tables are used where they take less space than */
303 /* the code to work out the mappings. Zero values mean */
304 /* undefined code points. */
306 static uint16_t const IPAExt_upper_mapping[] = { /* part only */
307 0x0181, 0x0186, 0x0255, 0x0189, 0x018A,
308 0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F,
309 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267,
310 0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C,
311 0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277,
312 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F,
313 0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287,
314 0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F,
315 0x0290, 0x0291, 0x01B7
318 static uint16_t const LatinExtB_upper_mapping[] = { /* first part only */
319 0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187,
320 0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F,
321 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197,
322 0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F,
323 0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7,
324 0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF,
325 0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7,
326 0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7,
327 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7,
328 0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA
331 static uint16_t const LatinExtB_lower_mapping[] = { /* first part only */
332 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188,
333 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259,
334 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268,
335 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275,
336 0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x0280, 0x01A8,
337 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0,
338 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292,
339 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF,
340 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9,
341 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC
344 static uint16_t const Greek_upper_mapping[] = {
345 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
346 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
347 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x0386, 0x0387,
348 0x0388, 0x0389, 0x038A, 0x0000, 0x038C, 0x0000, 0x038E, 0x038F,
349 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
350 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
351 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
352 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A,
353 0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
354 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F,
355 0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7,
356 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x0000,
357 0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03D7,
358 0x03D8, 0x03D8, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE,
359 0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6,
360 0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE,
361 0x039A, 0x03A1, 0x03F9, 0x03F3, 0x03F4, 0x0395, 0x03F6, 0x03F7,
362 0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x0000, 0x0000, 0x0000, 0x0000
365 static uint16_t const Greek_lower_mapping[] = {
366 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000,
367 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000,
368 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x03AC, 0x0387,
369 0x03AD, 0x03AE, 0x03AF, 0x0000, 0x03CC, 0x0000, 0x03CD, 0x03CE,
370 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
371 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
372 0x03C0, 0x03C1, 0x0000, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
373 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF,
374 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7,
375 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF,
376 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7,
377 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000,
378 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7,
379 0x03D9, 0x03D9, 0x03DB, 0x03DB, 0x03DD, 0x03DD, 0x03DF, 0x03DF,
380 0x03E1, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7,
381 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF,
382 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03B8, 0x03F5, 0x03F6, 0x03F8,
383 0x03F8, 0x03F2, 0x03FB, 0x03FB, 0x0000, 0x0000, 0x0000, 0x0000
386 static uint16_t const GreekExt_lower_mapping[] = {
387 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
388 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07,
389 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
390 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000,
391 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
392 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27,
393 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
394 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37,
395 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
396 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000,
397 0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57,
398 0x0000, 0x1F51, 0x0000, 0x1F53, 0x0000, 0x1F55, 0x0000, 0x1F57,
399 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
400 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67,
401 0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77,
402 0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x0000, 0x0000,
403 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
404 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87,
405 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
406 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97,
407 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
408 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7,
409 0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
410 0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1FBD, 0x1FBE, 0x1FBF,
411 0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
412 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF,
413 0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
414 0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
415 0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7,
416 0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF,
417 0x0000, 0x0000, 0x1FF2, 0x1FF3, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
418 0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x1FFD, 0x1FFE, 0x0000
421 static uint16_t const GreekExt_upper_mapping[] = {
422 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
423 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F,
424 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
425 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000,
426 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
427 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F,
428 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
429 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F,
430 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
431 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000,
432 0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F,
433 0x0000, 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F,
434 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
435 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F,
436 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB,
437 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x0000, 0x0000,
438 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
439 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F,
440 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
441 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F,
442 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
443 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF,
444 0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7,
445 0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x0399, 0x1FBF,
446 0x1FC0, 0x1FC1, 0x1FC2, 0x1FCC, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7,
447 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF,
448 0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7,
449 0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF,
450 0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7,
451 0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF,
452 0x0000, 0x0000, 0x1FF2, 0x1FFC, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7,
453 0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x0000
459 /* Basic Latin and Latin-1 Supplement, U+0000 to U+00FF */
460 if (code <= 0x00ff) {
461 if (code >= 0x0041 && code <= 0x005a) /* A-Z */
463 else if (code >= 0x0061 && code <= 0x007a) /* a-z */
465 else if ( (code >= 0x00c0 && code <= 0x00d6) ||
466 (code >= 0x00d8 && code <= 0x00de) )
468 else if ( (code >= 0x00e0 && code <= 0x00f6) ||
469 (code >= 0x00f8 && code <= 0x00fe) )
471 else if (code == 0x00ff) /* y with diaeresis */
473 else if (code == 0x00b5) /* micro sign */
475 else if (code == 0x00df) /* ssharp */
480 /* Latin Extended-A, U+0100 to U+017F */
481 if (code >= 0x0100 && code <= 0x017f) {
482 if ( (code >= 0x0100 && code <= 0x012f) ||
483 (code >= 0x0132 && code <= 0x0137) ||
484 (code >= 0x014a && code <= 0x0177) ) {
488 else if ( (code >= 0x0139 && code <= 0x0148) ||
489 (code >= 0x0179 && code <= 0x017e) ) {
495 else if (code == 0x0130)
497 else if (code == 0x0131)
499 else if (code == 0x0178)
501 else if (code == 0x017f)
506 /* Latin Extended-B, U+0180 to U+024F */
507 if (code >= 0x0180 && code <= 0x024f) {
508 if (code >= 0x01cd && code <= 0x01dc) {
514 else if ( (code >= 0x01de && code <= 0x01ef) ||
515 (code >= 0x01f4 && code <= 0x01f5) ||
516 (code >= 0x01f8 && code <= 0x021f) ||
517 (code >= 0x0222 && code <= 0x0233) ) {
521 else if (code >= 0x0180 && code <= 0x01cc) {
522 *lower = LatinExtB_lower_mapping[code - 0x0180];
523 *upper = LatinExtB_upper_mapping[code - 0x0180];
525 else if (code == 0x01dd)
527 else if (code == 0x01f1 || code == 0x01f2) {
531 else if (code == 0x01f3)
533 else if (code == 0x01f6)
535 else if (code == 0x01f7)
537 else if (code == 0x0220)
542 /* IPA Extensions, U+0250 to U+02AF */
543 if (code >= 0x0253 && code <= 0x0292) {
544 *upper = IPAExt_upper_mapping[code - 0x0253];
547 /* Combining Diacritical Marks, U+0300 to U+036F */
548 if (code == 0x0345) {
552 /* Greek and Coptic, U+0370 to U+03FF */
553 if (code >= 0x0370 && code <= 0x03ff) {
554 *lower = Greek_lower_mapping[code - 0x0370];
555 *upper = Greek_upper_mapping[code - 0x0370];
562 /* Cyrillic and Cyrillic Supplementary, U+0400 to U+052F */
563 if ( (code >= 0x0400 && code <= 0x04ff) ||
564 (code >= 0x0500 && code <= 0x052f) ) {
565 if (code >= 0x0400 && code <= 0x040f)
567 else if (code >= 0x0410 && code <= 0x042f)
569 else if (code >= 0x0430 && code <= 0x044f)
571 else if (code >= 0x0450 && code <= 0x045f)
573 else if ( (code >= 0x0460 && code <= 0x0481) ||
574 (code >= 0x048a && code <= 0x04bf) ||
575 (code >= 0x04d0 && code <= 0x04f5) ||
576 (code >= 0x04f8 && code <= 0x04f9) ||
577 (code >= 0x0500 && code <= 0x050f) ) {
581 else if (code >= 0x04c1 && code <= 0x04ce) {
589 /* Armenian, U+0530 to U+058F */
590 if (code >= 0x0530 && code <= 0x058f) {
591 if (code >= 0x0531 && code <= 0x0556)
593 else if (code >=0x0561 && code <= 0x0586)
597 /* Latin Extended Additional, U+1E00 to U+1EFF */
598 if (code >= 0x1e00 && code <= 0x1eff) {
599 if ( (code >= 0x1e00 && code <= 0x1e95) ||
600 (code >= 0x1ea0 && code <= 0x1ef9) ) {
604 else if (code == 0x1e9b)
606 else if (code == 0x1e9e)
607 *lower = 0x00df; /* ssharp */
610 /* Greek Extended, U+1F00 to U+1FFF */
611 if (code >= 0x1f00 && code <= 0x1fff) {
612 *lower = GreekExt_lower_mapping[code - 0x1f00];
613 *upper = GreekExt_upper_mapping[code - 0x1f00];
620 /* Letterlike Symbols, U+2100 to U+214F */
621 if (code >= 0x2100 && code <= 0x214f) {
623 case 0x2126: *lower = 0x03c9; break;
624 case 0x212a: *lower = 0x006b; break;
625 case 0x212b: *lower = 0x00e5; break;
628 /* Number Forms, U+2150 to U+218F */
629 else if (code >= 0x2160 && code <= 0x216f)
631 else if (code >= 0x2170 && code <= 0x217f)
633 /* Enclosed Alphanumerics, U+2460 to U+24FF */
634 else if (code >= 0x24b6 && code <= 0x24cf)
636 else if (code >= 0x24d0 && code <= 0x24e9)
638 /* Halfwidth and Fullwidth Forms, U+FF00 to U+FFEF */
639 else if (code >= 0xff21 && code <= 0xff3a)
641 else if (code >= 0xff41 && code <= 0xff5a)
643 /* Deseret, U+10400 to U+104FF */
644 else if (code >= 0x10400 && code <= 0x10427)
646 else if (code >= 0x10428 && code <= 0x1044f)
651 XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper)
655 UCSConvertCase(sym, lower, upper);
660 if ((sym & 0xff000000) == 0x01000000) {
661 UCSConvertCase((sym & 0x00ffffff), lower, upper);
662 *upper |= 0x01000000;
663 *lower |= 0x01000000;
673 case 1: /* Latin 2 */
674 /* Assume the KeySym is a legal value (ignore discontinuities) */
675 if (sym == XKB_KEY_Aogonek)
676 *lower = XKB_KEY_aogonek;
677 else if (sym >= XKB_KEY_Lstroke && sym <= XKB_KEY_Sacute)
678 *lower += (XKB_KEY_lstroke - XKB_KEY_Lstroke);
679 else if (sym >= XKB_KEY_Scaron && sym <= XKB_KEY_Zacute)
680 *lower += (XKB_KEY_scaron - XKB_KEY_Scaron);
681 else if (sym >= XKB_KEY_Zcaron && sym <= XKB_KEY_Zabovedot)
682 *lower += (XKB_KEY_zcaron - XKB_KEY_Zcaron);
683 else if (sym == XKB_KEY_aogonek)
684 *upper = XKB_KEY_Aogonek;
685 else if (sym >= XKB_KEY_lstroke && sym <= XKB_KEY_sacute)
686 *upper -= (XKB_KEY_lstroke - XKB_KEY_Lstroke);
687 else if (sym >= XKB_KEY_scaron && sym <= XKB_KEY_zacute)
688 *upper -= (XKB_KEY_scaron - XKB_KEY_Scaron);
689 else if (sym >= XKB_KEY_zcaron && sym <= XKB_KEY_zabovedot)
690 *upper -= (XKB_KEY_zcaron - XKB_KEY_Zcaron);
691 else if (sym >= XKB_KEY_Racute && sym <= XKB_KEY_Tcedilla)
692 *lower += (XKB_KEY_racute - XKB_KEY_Racute);
693 else if (sym >= XKB_KEY_racute && sym <= XKB_KEY_tcedilla)
694 *upper -= (XKB_KEY_racute - XKB_KEY_Racute);
696 case 2: /* Latin 3 */
697 /* Assume the KeySym is a legal value (ignore discontinuities) */
698 if (sym >= XKB_KEY_Hstroke && sym <= XKB_KEY_Hcircumflex)
699 *lower += (XKB_KEY_hstroke - XKB_KEY_Hstroke);
700 else if (sym >= XKB_KEY_Gbreve && sym <= XKB_KEY_Jcircumflex)
701 *lower += (XKB_KEY_gbreve - XKB_KEY_Gbreve);
702 else if (sym >= XKB_KEY_hstroke && sym <= XKB_KEY_hcircumflex)
703 *upper -= (XKB_KEY_hstroke - XKB_KEY_Hstroke);
704 else if (sym >= XKB_KEY_gbreve && sym <= XKB_KEY_jcircumflex)
705 *upper -= (XKB_KEY_gbreve - XKB_KEY_Gbreve);
706 else if (sym >= XKB_KEY_Cabovedot && sym <= XKB_KEY_Scircumflex)
707 *lower += (XKB_KEY_cabovedot - XKB_KEY_Cabovedot);
708 else if (sym >= XKB_KEY_cabovedot && sym <= XKB_KEY_scircumflex)
709 *upper -= (XKB_KEY_cabovedot - XKB_KEY_Cabovedot);
711 case 3: /* Latin 4 */
712 /* Assume the KeySym is a legal value (ignore discontinuities) */
713 if (sym >= XKB_KEY_Rcedilla && sym <= XKB_KEY_Tslash)
714 *lower += (XKB_KEY_rcedilla - XKB_KEY_Rcedilla);
715 else if (sym >= XKB_KEY_rcedilla && sym <= XKB_KEY_tslash)
716 *upper -= (XKB_KEY_rcedilla - XKB_KEY_Rcedilla);
717 else if (sym == XKB_KEY_ENG)
718 *lower = XKB_KEY_eng;
719 else if (sym == XKB_KEY_eng)
720 *upper = XKB_KEY_ENG;
721 else if (sym >= XKB_KEY_Amacron && sym <= XKB_KEY_Umacron)
722 *lower += (XKB_KEY_amacron - XKB_KEY_Amacron);
723 else if (sym >= XKB_KEY_amacron && sym <= XKB_KEY_umacron)
724 *upper -= (XKB_KEY_amacron - XKB_KEY_Amacron);
726 case 6: /* Cyrillic */
727 /* Assume the KeySym is a legal value (ignore discontinuities) */
728 if (sym >= XKB_KEY_Serbian_DJE && sym <= XKB_KEY_Serbian_DZE)
729 *lower -= (XKB_KEY_Serbian_DJE - XKB_KEY_Serbian_dje);
730 else if (sym >= XKB_KEY_Serbian_dje && sym <= XKB_KEY_Serbian_dze)
731 *upper += (XKB_KEY_Serbian_DJE - XKB_KEY_Serbian_dje);
732 else if (sym >= XKB_KEY_Cyrillic_YU && sym <= XKB_KEY_Cyrillic_HARDSIGN)
733 *lower -= (XKB_KEY_Cyrillic_YU - XKB_KEY_Cyrillic_yu);
734 else if (sym >= XKB_KEY_Cyrillic_yu && sym <= XKB_KEY_Cyrillic_hardsign)
735 *upper += (XKB_KEY_Cyrillic_YU - XKB_KEY_Cyrillic_yu);
738 /* Assume the KeySym is a legal value (ignore discontinuities) */
739 if (sym >= XKB_KEY_Greek_ALPHAaccent && sym <= XKB_KEY_Greek_OMEGAaccent)
740 *lower += (XKB_KEY_Greek_alphaaccent - XKB_KEY_Greek_ALPHAaccent);
741 else if (sym >= XKB_KEY_Greek_alphaaccent && sym <= XKB_KEY_Greek_omegaaccent &&
742 sym != XKB_KEY_Greek_iotaaccentdieresis &&
743 sym != XKB_KEY_Greek_upsilonaccentdieresis)
744 *upper -= (XKB_KEY_Greek_alphaaccent - XKB_KEY_Greek_ALPHAaccent);
745 else if (sym >= XKB_KEY_Greek_ALPHA && sym <= XKB_KEY_Greek_OMEGA)
746 *lower += (XKB_KEY_Greek_alpha - XKB_KEY_Greek_ALPHA);
747 else if (sym >= XKB_KEY_Greek_alpha && sym <= XKB_KEY_Greek_omega &&
748 sym != XKB_KEY_Greek_finalsmallsigma)
749 *upper -= (XKB_KEY_Greek_alpha - XKB_KEY_Greek_ALPHA);
751 case 0x13: /* Latin 9 */
752 if (sym == XKB_KEY_OE)
754 else if (sym == XKB_KEY_oe)
756 else if (sym == XKB_KEY_Ydiaeresis)
757 *lower = XKB_KEY_ydiaeresis;