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