1 /* 2 * Copyright 1985, 1987, 1990, 1998 The Open Group 3 * 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: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 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. 20 * 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. 25 */ 26 27 /* 28 * Copyright 2009 Dan Nicholson 29 * 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: 36 * 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 39 * Software. 40 * 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. 48 */ 49 50 #include <stdlib.h> 51 #include "xkbcommon/xkbcommon.h" 52 #include "utils.h" 53 #include "keysym.h" 54 #include "ks_tables.h" 55 56 static inline const char * 57 get_name(const struct name_keysym *entry) 58 { 59 return keysym_names + entry->offset; 60 } 61 62 static int 63 compare_by_keysym(const void *a, const void *b) 64 { 65 const xkb_keysym_t *key = a; 66 const struct name_keysym *entry = b; 67 if (*key < entry->keysym) 68 return -1; 69 if (*key > entry->keysym) 70 return 1; 71 return 0; 72 } 73 74 static int 75 compare_by_name(const void *a, const void *b) 76 { 77 const char *key = a; 78 const struct name_keysym *entry = b; 79 return strcasecmp(key, get_name(entry)); 80 } 81 82 XKB_EXPORT int 83 xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size) 84 { 85 const struct name_keysym *entry; 86 87 if ((ks & ((unsigned long) ~0x1fffffff)) != 0) { 88 snprintf(buffer, size, "Invalid"); 89 return -1; 90 } 91 92 entry = bsearch(&ks, keysym_to_name, 93 ARRAY_SIZE(keysym_to_name), 94 sizeof(*keysym_to_name), 95 compare_by_keysym); 96 if (entry) 97 return snprintf(buffer, size, "%s", get_name(entry)); 98 99 /* Unnamed Unicode codepoint. */ 100 if (ks >= 0x01000100 && ks <= 0x0110ffff) { 101 const int width = (ks & 0xff0000UL) ? 8 : 4; 102 return snprintf(buffer, size, "U%0*lX", width, ks & 0xffffffUL); 103 } 104 105 /* Unnamed, non-Unicode, symbol (shouldn't generally happen). */ 106 return snprintf(buffer, size, "0x%08x", ks); 107 } 108 109 /* 110 * Find the correct keysym if one case-insensitive match is given. 111 * 112 * The name_to_keysym table is sorted by strcasecmp(). So bsearch() may return 113 * _any_ of all possible case-insensitive duplicates. This function searches the 114 * returned entry @entry, all previous and all next entries that match by 115 * case-insensitive comparison and returns the exact match to @name. If @icase 116 * is true, then this returns the best case-insensitive match instead of a 117 * correct match. 118 * The "best" case-insensitive match is the lower-case keysym which we find with 119 * the help of xkb_keysym_is_lower(). 120 * The only keysyms that only differ by letter-case are keysyms that are 121 * available as lower-case and upper-case variant (like KEY_a and KEY_A). So 122 * returning the first lower-case match is enough in this case. 123 */ 124 static const struct name_keysym * 125 find_sym(const struct name_keysym *entry, const char *name, bool icase) 126 { 127 const struct name_keysym *iter, *last; 128 size_t len = ARRAY_SIZE(name_to_keysym); 129 130 if (!entry) 131 return NULL; 132 133 if (!icase && strcmp(get_name(entry), name) == 0) 134 return entry; 135 if (icase && xkb_keysym_is_lower(entry->keysym)) 136 return entry; 137 138 for (iter = entry - 1; iter >= name_to_keysym; --iter) { 139 if (!icase && strcmp(get_name(iter), name) == 0) 140 return iter; 141 if (strcasecmp(get_name(iter), get_name(entry)) != 0) 142 break; 143 if (icase && xkb_keysym_is_lower(iter->keysym)) 144 return iter; 145 } 146 147 last = name_to_keysym + len; 148 for (iter = entry + 1; iter < last; ++iter) { 149 if (!icase && strcmp(get_name(iter), name) == 0) 150 return iter; 151 if (strcasecmp(get_name(iter), get_name(entry)) != 0) 152 break; 153 if (icase && xkb_keysym_is_lower(iter->keysym)) 154 return iter; 155 } 156 157 if (icase) 158 return entry; 159 return NULL; 160 } 161 162 XKB_EXPORT xkb_keysym_t 163 xkb_keysym_from_name(const char *s, enum xkb_keysym_flags flags) 164 { 165 const struct name_keysym *entry; 166 char *tmp; 167 xkb_keysym_t val; 168 bool icase = (flags & XKB_KEYSYM_CASE_INSENSITIVE); 169 170 if (flags & ~XKB_KEYSYM_CASE_INSENSITIVE) 171 return XKB_KEY_NoSymbol; 172 173 entry = bsearch(s, name_to_keysym, 174 ARRAY_SIZE(name_to_keysym), 175 sizeof(*name_to_keysym), 176 compare_by_name); 177 entry = find_sym(entry, s, icase); 178 if (entry) 179 return entry->keysym; 180 181 if (*s == 'U' || (icase && *s == 'u')) { 182 val = strtoul(&s[1], &tmp, 16); 183 if (tmp && *tmp != '\0') 184 return XKB_KEY_NoSymbol; 185 186 if (val < 0x20 || (val > 0x7e && val < 0xa0)) 187 return XKB_KEY_NoSymbol; 188 if (val < 0x100) 189 return val; 190 if (val > 0x10ffff) 191 return XKB_KEY_NoSymbol; 192 return val | 0x01000000; 193 } 194 else if (s[0] == '0' && (s[1] == 'x' || (icase && s[1] == 'X'))) { 195 val = strtoul(&s[2], &tmp, 16); 196 if (tmp && *tmp != '\0') 197 return XKB_KEY_NoSymbol; 198 199 return val; 200 } 201 202 /* Stupid inconsistency between the headers and XKeysymDB: the former has 203 * no separating underscore, while some XF86* syms in the latter did. 204 * As a last ditch effort, try without. */ 205 if (strncmp(s, "XF86_", 5) == 0 || 206 (icase && strncasecmp(s, "XF86_", 5) == 0)) { 207 xkb_keysym_t ret; 208 tmp = strdup(s); 209 if (!tmp) 210 return XKB_KEY_NoSymbol; 211 memmove(&tmp[4], &tmp[5], strlen(s) - 5 + 1); 212 ret = xkb_keysym_from_name(tmp, flags); 213 free(tmp); 214 return ret; 215 } 216 217 return XKB_KEY_NoSymbol; 218 } 219 220 bool 221 xkb_keysym_is_keypad(xkb_keysym_t keysym) 222 { 223 return keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_Equal; 224 } 225 226 227 bool 228 xkb_keysym_is_modifier(xkb_keysym_t keysym) 229 { 230 return 231 (keysym >= XKB_KEY_Shift_L && keysym <= XKB_KEY_Hyper_R) || 232 /* libX11 only goes upto XKB_KEY_ISO_Level5_Lock. */ 233 (keysym >= XKB_KEY_ISO_Lock && keysym <= XKB_KEY_ISO_Last_Group_Lock) || 234 keysym == XKB_KEY_Mode_switch || 235 keysym == XKB_KEY_Num_Lock; 236 } 237 238 static void 239 XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper); 240 241 bool 242 xkb_keysym_is_lower(xkb_keysym_t ks) 243 { 244 xkb_keysym_t lower, upper; 245 246 XConvertCase(ks, &lower, &upper); 247 248 if (lower == upper) 249 return false; 250 251 return (ks == lower ? true : false); 252 } 253 254 bool 255 xkb_keysym_is_upper(xkb_keysym_t ks) 256 { 257 xkb_keysym_t lower, upper; 258 259 XConvertCase(ks, &lower, &upper); 260 261 if (lower == upper) 262 return false; 263 264 return (ks == upper ? true : false); 265 } 266 267 xkb_keysym_t 268 xkb_keysym_to_lower(xkb_keysym_t ks) 269 { 270 xkb_keysym_t lower, upper; 271 272 XConvertCase(ks, &lower, &upper); 273 274 return lower; 275 } 276 277 xkb_keysym_t 278 xkb_keysym_to_upper(xkb_keysym_t ks) 279 { 280 xkb_keysym_t lower, upper; 281 282 XConvertCase(ks, &lower, &upper); 283 284 return upper; 285 } 286 287 /* 288 * The following is copied verbatim from libX11:src/KeyBind.c, commit 289 * d45b3fc19fbe95c41afc4e51d768df6d42332010, with the following changes: 290 * - unsigned -> uint32_t 291 * - unsigend short -> uint16_t 292 * - s/XK_/XKB_KEY_ 293 * 294 * XXX: If newlocale() and iswlower_l()/iswupper_l() interface ever 295 * become portable, we should use that in conjunction with 296 * xkb_keysym_to_utf32(), instead of all this stuff. We should 297 * be sure to give the same results as libX11, though, and be 298 * locale independent; this information is used by xkbcomp to 299 * find the automatic type to assign to key groups. 300 */ 301 302 static void 303 UCSConvertCase(uint32_t code, xkb_keysym_t *lower, xkb_keysym_t *upper) 304 { 305 /* Case conversion for UCS, as in Unicode Data version 4.0.0 */ 306 /* NB: Only converts simple one-to-one mappings. */ 307 308 /* Tables are used where they take less space than */ 309 /* the code to work out the mappings. Zero values mean */ 310 /* undefined code points. */ 311 312 static uint16_t const IPAExt_upper_mapping[] = { /* part only */ 313 0x0181, 0x0186, 0x0255, 0x0189, 0x018A, 314 0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F, 315 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267, 316 0x0197, 0x0196, 0x026A, 0x026B, 0x026C, 0x026D, 0x026E, 0x019C, 317 0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277, 318 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x027D, 0x027E, 0x027F, 319 0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287, 320 0x01AE, 0x0289, 0x01B1, 0x01B2, 0x028C, 0x028D, 0x028E, 0x028F, 321 0x0290, 0x0291, 0x01B7 322 }; 323 324 static uint16_t const LatinExtB_upper_mapping[] = { /* first part only */ 325 0x0180, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, 326 0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F, 327 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197, 328 0x0198, 0x0198, 0x019A, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F, 329 0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7, 330 0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF, 331 0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7, 332 0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7, 333 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C4, 0x01C4, 0x01C7, 334 0x01C7, 0x01C7, 0x01CA, 0x01CA, 0x01CA 335 }; 336 337 static uint16_t const LatinExtB_lower_mapping[] = { /* first part only */ 338 0x0180, 0x0253, 0x0183, 0x0183, 0x0185, 0x0185, 0x0254, 0x0188, 339 0x0188, 0x0256, 0x0257, 0x018C, 0x018C, 0x018D, 0x01DD, 0x0259, 340 0x025B, 0x0192, 0x0192, 0x0260, 0x0263, 0x0195, 0x0269, 0x0268, 341 0x0199, 0x0199, 0x019A, 0x019B, 0x026F, 0x0272, 0x019E, 0x0275, 342 0x01A1, 0x01A1, 0x01A3, 0x01A3, 0x01A5, 0x01A5, 0x0280, 0x01A8, 343 0x01A8, 0x0283, 0x01AA, 0x01AB, 0x01AD, 0x01AD, 0x0288, 0x01B0, 344 0x01B0, 0x028A, 0x028B, 0x01B4, 0x01B4, 0x01B6, 0x01B6, 0x0292, 345 0x01B9, 0x01B9, 0x01BA, 0x01BB, 0x01BD, 0x01BD, 0x01BE, 0x01BF, 346 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C6, 0x01C6, 0x01C6, 0x01C9, 347 0x01C9, 0x01C9, 0x01CC, 0x01CC, 0x01CC 348 }; 349 350 static uint16_t const Greek_upper_mapping[] = { 351 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000, 352 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000, 353 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x0386, 0x0387, 354 0x0388, 0x0389, 0x038A, 0x0000, 0x038C, 0x0000, 0x038E, 0x038F, 355 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 356 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 357 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 358 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x0386, 0x0388, 0x0389, 0x038A, 359 0x03B0, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 360 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 361 0x03A0, 0x03A1, 0x03A3, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 362 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x038C, 0x038E, 0x038F, 0x0000, 363 0x0392, 0x0398, 0x03D2, 0x03D3, 0x03D4, 0x03A6, 0x03A0, 0x03D7, 364 0x03D8, 0x03D8, 0x03DA, 0x03DA, 0x03DC, 0x03DC, 0x03DE, 0x03DE, 365 0x03E0, 0x03E0, 0x03E2, 0x03E2, 0x03E4, 0x03E4, 0x03E6, 0x03E6, 366 0x03E8, 0x03E8, 0x03EA, 0x03EA, 0x03EC, 0x03EC, 0x03EE, 0x03EE, 367 0x039A, 0x03A1, 0x03F9, 0x03F3, 0x03F4, 0x0395, 0x03F6, 0x03F7, 368 0x03F7, 0x03F9, 0x03FA, 0x03FA, 0x0000, 0x0000, 0x0000, 0x0000 369 }; 370 371 static uint16_t const Greek_lower_mapping[] = { 372 0x0000, 0x0000, 0x0000, 0x0000, 0x0374, 0x0375, 0x0000, 0x0000, 373 0x0000, 0x0000, 0x037A, 0x0000, 0x0000, 0x0000, 0x037E, 0x0000, 374 0x0000, 0x0000, 0x0000, 0x0000, 0x0384, 0x0385, 0x03AC, 0x0387, 375 0x03AD, 0x03AE, 0x03AF, 0x0000, 0x03CC, 0x0000, 0x03CD, 0x03CE, 376 0x0390, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 377 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 378 0x03C0, 0x03C1, 0x0000, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 379 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 380 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 381 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 382 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 383 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000, 384 0x03D0, 0x03D1, 0x03D2, 0x03D3, 0x03D4, 0x03D5, 0x03D6, 0x03D7, 385 0x03D9, 0x03D9, 0x03DB, 0x03DB, 0x03DD, 0x03DD, 0x03DF, 0x03DF, 386 0x03E1, 0x03E1, 0x03E3, 0x03E3, 0x03E5, 0x03E5, 0x03E7, 0x03E7, 387 0x03E9, 0x03E9, 0x03EB, 0x03EB, 0x03ED, 0x03ED, 0x03EF, 0x03EF, 388 0x03F0, 0x03F1, 0x03F2, 0x03F3, 0x03B8, 0x03F5, 0x03F6, 0x03F8, 389 0x03F8, 0x03F2, 0x03FB, 0x03FB, 0x0000, 0x0000, 0x0000, 0x0000 390 }; 391 392 static uint16_t const GreekExt_lower_mapping[] = { 393 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07, 394 0x1F00, 0x1F01, 0x1F02, 0x1F03, 0x1F04, 0x1F05, 0x1F06, 0x1F07, 395 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000, 396 0x1F10, 0x1F11, 0x1F12, 0x1F13, 0x1F14, 0x1F15, 0x0000, 0x0000, 397 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27, 398 0x1F20, 0x1F21, 0x1F22, 0x1F23, 0x1F24, 0x1F25, 0x1F26, 0x1F27, 399 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37, 400 0x1F30, 0x1F31, 0x1F32, 0x1F33, 0x1F34, 0x1F35, 0x1F36, 0x1F37, 401 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000, 402 0x1F40, 0x1F41, 0x1F42, 0x1F43, 0x1F44, 0x1F45, 0x0000, 0x0000, 403 0x1F50, 0x1F51, 0x1F52, 0x1F53, 0x1F54, 0x1F55, 0x1F56, 0x1F57, 404 0x0000, 0x1F51, 0x0000, 0x1F53, 0x0000, 0x1F55, 0x0000, 0x1F57, 405 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67, 406 0x1F60, 0x1F61, 0x1F62, 0x1F63, 0x1F64, 0x1F65, 0x1F66, 0x1F67, 407 0x1F70, 0x1F71, 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1F76, 0x1F77, 408 0x1F78, 0x1F79, 0x1F7A, 0x1F7B, 0x1F7C, 0x1F7D, 0x0000, 0x0000, 409 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87, 410 0x1F80, 0x1F81, 0x1F82, 0x1F83, 0x1F84, 0x1F85, 0x1F86, 0x1F87, 411 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97, 412 0x1F90, 0x1F91, 0x1F92, 0x1F93, 0x1F94, 0x1F95, 0x1F96, 0x1F97, 413 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7, 414 0x1FA0, 0x1FA1, 0x1FA2, 0x1FA3, 0x1FA4, 0x1FA5, 0x1FA6, 0x1FA7, 415 0x1FB0, 0x1FB1, 0x1FB2, 0x1FB3, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7, 416 0x1FB0, 0x1FB1, 0x1F70, 0x1F71, 0x1FB3, 0x1FBD, 0x1FBE, 0x1FBF, 417 0x1FC0, 0x1FC1, 0x1FC2, 0x1FC3, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7, 418 0x1F72, 0x1F73, 0x1F74, 0x1F75, 0x1FC3, 0x1FCD, 0x1FCE, 0x1FCF, 419 0x1FD0, 0x1FD1, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7, 420 0x1FD0, 0x1FD1, 0x1F76, 0x1F77, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF, 421 0x1FE0, 0x1FE1, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FE5, 0x1FE6, 0x1FE7, 422 0x1FE0, 0x1FE1, 0x1F7A, 0x1F7B, 0x1FE5, 0x1FED, 0x1FEE, 0x1FEF, 423 0x0000, 0x0000, 0x1FF2, 0x1FF3, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7, 424 0x1F78, 0x1F79, 0x1F7C, 0x1F7D, 0x1FF3, 0x1FFD, 0x1FFE, 0x0000 425 }; 426 427 static uint16_t const GreekExt_upper_mapping[] = { 428 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, 429 0x1F08, 0x1F09, 0x1F0A, 0x1F0B, 0x1F0C, 0x1F0D, 0x1F0E, 0x1F0F, 430 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000, 431 0x1F18, 0x1F19, 0x1F1A, 0x1F1B, 0x1F1C, 0x1F1D, 0x0000, 0x0000, 432 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 433 0x1F28, 0x1F29, 0x1F2A, 0x1F2B, 0x1F2C, 0x1F2D, 0x1F2E, 0x1F2F, 434 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, 435 0x1F38, 0x1F39, 0x1F3A, 0x1F3B, 0x1F3C, 0x1F3D, 0x1F3E, 0x1F3F, 436 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000, 437 0x1F48, 0x1F49, 0x1F4A, 0x1F4B, 0x1F4C, 0x1F4D, 0x0000, 0x0000, 438 0x1F50, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F, 439 0x0000, 0x1F59, 0x0000, 0x1F5B, 0x0000, 0x1F5D, 0x0000, 0x1F5F, 440 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, 441 0x1F68, 0x1F69, 0x1F6A, 0x1F6B, 0x1F6C, 0x1F6D, 0x1F6E, 0x1F6F, 442 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB, 443 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, 0x0000, 0x0000, 444 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, 445 0x1F88, 0x1F89, 0x1F8A, 0x1F8B, 0x1F8C, 0x1F8D, 0x1F8E, 0x1F8F, 446 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, 447 0x1F98, 0x1F99, 0x1F9A, 0x1F9B, 0x1F9C, 0x1F9D, 0x1F9E, 0x1F9F, 448 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, 449 0x1FA8, 0x1FA9, 0x1FAA, 0x1FAB, 0x1FAC, 0x1FAD, 0x1FAE, 0x1FAF, 450 0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, 0x1FB4, 0x0000, 0x1FB6, 0x1FB7, 451 0x1FB8, 0x1FB9, 0x1FBA, 0x1FBB, 0x1FBC, 0x1FBD, 0x0399, 0x1FBF, 452 0x1FC0, 0x1FC1, 0x1FC2, 0x1FCC, 0x1FC4, 0x0000, 0x1FC6, 0x1FC7, 453 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FCC, 0x1FCD, 0x1FCE, 0x1FCF, 454 0x1FD8, 0x1FD9, 0x1FD2, 0x1FD3, 0x0000, 0x0000, 0x1FD6, 0x1FD7, 455 0x1FD8, 0x1FD9, 0x1FDA, 0x1FDB, 0x0000, 0x1FDD, 0x1FDE, 0x1FDF, 456 0x1FE8, 0x1FE9, 0x1FE2, 0x1FE3, 0x1FE4, 0x1FEC, 0x1FE6, 0x1FE7, 457 0x1FE8, 0x1FE9, 0x1FEA, 0x1FEB, 0x1FEC, 0x1FED, 0x1FEE, 0x1FEF, 458 0x0000, 0x0000, 0x1FF2, 0x1FFC, 0x1FF4, 0x0000, 0x1FF6, 0x1FF7, 459 0x1FF8, 0x1FF9, 0x1FFA, 0x1FFB, 0x1FFC, 0x1FFD, 0x1FFE, 0x0000 460 }; 461 462 *lower = code; 463 *upper = code; 464 465 /* Basic Latin and Latin-1 Supplement, U+0000 to U+00FF */ 466 if (code <= 0x00ff) { 467 if (code >= 0x0041 && code <= 0x005a) /* A-Z */ 468 *lower += 0x20; 469 else if (code >= 0x0061 && code <= 0x007a) /* a-z */ 470 *upper -= 0x20; 471 else if ( (code >= 0x00c0 && code <= 0x00d6) || 472 (code >= 0x00d8 && code <= 0x00de) ) 473 *lower += 0x20; 474 else if ( (code >= 0x00e0 && code <= 0x00f6) || 475 (code >= 0x00f8 && code <= 0x00fe) ) 476 *upper -= 0x20; 477 else if (code == 0x00ff) /* y with diaeresis */ 478 *upper = 0x0178; 479 else if (code == 0x00b5) /* micro sign */ 480 *upper = 0x039c; 481 return; 482 } 483 484 /* Latin Extended-A, U+0100 to U+017F */ 485 if (code >= 0x0100 && code <= 0x017f) { 486 if ( (code >= 0x0100 && code <= 0x012f) || 487 (code >= 0x0132 && code <= 0x0137) || 488 (code >= 0x014a && code <= 0x0177) ) { 489 *upper = code & ~1; 490 *lower = code | 1; 491 } 492 else if ( (code >= 0x0139 && code <= 0x0148) || 493 (code >= 0x0179 && code <= 0x017e) ) { 494 if (code & 1) 495 *lower += 1; 496 else 497 *upper -= 1; 498 } 499 else if (code == 0x0130) 500 *lower = 0x0069; 501 else if (code == 0x0131) 502 *upper = 0x0049; 503 else if (code == 0x0178) 504 *lower = 0x00ff; 505 else if (code == 0x017f) 506 *upper = 0x0053; 507 return; 508 } 509 510 /* Latin Extended-B, U+0180 to U+024F */ 511 if (code >= 0x0180 && code <= 0x024f) { 512 if (code >= 0x01cd && code <= 0x01dc) { 513 if (code & 1) 514 *lower += 1; 515 else 516 *upper -= 1; 517 } 518 else if ( (code >= 0x01de && code <= 0x01ef) || 519 (code >= 0x01f4 && code <= 0x01f5) || 520 (code >= 0x01f8 && code <= 0x021f) || 521 (code >= 0x0222 && code <= 0x0233) ) { 522 *lower |= 1; 523 *upper &= ~1; 524 } 525 else if (code >= 0x0180 && code <= 0x01cc) { 526 *lower = LatinExtB_lower_mapping[code - 0x0180]; 527 *upper = LatinExtB_upper_mapping[code - 0x0180]; 528 } 529 else if (code == 0x01dd) 530 *upper = 0x018e; 531 else if (code == 0x01f1 || code == 0x01f2) { 532 *lower = 0x01f3; 533 *upper = 0x01f1; 534 } 535 else if (code == 0x01f3) 536 *upper = 0x01f1; 537 else if (code == 0x01f6) 538 *lower = 0x0195; 539 else if (code == 0x01f7) 540 *lower = 0x01bf; 541 else if (code == 0x0220) 542 *lower = 0x019e; 543 return; 544 } 545 546 /* IPA Extensions, U+0250 to U+02AF */ 547 if (code >= 0x0253 && code <= 0x0292) { 548 *upper = IPAExt_upper_mapping[code - 0x0253]; 549 } 550 551 /* Combining Diacritical Marks, U+0300 to U+036F */ 552 if (code == 0x0345) { 553 *upper = 0x0399; 554 } 555 556 /* Greek and Coptic, U+0370 to U+03FF */ 557 if (code >= 0x0370 && code <= 0x03ff) { 558 *lower = Greek_lower_mapping[code - 0x0370]; 559 *upper = Greek_upper_mapping[code - 0x0370]; 560 if (*upper == 0) 561 *upper = code; 562 if (*lower == 0) 563 *lower = code; 564 } 565 566 /* Cyrillic and Cyrillic Supplementary, U+0400 to U+052F */ 567 if ( (code >= 0x0400 && code <= 0x04ff) || 568 (code >= 0x0500 && code <= 0x052f) ) { 569 if (code >= 0x0400 && code <= 0x040f) 570 *lower += 0x50; 571 else if (code >= 0x0410 && code <= 0x042f) 572 *lower += 0x20; 573 else if (code >= 0x0430 && code <= 0x044f) 574 *upper -= 0x20; 575 else if (code >= 0x0450 && code <= 0x045f) 576 *upper -= 0x50; 577 else if ( (code >= 0x0460 && code <= 0x0481) || 578 (code >= 0x048a && code <= 0x04bf) || 579 (code >= 0x04d0 && code <= 0x04f5) || 580 (code >= 0x04f8 && code <= 0x04f9) || 581 (code >= 0x0500 && code <= 0x050f) ) { 582 *upper &= ~1; 583 *lower |= 1; 584 } 585 else if (code >= 0x04c1 && code <= 0x04ce) { 586 if (code & 1) 587 *lower += 1; 588 else 589 *upper -= 1; 590 } 591 } 592 593 /* Armenian, U+0530 to U+058F */ 594 if (code >= 0x0530 && code <= 0x058f) { 595 if (code >= 0x0531 && code <= 0x0556) 596 *lower += 0x30; 597 else if (code >=0x0561 && code <= 0x0586) 598 *upper -= 0x30; 599 } 600 601 /* Latin Extended Additional, U+1E00 to U+1EFF */ 602 if (code >= 0x1e00 && code <= 0x1eff) { 603 if ( (code >= 0x1e00 && code <= 0x1e95) || 604 (code >= 0x1ea0 && code <= 0x1ef9) ) { 605 *upper &= ~1; 606 *lower |= 1; 607 } 608 else if (code == 0x1e9b) 609 *upper = 0x1e60; 610 } 611 612 /* Greek Extended, U+1F00 to U+1FFF */ 613 if (code >= 0x1f00 && code <= 0x1fff) { 614 *lower = GreekExt_lower_mapping[code - 0x1f00]; 615 *upper = GreekExt_upper_mapping[code - 0x1f00]; 616 if (*upper == 0) 617 *upper = code; 618 if (*lower == 0) 619 *lower = code; 620 } 621 622 /* Letterlike Symbols, U+2100 to U+214F */ 623 if (code >= 0x2100 && code <= 0x214f) { 624 switch (code) { 625 case 0x2126: *lower = 0x03c9; break; 626 case 0x212a: *lower = 0x006b; break; 627 case 0x212b: *lower = 0x00e5; break; 628 } 629 } 630 /* Number Forms, U+2150 to U+218F */ 631 else if (code >= 0x2160 && code <= 0x216f) 632 *lower += 0x10; 633 else if (code >= 0x2170 && code <= 0x217f) 634 *upper -= 0x10; 635 /* Enclosed Alphanumerics, U+2460 to U+24FF */ 636 else if (code >= 0x24b6 && code <= 0x24cf) 637 *lower += 0x1a; 638 else if (code >= 0x24d0 && code <= 0x24e9) 639 *upper -= 0x1a; 640 /* Halfwidth and Fullwidth Forms, U+FF00 to U+FFEF */ 641 else if (code >= 0xff21 && code <= 0xff3a) 642 *lower += 0x20; 643 else if (code >= 0xff41 && code <= 0xff5a) 644 *upper -= 0x20; 645 /* Deseret, U+10400 to U+104FF */ 646 else if (code >= 0x10400 && code <= 0x10427) 647 *lower += 0x28; 648 else if (code >= 0x10428 && code <= 0x1044f) 649 *upper -= 0x28; 650 } 651 652 static void 653 XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper) 654 { 655 /* Latin 1 keysym */ 656 if (sym < 0x100) { 657 UCSConvertCase(sym, lower, upper); 658 return; 659 } 660 661 /* Unicode keysym */ 662 if ((sym & 0xff000000) == 0x01000000) { 663 UCSConvertCase((sym & 0x00ffffff), lower, upper); 664 *upper |= 0x01000000; 665 *lower |= 0x01000000; 666 return; 667 } 668 669 /* Legacy keysym */ 670 671 *lower = sym; 672 *upper = sym; 673 674 switch(sym >> 8) { 675 case 1: /* Latin 2 */ 676 /* Assume the KeySym is a legal value (ignore discontinuities) */ 677 if (sym == XKB_KEY_Aogonek) 678 *lower = XKB_KEY_aogonek; 679 else if (sym >= XKB_KEY_Lstroke && sym <= XKB_KEY_Sacute) 680 *lower += (XKB_KEY_lstroke - XKB_KEY_Lstroke); 681 else if (sym >= XKB_KEY_Scaron && sym <= XKB_KEY_Zacute) 682 *lower += (XKB_KEY_scaron - XKB_KEY_Scaron); 683 else if (sym >= XKB_KEY_Zcaron && sym <= XKB_KEY_Zabovedot) 684 *lower += (XKB_KEY_zcaron - XKB_KEY_Zcaron); 685 else if (sym == XKB_KEY_aogonek) 686 *upper = XKB_KEY_Aogonek; 687 else if (sym >= XKB_KEY_lstroke && sym <= XKB_KEY_sacute) 688 *upper -= (XKB_KEY_lstroke - XKB_KEY_Lstroke); 689 else if (sym >= XKB_KEY_scaron && sym <= XKB_KEY_zacute) 690 *upper -= (XKB_KEY_scaron - XKB_KEY_Scaron); 691 else if (sym >= XKB_KEY_zcaron && sym <= XKB_KEY_zabovedot) 692 *upper -= (XKB_KEY_zcaron - XKB_KEY_Zcaron); 693 else if (sym >= XKB_KEY_Racute && sym <= XKB_KEY_Tcedilla) 694 *lower += (XKB_KEY_racute - XKB_KEY_Racute); 695 else if (sym >= XKB_KEY_racute && sym <= XKB_KEY_tcedilla) 696 *upper -= (XKB_KEY_racute - XKB_KEY_Racute); 697 break; 698 case 2: /* Latin 3 */ 699 /* Assume the KeySym is a legal value (ignore discontinuities) */ 700 if (sym >= XKB_KEY_Hstroke && sym <= XKB_KEY_Hcircumflex) 701 *lower += (XKB_KEY_hstroke - XKB_KEY_Hstroke); 702 else if (sym >= XKB_KEY_Gbreve && sym <= XKB_KEY_Jcircumflex) 703 *lower += (XKB_KEY_gbreve - XKB_KEY_Gbreve); 704 else if (sym >= XKB_KEY_hstroke && sym <= XKB_KEY_hcircumflex) 705 *upper -= (XKB_KEY_hstroke - XKB_KEY_Hstroke); 706 else if (sym >= XKB_KEY_gbreve && sym <= XKB_KEY_jcircumflex) 707 *upper -= (XKB_KEY_gbreve - XKB_KEY_Gbreve); 708 else if (sym >= XKB_KEY_Cabovedot && sym <= XKB_KEY_Scircumflex) 709 *lower += (XKB_KEY_cabovedot - XKB_KEY_Cabovedot); 710 else if (sym >= XKB_KEY_cabovedot && sym <= XKB_KEY_scircumflex) 711 *upper -= (XKB_KEY_cabovedot - XKB_KEY_Cabovedot); 712 break; 713 case 3: /* Latin 4 */ 714 /* Assume the KeySym is a legal value (ignore discontinuities) */ 715 if (sym >= XKB_KEY_Rcedilla && sym <= XKB_KEY_Tslash) 716 *lower += (XKB_KEY_rcedilla - XKB_KEY_Rcedilla); 717 else if (sym >= XKB_KEY_rcedilla && sym <= XKB_KEY_tslash) 718 *upper -= (XKB_KEY_rcedilla - XKB_KEY_Rcedilla); 719 else if (sym == XKB_KEY_ENG) 720 *lower = XKB_KEY_eng; 721 else if (sym == XKB_KEY_eng) 722 *upper = XKB_KEY_ENG; 723 else if (sym >= XKB_KEY_Amacron && sym <= XKB_KEY_Umacron) 724 *lower += (XKB_KEY_amacron - XKB_KEY_Amacron); 725 else if (sym >= XKB_KEY_amacron && sym <= XKB_KEY_umacron) 726 *upper -= (XKB_KEY_amacron - XKB_KEY_Amacron); 727 break; 728 case 6: /* Cyrillic */ 729 /* Assume the KeySym is a legal value (ignore discontinuities) */ 730 if (sym >= XKB_KEY_Serbian_DJE && sym <= XKB_KEY_Serbian_DZE) 731 *lower -= (XKB_KEY_Serbian_DJE - XKB_KEY_Serbian_dje); 732 else if (sym >= XKB_KEY_Serbian_dje && sym <= XKB_KEY_Serbian_dze) 733 *upper += (XKB_KEY_Serbian_DJE - XKB_KEY_Serbian_dje); 734 else if (sym >= XKB_KEY_Cyrillic_YU && sym <= XKB_KEY_Cyrillic_HARDSIGN) 735 *lower -= (XKB_KEY_Cyrillic_YU - XKB_KEY_Cyrillic_yu); 736 else if (sym >= XKB_KEY_Cyrillic_yu && sym <= XKB_KEY_Cyrillic_hardsign) 737 *upper += (XKB_KEY_Cyrillic_YU - XKB_KEY_Cyrillic_yu); 738 break; 739 case 7: /* Greek */ 740 /* Assume the KeySym is a legal value (ignore discontinuities) */ 741 if (sym >= XKB_KEY_Greek_ALPHAaccent && sym <= XKB_KEY_Greek_OMEGAaccent) 742 *lower += (XKB_KEY_Greek_alphaaccent - XKB_KEY_Greek_ALPHAaccent); 743 else if (sym >= XKB_KEY_Greek_alphaaccent && sym <= XKB_KEY_Greek_omegaaccent && 744 sym != XKB_KEY_Greek_iotaaccentdieresis && 745 sym != XKB_KEY_Greek_upsilonaccentdieresis) 746 *upper -= (XKB_KEY_Greek_alphaaccent - XKB_KEY_Greek_ALPHAaccent); 747 else if (sym >= XKB_KEY_Greek_ALPHA && sym <= XKB_KEY_Greek_OMEGA) 748 *lower += (XKB_KEY_Greek_alpha - XKB_KEY_Greek_ALPHA); 749 else if (sym >= XKB_KEY_Greek_alpha && sym <= XKB_KEY_Greek_omega && 750 sym != XKB_KEY_Greek_finalsmallsigma) 751 *upper -= (XKB_KEY_Greek_alpha - XKB_KEY_Greek_ALPHA); 752 break; 753 case 0x13: /* Latin 9 */ 754 if (sym == XKB_KEY_OE) 755 *lower = XKB_KEY_oe; 756 else if (sym == XKB_KEY_oe) 757 *upper = XKB_KEY_OE; 758 else if (sym == XKB_KEY_Ydiaeresis) 759 *lower = XKB_KEY_ydiaeresis; 760 break; 761 } 762 } 763