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