2009-01-20 08:46:12 -07:00
|
|
|
/*
|
2012-07-17 03:20:15 -06:00
|
|
|
* Copyright 1985, 1987, 1990, 1998 The Open Group
|
|
|
|
* Copyright 2008 Dan Nicholson
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
*
|
|
|
|
* Except as contained in this notice, the names of the authors or their
|
|
|
|
* institutions shall not be used in advertising or otherwise to promote the
|
|
|
|
* sale, use or other dealings in this Software without prior written
|
|
|
|
* authorization from the authors.
|
|
|
|
*/
|
2009-01-20 08:46:12 -07:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
2012-04-05 01:47:43 -06:00
|
|
|
#include <stdio.h>
|
2009-01-20 08:46:12 -07:00
|
|
|
#include <string.h>
|
|
|
|
|
2012-05-08 05:52:23 -06:00
|
|
|
#include "xkb-priv.h"
|
2009-01-20 08:46:12 -07:00
|
|
|
#include "ks_tables.h"
|
|
|
|
|
2012-04-05 01:47:43 -06:00
|
|
|
_X_EXPORT void
|
2012-05-09 06:22:34 -06:00
|
|
|
xkb_keysym_get_name(xkb_keysym_t ks, char *buffer, size_t size)
|
2009-01-20 08:46:12 -07:00
|
|
|
{
|
2009-03-19 12:34:54 -06:00
|
|
|
int i, n, h, idx;
|
2009-01-20 08:46:12 -07:00
|
|
|
const unsigned char *entry;
|
|
|
|
unsigned char val1, val2, val3, val4;
|
|
|
|
|
2010-10-08 13:33:18 -06:00
|
|
|
if ((ks & ((unsigned long) ~0x1fffffff)) != 0) {
|
|
|
|
snprintf(buffer, size, "Invalid");
|
|
|
|
return;
|
|
|
|
}
|
2009-03-19 12:34:54 -06:00
|
|
|
|
2009-04-24 22:42:42 -06:00
|
|
|
/* Try to find it in our hash table. */
|
2009-03-19 12:34:54 -06:00
|
|
|
if (ks <= 0x1fffffff) {
|
|
|
|
val1 = ks >> 24;
|
|
|
|
val2 = (ks >> 16) & 0xff;
|
|
|
|
val3 = (ks >> 8) & 0xff;
|
|
|
|
val4 = ks & 0xff;
|
|
|
|
i = ks % VTABLESIZE;
|
|
|
|
h = i + 1;
|
|
|
|
n = VMAXHASH;
|
|
|
|
|
|
|
|
while ((idx = hashKeysym[i])) {
|
|
|
|
entry = &_XkeyTable[idx];
|
|
|
|
|
|
|
|
if ((entry[0] == val1) && (entry[1] == val2) &&
|
2010-10-08 13:33:18 -06:00
|
|
|
(entry[2] == val3) && (entry[3] == val4)) {
|
2012-07-17 03:20:15 -06:00
|
|
|
snprintf(buffer, size, "%s", entry + 4);
|
|
|
|
return;
|
|
|
|
}
|
2009-03-19 12:34:54 -06:00
|
|
|
|
|
|
|
if (!--n)
|
|
|
|
break;
|
|
|
|
|
|
|
|
i += h;
|
|
|
|
if (i >= VTABLESIZE)
|
|
|
|
i -= VTABLESIZE;
|
|
|
|
}
|
2009-01-20 08:46:12 -07:00
|
|
|
}
|
|
|
|
|
2010-10-08 13:33:18 -06:00
|
|
|
if (ks >= 0x01000100 && ks <= 0x0110ffff)
|
2012-07-17 03:20:15 -06:00
|
|
|
/* Unnamed Unicode codepoint. */
|
2010-10-08 13:33:18 -06:00
|
|
|
snprintf(buffer, size, "U%lx", ks & 0xffffffUL);
|
|
|
|
else
|
2012-07-17 03:20:15 -06:00
|
|
|
/* Unnamed, non-Unicode, symbol (shouldn't generally happen). */
|
|
|
|
snprintf(buffer, size, "0x%08x", ks);
|
2009-01-20 08:46:12 -07:00
|
|
|
}
|
|
|
|
|
2012-04-05 01:47:43 -06:00
|
|
|
_X_EXPORT xkb_keysym_t
|
2012-05-09 06:22:34 -06:00
|
|
|
xkb_keysym_from_name(const char *s)
|
2009-01-20 08:46:12 -07:00
|
|
|
{
|
2009-03-19 12:34:54 -06:00
|
|
|
int i, n, h, c, idx;
|
2012-02-25 12:09:28 -07:00
|
|
|
uint32_t sig = 0;
|
2009-03-19 12:34:54 -06:00
|
|
|
const char *p = s;
|
2012-04-03 06:57:44 -06:00
|
|
|
char *tmp;
|
2009-01-20 08:46:12 -07:00
|
|
|
const unsigned char *entry;
|
|
|
|
unsigned char sig1, sig2;
|
2012-03-09 12:03:59 -07:00
|
|
|
xkb_keysym_t val;
|
2009-01-20 08:46:12 -07:00
|
|
|
|
|
|
|
while ((c = *p++))
|
2009-03-19 12:34:54 -06:00
|
|
|
sig = (sig << 1) + c;
|
|
|
|
|
2009-01-20 08:46:12 -07:00
|
|
|
i = sig % KTABLESIZE;
|
|
|
|
h = i + 1;
|
|
|
|
sig1 = (sig >> 8) & 0xff;
|
|
|
|
sig2 = sig & 0xff;
|
|
|
|
n = KMAXHASH;
|
2009-03-19 12:34:54 -06:00
|
|
|
|
|
|
|
while ((idx = hashString[i])) {
|
|
|
|
entry = &_XkeyTable[idx];
|
|
|
|
|
|
|
|
if ((entry[0] == sig1) && (entry[1] == sig2) &&
|
2012-07-17 03:20:15 -06:00
|
|
|
!strcmp(s, (const char *) entry + 6)) {
|
2009-03-19 12:34:54 -06:00
|
|
|
val = (entry[2] << 24) | (entry[3] << 16) |
|
2012-07-17 03:20:15 -06:00
|
|
|
(entry[4] << 8) | entry[5];
|
2009-03-19 12:34:54 -06:00
|
|
|
if (!val)
|
2012-05-09 07:05:00 -06:00
|
|
|
val = XKB_KEY_VoidSymbol;
|
2009-03-19 12:34:54 -06:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!--n)
|
|
|
|
break;
|
|
|
|
|
|
|
|
i += h;
|
|
|
|
if (i >= KTABLESIZE)
|
|
|
|
i -= KTABLESIZE;
|
2009-01-20 08:46:12 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
if (*s == 'U') {
|
2012-04-03 06:57:44 -06:00
|
|
|
val = strtoul(&s[1], &tmp, 16);
|
|
|
|
if (tmp && *tmp != '\0')
|
2012-05-09 07:05:00 -06:00
|
|
|
return XKB_KEY_NoSymbol;
|
2009-03-19 12:34:54 -06:00
|
|
|
|
|
|
|
if (val < 0x20 || (val > 0x7e && val < 0xa0))
|
2012-05-09 07:05:00 -06:00
|
|
|
return XKB_KEY_NoSymbol;
|
2009-03-19 12:34:54 -06:00
|
|
|
if (val < 0x100)
|
|
|
|
return val;
|
2009-04-24 22:42:42 -06:00
|
|
|
if (val > 0x10ffff)
|
2012-05-09 07:05:00 -06:00
|
|
|
return XKB_KEY_NoSymbol;
|
2009-01-20 08:46:12 -07:00
|
|
|
return val | 0x01000000;
|
|
|
|
}
|
2009-04-24 22:42:42 -06:00
|
|
|
else if (s[0] == '0' && s[1] == 'x') {
|
2012-04-03 06:57:44 -06:00
|
|
|
val = strtoul(&s[2], &tmp, 16);
|
|
|
|
if (tmp && *tmp != '\0')
|
2012-05-09 07:05:00 -06:00
|
|
|
return XKB_KEY_NoSymbol;
|
2012-04-03 06:57:44 -06:00
|
|
|
|
|
|
|
return val;
|
2009-04-24 22:42:42 -06:00
|
|
|
}
|
2009-03-19 12:34:54 -06:00
|
|
|
|
2012-02-25 15:03:24 -07:00
|
|
|
/* Stupid inconsistency between the headers and XKeysymDB: the former has
|
|
|
|
* no separating underscore, while some XF86* syms in the latter did.
|
|
|
|
* As a last ditch effort, try without. */
|
|
|
|
if (strncmp(s, "XF86_", 5) == 0) {
|
2012-03-09 12:03:59 -07:00
|
|
|
xkb_keysym_t ret;
|
2012-04-03 07:26:04 -06:00
|
|
|
tmp = strdup(s);
|
2012-02-25 15:03:24 -07:00
|
|
|
if (!tmp)
|
2012-05-09 07:05:00 -06:00
|
|
|
return XKB_KEY_NoSymbol;
|
2012-02-25 15:03:24 -07:00
|
|
|
memmove(&tmp[4], &tmp[5], strlen(s) - 5 + 1);
|
2012-05-09 06:22:34 -06:00
|
|
|
ret = xkb_keysym_from_name(tmp);
|
2012-02-25 15:03:24 -07:00
|
|
|
free(tmp);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-05-09 07:05:00 -06:00
|
|
|
return XKB_KEY_NoSymbol;
|
2009-01-20 08:46:12 -07:00
|
|
|
}
|
2012-07-13 09:55:10 -06:00
|
|
|
|
|
|
|
enum keysym_case {
|
|
|
|
NONE,
|
|
|
|
LOWERCASE,
|
|
|
|
UPPERCASE,
|
|
|
|
};
|
|
|
|
|
|
|
|
static enum keysym_case
|
|
|
|
keysym_get_case(xkb_keysym_t ks)
|
|
|
|
{
|
|
|
|
unsigned set = (ks & (~0xff)) >> 8;
|
|
|
|
|
|
|
|
switch (set) {
|
|
|
|
case 0: /* latin 1 */
|
|
|
|
if ((ks >= XKB_KEY_A && ks <= XKB_KEY_Z) ||
|
2012-07-17 03:20:15 -06:00
|
|
|
(ks >= XKB_KEY_Agrave && ks <= XKB_KEY_THORN && ks !=
|
|
|
|
XKB_KEY_multiply))
|
2012-07-13 09:55:10 -06:00
|
|
|
return UPPERCASE;
|
|
|
|
if ((ks >= XKB_KEY_a && ks <= XKB_KEY_z) ||
|
|
|
|
(ks >= XKB_KEY_agrave && ks <= XKB_KEY_ydiaeresis))
|
|
|
|
return LOWERCASE;
|
|
|
|
break;
|
2012-07-17 03:20:15 -06:00
|
|
|
|
2012-07-13 09:55:10 -06:00
|
|
|
case 1: /* latin 2 */
|
2012-07-17 03:20:15 -06:00
|
|
|
if ((ks >= XKB_KEY_Aogonek && ks <= XKB_KEY_Zabovedot && ks !=
|
|
|
|
XKB_KEY_breve) ||
|
|
|
|
(ks >= XKB_KEY_Racute && ks <= XKB_KEY_Tcedilla))
|
2012-07-13 09:55:10 -06:00
|
|
|
return UPPERCASE;
|
2012-07-17 03:20:15 -06:00
|
|
|
if ((ks >= XKB_KEY_aogonek && ks <= XKB_KEY_zabovedot && ks !=
|
|
|
|
XKB_KEY_caron) ||
|
2012-07-13 09:55:10 -06:00
|
|
|
(ks >= XKB_KEY_racute && ks <= XKB_KEY_tcedilla))
|
|
|
|
return LOWERCASE;
|
|
|
|
break;
|
2012-07-17 03:20:15 -06:00
|
|
|
|
2012-07-13 09:55:10 -06:00
|
|
|
case 2: /* latin 3 */
|
|
|
|
if ((ks >= XKB_KEY_Hstroke && ks <= XKB_KEY_Jcircumflex) ||
|
|
|
|
(ks >= XKB_KEY_Cabovedot && ks <= XKB_KEY_Scircumflex))
|
|
|
|
return UPPERCASE;
|
|
|
|
if ((ks >= XKB_KEY_hstroke && ks <= XKB_KEY_jcircumflex) ||
|
|
|
|
(ks >= XKB_KEY_cabovedot && ks <= XKB_KEY_scircumflex))
|
|
|
|
return LOWERCASE;
|
|
|
|
break;
|
2012-07-17 03:20:15 -06:00
|
|
|
|
2012-07-13 09:55:10 -06:00
|
|
|
case 3: /* latin 4 */
|
|
|
|
if ((ks >= XKB_KEY_Rcedilla && ks <= XKB_KEY_Tslash) ||
|
|
|
|
(ks == XKB_KEY_ENG) ||
|
|
|
|
(ks >= XKB_KEY_Amacron && ks <= XKB_KEY_Umacron))
|
|
|
|
return UPPERCASE;
|
|
|
|
if ((ks >= XKB_KEY_rcedilla && ks <= XKB_KEY_tslash) ||
|
|
|
|
(ks == XKB_KEY_eng) ||
|
|
|
|
(ks >= XKB_KEY_amacron && ks <= XKB_KEY_umacron))
|
|
|
|
return LOWERCASE;
|
|
|
|
break;
|
2012-07-17 03:20:15 -06:00
|
|
|
|
2012-07-13 09:55:10 -06:00
|
|
|
case 6: /* Cyrillic */
|
|
|
|
if ((ks >= XKB_KEY_Serbian_DJE && ks <= XKB_KEY_Serbian_DZE) ||
|
|
|
|
(ks >= XKB_KEY_Cyrillic_YU && ks <= XKB_KEY_Cyrillic_HARDSIGN))
|
|
|
|
return UPPERCASE;
|
|
|
|
if ((ks >= XKB_KEY_Serbian_dje && ks <= XKB_KEY_Serbian_dze) ||
|
|
|
|
(ks >= XKB_KEY_Cyrillic_yu && ks <= XKB_KEY_Cyrillic_hardsign))
|
|
|
|
return LOWERCASE;
|
|
|
|
break;
|
2012-07-17 03:20:15 -06:00
|
|
|
|
2012-07-13 09:55:10 -06:00
|
|
|
case 7: /* Greek */
|
|
|
|
if ((ks >= XKB_KEY_Greek_ALPHAaccent &&
|
|
|
|
ks <= XKB_KEY_Greek_OMEGAaccent) ||
|
|
|
|
(ks >= XKB_KEY_Greek_ALPHA && ks <= XKB_KEY_Greek_OMEGA))
|
|
|
|
return UPPERCASE;
|
|
|
|
if ((ks >= XKB_KEY_Greek_alphaaccent &&
|
|
|
|
ks <= XKB_KEY_Greek_omegaaccent) ||
|
|
|
|
(ks >= XKB_KEY_Greek_alpha && ks <= XKB_KEY_Greek_OMEGA))
|
|
|
|
return LOWERCASE;
|
|
|
|
break;
|
2012-07-17 03:20:15 -06:00
|
|
|
|
2012-07-13 09:55:10 -06:00
|
|
|
case 18: /* latin 8 */
|
|
|
|
if ((ks == XKB_KEY_Wcircumflex) ||
|
|
|
|
(ks == XKB_KEY_Ycircumflex) ||
|
|
|
|
(ks == XKB_KEY_Babovedot) ||
|
|
|
|
(ks == XKB_KEY_Dabovedot) ||
|
|
|
|
(ks == XKB_KEY_Fabovedot) ||
|
|
|
|
(ks == XKB_KEY_Mabovedot) ||
|
|
|
|
(ks == XKB_KEY_Pabovedot) ||
|
|
|
|
(ks == XKB_KEY_Sabovedot) ||
|
|
|
|
(ks == XKB_KEY_Tabovedot) ||
|
|
|
|
(ks == XKB_KEY_Wdiaeresis) ||
|
|
|
|
(ks == XKB_KEY_Ygrave))
|
|
|
|
return UPPERCASE;
|
|
|
|
if ((ks == XKB_KEY_wcircumflex) ||
|
|
|
|
(ks == XKB_KEY_ycircumflex) ||
|
|
|
|
(ks == XKB_KEY_babovedot) ||
|
|
|
|
(ks == XKB_KEY_dabovedot) ||
|
|
|
|
(ks == XKB_KEY_fabovedot) ||
|
|
|
|
(ks == XKB_KEY_mabovedot) ||
|
|
|
|
(ks == XKB_KEY_pabovedot) ||
|
|
|
|
(ks == XKB_KEY_sabovedot) ||
|
|
|
|
(ks == XKB_KEY_tabovedot) ||
|
|
|
|
(ks == XKB_KEY_wdiaeresis) ||
|
|
|
|
(ks == XKB_KEY_ygrave))
|
|
|
|
return LOWERCASE;
|
|
|
|
break;
|
2012-07-17 03:20:15 -06:00
|
|
|
|
2012-07-13 09:55:10 -06:00
|
|
|
case 19: /* latin 9 */
|
|
|
|
if (ks == XKB_KEY_OE || ks == XKB_KEY_Ydiaeresis)
|
|
|
|
return UPPERCASE;
|
|
|
|
if (ks == XKB_KEY_oe)
|
|
|
|
return LOWERCASE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
xkb_keysym_is_lower(xkb_keysym_t keysym)
|
|
|
|
{
|
|
|
|
return keysym_get_case(keysym) == LOWERCASE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
xkb_keysym_is_upper(xkb_keysym_t keysym)
|
|
|
|
{
|
|
|
|
return keysym_get_case(keysym) == UPPERCASE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
xkb_keysym_is_keypad(xkb_keysym_t keysym)
|
|
|
|
{
|
|
|
|
return keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_Equal;
|
|
|
|
}
|