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 *
get_name(const struct name_keysym * entry)57 get_name(const struct name_keysym *entry)
58 {
59 return keysym_names + entry->offset;
60 }
61
62 static int
compare_by_keysym(const void * a,const void * b)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
compare_by_name(const void * a,const void * b)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
xkb_keysym_get_name(xkb_keysym_t ks,char * buffer,size_t size)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 *
find_sym(const struct name_keysym * entry,const char * name,bool icase)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
xkb_keysym_from_name(const char * s,enum xkb_keysym_flags flags)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
xkb_keysym_is_keypad(xkb_keysym_t keysym)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
xkb_keysym_is_modifier(xkb_keysym_t keysym)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
xkb_keysym_is_lower(xkb_keysym_t ks)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
xkb_keysym_is_upper(xkb_keysym_t ks)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
xkb_keysym_to_lower(xkb_keysym_t ks)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
xkb_keysym_to_upper(xkb_keysym_t ks)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
UCSConvertCase(uint32_t code,xkb_keysym_t * lower,xkb_keysym_t * upper)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
XConvertCase(xkb_keysym_t sym,xkb_keysym_t * lower,xkb_keysym_t * upper)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