da1d2192c597de14fd3d28c610c5372ce79506fd
[platform/upstream/libxkbcommon.git] / src / keysym.c
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 "xkbcommon/xkbcommon.h"
51 #include "utils.h"
52 #include "ks_tables.h"
53 #include "keysym.h"
54
55 XKB_EXPORT void
56 xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
57 {
58     int i, n, h, idx;
59     const unsigned char *entry;
60     unsigned char val1, val2, val3, val4;
61
62     if ((ks & ((unsigned long) ~0x1fffffff)) != 0) {
63         snprintf(buffer, size, "Invalid");
64         return;
65     }
66
67     /* Try to find it in our hash table. */
68     if (ks <= 0x1fffffff) {
69         val1 = ks >> 24;
70         val2 = (ks >> 16) & 0xff;
71         val3 = (ks >> 8) & 0xff;
72         val4 = ks & 0xff;
73         i = ks % VTABLESIZE;
74         h = i + 1;
75         n = VMAXHASH;
76
77         while ((idx = hashKeysym[i])) {
78             entry = &_XkeyTable[idx];
79
80             if ((entry[0] == val1) && (entry[1] == val2) &&
81                 (entry[2] == val3) && (entry[3] == val4)) {
82                 snprintf(buffer, size, "%s", entry + 4);
83                 return;
84             }
85
86             if (!--n)
87                 break;
88
89             i += h;
90             if (i >= VTABLESIZE)
91                 i -= VTABLESIZE;
92         }
93     }
94
95     if (ks >= 0x01000100 && ks <= 0x0110ffff)
96         /* Unnamed Unicode codepoint. */
97         snprintf(buffer, size, "U%lx", ks & 0xffffffUL);
98     else
99         /* Unnamed, non-Unicode, symbol (shouldn't generally happen). */
100         snprintf(buffer, size, "0x%08x", ks);
101 }
102
103 XKB_EXPORT xkb_keysym_t
104 xkb_keysym_from_name(const char *s)
105 {
106     int i, n, h, c, idx;
107     uint32_t sig = 0;
108     const char *p = s;
109     char *tmp;
110     const unsigned char *entry;
111     unsigned char sig1, sig2;
112     xkb_keysym_t val;
113
114     while ((c = *p++))
115         sig = (sig << 1) + c;
116
117     i = sig % KTABLESIZE;
118     h = i + 1;
119     sig1 = (sig >> 8) & 0xff;
120     sig2 = sig & 0xff;
121     n = KMAXHASH;
122
123     while ((idx = hashString[i])) {
124         entry = &_XkeyTable[idx];
125
126         if ((entry[0] == sig1) && (entry[1] == sig2) &&
127             streq(s, (const char *) entry + 6)) {
128             val = (entry[2] << 24) | (entry[3] << 16) |
129                   (entry[4] << 8) | entry[5];
130             if (!val)
131                 val = XKB_KEY_VoidSymbol;
132             return val;
133         }
134
135         if (!--n)
136             break;
137
138         i += h;
139         if (i >= KTABLESIZE)
140             i -= KTABLESIZE;
141     }
142
143     if (*s == 'U') {
144         val = strtoul(&s[1], &tmp, 16);
145         if (tmp && *tmp != '\0')
146             return XKB_KEY_NoSymbol;
147
148         if (val < 0x20 || (val > 0x7e && val < 0xa0))
149             return XKB_KEY_NoSymbol;
150         if (val < 0x100)
151             return val;
152         if (val > 0x10ffff)
153             return XKB_KEY_NoSymbol;
154         return val | 0x01000000;
155     }
156     else if (s[0] == '0' && s[1] == 'x') {
157         val = strtoul(&s[2], &tmp, 16);
158         if (tmp && *tmp != '\0')
159             return XKB_KEY_NoSymbol;
160
161         return val;
162     }
163
164     /* Stupid inconsistency between the headers and XKeysymDB: the former has
165      * no separating underscore, while some XF86* syms in the latter did.
166      * As a last ditch effort, try without. */
167     if (strncmp(s, "XF86_", 5) == 0) {
168         xkb_keysym_t ret;
169         tmp = strdup(s);
170         if (!tmp)
171             return XKB_KEY_NoSymbol;
172         memmove(&tmp[4], &tmp[5], strlen(s) - 5 + 1);
173         ret = xkb_keysym_from_name(tmp);
174         free(tmp);
175         return ret;
176     }
177
178     return XKB_KEY_NoSymbol;
179 }
180
181 enum keysym_case {
182     NONE,
183     LOWERCASE,
184     UPPERCASE,
185 };
186
187 static enum keysym_case
188 keysym_get_case(xkb_keysym_t ks)
189 {
190     unsigned set = (ks & (~0xff)) >> 8;
191
192     switch (set) {
193     case 0: /* latin 1 */
194         if ((ks >= XKB_KEY_A && ks <= XKB_KEY_Z) ||
195             (ks >= XKB_KEY_Agrave && ks <= XKB_KEY_THORN && ks !=
196              XKB_KEY_multiply))
197             return UPPERCASE;
198         if ((ks >= XKB_KEY_a && ks <= XKB_KEY_z) ||
199             (ks >= XKB_KEY_agrave && ks <= XKB_KEY_ydiaeresis))
200             return LOWERCASE;
201         break;
202
203     case 1: /* latin 2 */
204         if ((ks >= XKB_KEY_Aogonek && ks <= XKB_KEY_Zabovedot && ks !=
205              XKB_KEY_breve) ||
206             (ks >= XKB_KEY_Racute && ks <= XKB_KEY_Tcedilla))
207             return UPPERCASE;
208         if ((ks >= XKB_KEY_aogonek && ks <= XKB_KEY_zabovedot && ks !=
209              XKB_KEY_caron) ||
210             (ks >= XKB_KEY_racute && ks <= XKB_KEY_tcedilla))
211             return LOWERCASE;
212         break;
213
214     case 2: /* latin 3 */
215         if ((ks >= XKB_KEY_Hstroke && ks <= XKB_KEY_Jcircumflex) ||
216             (ks >= XKB_KEY_Cabovedot && ks <= XKB_KEY_Scircumflex))
217             return UPPERCASE;
218         if ((ks >= XKB_KEY_hstroke && ks <= XKB_KEY_jcircumflex) ||
219             (ks >= XKB_KEY_cabovedot && ks <= XKB_KEY_scircumflex))
220             return LOWERCASE;
221         break;
222
223     case 3: /* latin 4 */
224         if ((ks >= XKB_KEY_Rcedilla && ks <= XKB_KEY_Tslash) ||
225             (ks == XKB_KEY_ENG) ||
226             (ks >= XKB_KEY_Amacron && ks <= XKB_KEY_Umacron))
227             return UPPERCASE;
228         if ((ks >= XKB_KEY_rcedilla && ks <= XKB_KEY_tslash) ||
229             (ks == XKB_KEY_eng) ||
230             (ks >= XKB_KEY_amacron && ks <= XKB_KEY_umacron))
231             return LOWERCASE;
232         break;
233
234     case 6: /* Cyrillic */
235         if ((ks >= XKB_KEY_Serbian_DJE && ks <= XKB_KEY_Serbian_DZE) ||
236             (ks >= XKB_KEY_Cyrillic_YU && ks <= XKB_KEY_Cyrillic_HARDSIGN))
237             return UPPERCASE;
238         if ((ks >= XKB_KEY_Serbian_dje && ks <= XKB_KEY_Serbian_dze) ||
239             (ks >= XKB_KEY_Cyrillic_yu && ks <= XKB_KEY_Cyrillic_hardsign))
240             return LOWERCASE;
241         break;
242
243     case 7: /* Greek */
244         if ((ks >= XKB_KEY_Greek_ALPHAaccent &&
245              ks <= XKB_KEY_Greek_OMEGAaccent) ||
246             (ks >= XKB_KEY_Greek_ALPHA && ks <= XKB_KEY_Greek_OMEGA))
247             return UPPERCASE;
248         if ((ks >= XKB_KEY_Greek_alphaaccent &&
249              ks <= XKB_KEY_Greek_omegaaccent) ||
250             (ks >= XKB_KEY_Greek_alpha && ks <= XKB_KEY_Greek_OMEGA))
251             return LOWERCASE;
252         break;
253
254     case 18: /* latin 8 */
255         if ((ks == XKB_KEY_Wcircumflex) ||
256             (ks == XKB_KEY_Ycircumflex) ||
257             (ks == XKB_KEY_Babovedot) ||
258             (ks == XKB_KEY_Dabovedot) ||
259             (ks == XKB_KEY_Fabovedot) ||
260             (ks == XKB_KEY_Mabovedot) ||
261             (ks == XKB_KEY_Pabovedot) ||
262             (ks == XKB_KEY_Sabovedot) ||
263             (ks == XKB_KEY_Tabovedot) ||
264             (ks == XKB_KEY_Wdiaeresis) ||
265             (ks == XKB_KEY_Ygrave))
266             return UPPERCASE;
267         if ((ks == XKB_KEY_wcircumflex) ||
268             (ks == XKB_KEY_ycircumflex) ||
269             (ks == XKB_KEY_babovedot) ||
270             (ks == XKB_KEY_dabovedot) ||
271             (ks == XKB_KEY_fabovedot) ||
272             (ks == XKB_KEY_mabovedot) ||
273             (ks == XKB_KEY_pabovedot) ||
274             (ks == XKB_KEY_sabovedot) ||
275             (ks == XKB_KEY_tabovedot) ||
276             (ks == XKB_KEY_wdiaeresis) ||
277             (ks == XKB_KEY_ygrave))
278             return LOWERCASE;
279         break;
280
281     case 19: /* latin 9 */
282         if (ks == XKB_KEY_OE || ks == XKB_KEY_Ydiaeresis)
283             return UPPERCASE;
284         if (ks == XKB_KEY_oe)
285             return LOWERCASE;
286         break;
287     }
288
289     return NONE;
290 }
291
292 bool
293 xkb_keysym_is_lower(xkb_keysym_t keysym)
294 {
295     return keysym_get_case(keysym) == LOWERCASE;
296 }
297
298 bool
299 xkb_keysym_is_upper(xkb_keysym_t keysym)
300 {
301     return keysym_get_case(keysym) == UPPERCASE;
302 }
303
304 bool
305 xkb_keysym_is_keypad(xkb_keysym_t keysym)
306 {
307     return keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_Equal;
308 }