/************************************************************
* Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, and distribute this
* software and its documentation for any purpose and without
* fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting
* documentation, and that the name of Silicon Graphics not be
* used in advertising or publicity pertaining to distribution
* of the software without specific prior written permission.
* Silicon Graphics makes no representation about the suitability
* of this software for any purpose. It is provided "as is"
* without any express or implied warranty.
*
* SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
* GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
* THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
********************************************************/
#include "keymap.h"
#include "text.h"
bool
LookupString(const LookupEntry tab[], const char *string,
unsigned int *value_rtrn)
{
const LookupEntry *entry;
if (!string)
return false;
for (entry = tab; entry->name; entry++) {
if (istreq(entry->name, string)) {
*value_rtrn = entry->value;
return true;
}
}
return false;
}
const char *
LookupValue(const LookupEntry tab[], unsigned int value)
{
const LookupEntry *entry;
for (entry = tab; entry->name; entry++)
if (entry->value == value)
return entry->name;
return NULL;
}
const LookupEntry ctrlMaskNames[] = {
{ "RepeatKeys", CONTROL_REPEAT },
{ "Repeat", CONTROL_REPEAT },
{ "AutoRepeat", CONTROL_REPEAT },
{ "SlowKeys", CONTROL_SLOW },
{ "BounceKeys", CONTROL_DEBOUNCE },
{ "StickyKeys", CONTROL_STICKY },
{ "MouseKeys", CONTROL_MOUSEKEYS },
{ "MouseKeysAccel", CONTROL_MOUSEKEYS_ACCEL },
{ "AccessXKeys", CONTROL_AX },
{ "AccessXTimeout", CONTROL_AX_TIMEOUT },
{ "AccessXFeedback", CONTROL_AX_FEEDBACK },
{ "AudibleBell", CONTROL_BELL },
{ "IgnoreGroupLock", CONTROL_IGNORE_GROUP_LOCK },
{ "all", CONTROL_ALL },
{ "none", 0 },
{ "Overlay1", 0 },
{ "Overlay2", 0 },
{ NULL, 0 }
};
const LookupEntry modComponentMaskNames[] = {
{"base", XKB_STATE_DEPRESSED},
{"latched", XKB_STATE_LATCHED},
{"locked", XKB_STATE_LOCKED},
{"effective", XKB_STATE_EFFECTIVE},
{"compat", XKB_STATE_EFFECTIVE},
{"any", XKB_STATE_EFFECTIVE},
{"none", 0},
{NULL, 0}
};
const LookupEntry groupComponentMaskNames[] = {
{"base", XKB_STATE_DEPRESSED},
{"latched", XKB_STATE_LATCHED},
{"locked", XKB_STATE_LOCKED},
{"effective", XKB_STATE_EFFECTIVE},
{"any", XKB_STATE_EFFECTIVE},
{"none", 0},
{NULL, 0}
};
const LookupEntry groupMaskNames[] = {
{"group1", 0x01},
{"group2", 0x02},
{"group3", 0x04},
{"group4", 0x08},
{"group5", 0x10},
{"group6", 0x20},
{"group7", 0x40},
{"group8", 0x80},
{"none", 0x00},
{"all", 0xff},
{NULL, 0}
};
const LookupEntry groupNames[] = {
{"group1", 1},
{"group2", 2},
{"group3", 3},
{"group4", 4},
{"group5", 5},
{"group6", 6},
{"group7", 7},
{"group8", 8},
{NULL, 0}
};
const LookupEntry levelNames[] = {
{ "level1", 1 },
{ "level2", 2 },
{ "level3", 3 },
{ "level4", 4 },
{ "level5", 5 },
{ "level6", 6 },
{ "level7", 7 },
{ "level8", 8 },
{ NULL, 0 }
};
const LookupEntry buttonNames[] = {
{ "button1", 1 },
{ "button2", 2 },
{ "button3", 3 },
{ "button4", 4 },
{ "button5", 5 },
{ "default", 0 },
{ NULL, 0 }
};
const LookupEntry useModMapValueNames[] = {
{ "levelone", 1 },
{ "level1", 1 },
{ "anylevel", 0 },
{ "any", 0 },
{ NULL, 0 }
};
const LookupEntry actionTypeNames[] = {
{ "NoAction", ACTION_TYPE_NONE },
{ "SetMods", ACTION_TYPE_MOD_SET },
{ "LatchMods", ACTION_TYPE_MOD_LATCH },
{ "LockMods", ACTION_TYPE_MOD_LOCK },
{ "SetGroup", ACTION_TYPE_GROUP_SET },
{ "LatchGroup", ACTION_TYPE_GROUP_LATCH },
{ "LockGroup", ACTION_TYPE_GROUP_LOCK },
{ "MovePtr", ACTION_TYPE_PTR_MOVE },
{ "MovePointer", ACTION_TYPE_PTR_MOVE },
{ "PtrBtn", ACTION_TYPE_PTR_BUTTON },
{ "PointerButton", ACTION_TYPE_PTR_BUTTON },
{ "LockPtrBtn", ACTION_TYPE_PTR_LOCK },
{ "LockPtrButton", ACTION_TYPE_PTR_LOCK },
{ "LockPointerButton", ACTION_TYPE_PTR_LOCK },
{ "LockPointerBtn", ACTION_TYPE_PTR_LOCK },
{ "SetPtrDflt", ACTION_TYPE_PTR_DEFAULT },
{ "SetPointerDefault", ACTION_TYPE_PTR_DEFAULT },
{ "Terminate", ACTION_TYPE_TERMINATE },
{ "TerminateServer", ACTION_TYPE_TERMINATE },
{ "SwitchScreen", ACTION_TYPE_SWITCH_VT },
{ "SetControls", ACTION_TYPE_CTRL_SET },
{ "LockControls", ACTION_TYPE_CTRL_LOCK },
{ "RedirectKey", ACTION_TYPE_KEY_REDIRECT },
{ "Redirect", ACTION_TYPE_KEY_REDIRECT },
{ "Private", ACTION_TYPE_PRIVATE },
/* deprecated actions below here - unused */
{ "ISOLock", ACTION_TYPE_NONE },
{ "ActionMessage", ACTION_TYPE_NONE },
{ "MessageAction", ACTION_TYPE_NONE },
{ "Message", ACTION_TYPE_NONE },
{ "DeviceBtn", ACTION_TYPE_NONE },
{ "DevBtn", ACTION_TYPE_NONE },
{ "DevButton", ACTION_TYPE_NONE },
{ "DeviceButton", ACTION_TYPE_NONE },
{ "LockDeviceBtn", ACTION_TYPE_NONE },
{ "LockDevBtn", ACTION_TYPE_NONE },
{ "LockDevButton", ACTION_TYPE_NONE },
{ "LockDeviceButton", ACTION_TYPE_NONE },
{ "DeviceValuator", ACTION_TYPE_NONE },
{ "DevVal", ACTION_TYPE_NONE },
{ "DeviceVal", ACTION_TYPE_NONE },
{ "DevValuator", ACTION_TYPE_NONE },
{ NULL, 0 },
};
const LookupEntry symInterpretMatchMaskNames[] = {
{ "NoneOf", MATCH_NONE },
{ "AnyOfOrNone", MATCH_ANY_OR_NONE },
{ "AnyOf", MATCH_ANY },
{ "AllOf", MATCH_ALL },
{ "Exactly", MATCH_EXACTLY },
};
#define BUFFER_SIZE 1024
static char *
GetBuffer(size_t size)
{
static char buffer[BUFFER_SIZE];
static size_t next;
char *rtrn;
if (size >= BUFFER_SIZE)
return NULL;
if (BUFFER_SIZE - next <= size)
next = 0;
rtrn = &buffer[next];
next += size;
return rtrn;
}
/*
* Get a vmod name's text, where the vmod index is zero based
* (0..XKB_NUM_VIRTUAL_MODS-1).
*/
static const char *
VModIndexText(struct xkb_keymap *keymap, xkb_mod_index_t ndx)
{
int len;
char *rtrn;
const char *tmp = NULL;
char buf[20];
if (ndx >= XKB_NUM_VIRTUAL_MODS)
tmp = "illegal";
else
tmp = xkb_atom_text(keymap->ctx, keymap->vmod_names[ndx]);
if (!tmp) {
snprintf(buf, sizeof(buf) - 1, "%d", ndx);
tmp = buf;
}
len = strlen(tmp) + 1;
if (len >= BUFFER_SIZE)
len = BUFFER_SIZE - 1;
rtrn = GetBuffer(len);
strncpy(rtrn, tmp, len);
return rtrn;
}
/* Get a mod mask's text, where the mask is in rmods+vmods format. */
const char *
VModMaskText(struct xkb_keymap *keymap, xkb_mod_mask_t cmask)
{
xkb_mod_index_t i;
xkb_mod_mask_t bit;
xkb_mod_mask_t rmask, vmask;
int len, rem;
const char *mm = NULL;
char *rtrn, *str;
char buf[BUFFER_SIZE];
rmask = cmask & 0xff;
vmask = cmask >> XKB_NUM_CORE_MODS;
if (rmask == 0 && vmask == 0)
return "none";
if (rmask != 0)
mm = ModMaskText(rmask);
str = buf;
buf[0] = '\0';
rem = BUFFER_SIZE;
if (vmask != 0) {
for (i = 0, bit = 1; i < XKB_NUM_VIRTUAL_MODS && rem > 1; i++, bit <<=
1) {
if (!(vmask & bit))
continue;
len = snprintf(str, rem, "%s%s",
(str != buf) ? "+" : "",
VModIndexText(keymap, i));
rem -= len;
str += len;
}
str = buf;
}
else
str = NULL;
len = (str ? strlen(str) : 0) + (mm ? strlen(mm) : 0) +
(str && mm ? 1 : 0);
if (len >= BUFFER_SIZE)
len = BUFFER_SIZE - 1;
rtrn = GetBuffer(len + 1);
rtrn[0] = '\0';
snprintf(rtrn, len + 1, "%s%s%s", (mm ? mm : ""),
(mm && str ? "+" : ""), (str ? str : ""));
return rtrn;
}
/*
* IMPORTATNT
* The indices used for the legacy core modifiers is derived from
* the order of the names in this table. It matches the values
* ShiftMapIndex, LockMapIndex, etc. from X11/X.h. Take note before
* changing.
*/
static const char *modNames[XKB_NUM_CORE_MODS] = {
"Shift",
"Lock",
"Control",
"Mod1",
"Mod2",
"Mod3",
"Mod4",
"Mod5",
};
xkb_mod_index_t
ModNameToIndex(const char *name)
{
xkb_mod_index_t i;
for (i = 0; i < XKB_NUM_CORE_MODS; i++)
if (istreq(name, modNames[i]))
return i;
return XKB_MOD_INVALID;
}
const char *
ModIndexToName(xkb_mod_index_t ndx)
{
if (ndx < XKB_NUM_CORE_MODS)
return modNames[ndx];
return NULL;
}
const char *
ModIndexText(xkb_mod_index_t ndx)
{
const char *name;
char *buf;
name = ModIndexToName(ndx);
if (name)
return name;
if (ndx == XKB_MOD_INVALID)
return "none";
buf = GetBuffer(32);
snprintf(buf, 32, "ILLEGAL_%02x", ndx);
return buf;
}
/* Gets the text for the real modifiers only. */
const char *
ModMaskText(xkb_mod_mask_t mask)
{
int i, rem;
xkb_mod_index_t bit;
char *str, *buf;
if ((mask & 0xff) == 0xff)
return "all";
if ((mask & 0xff) == 0)
return "none";
rem = 64;
buf = GetBuffer(rem);
str = buf;
buf[0] = '\0';
for (i = 0, bit = 1; i < XKB_NUM_CORE_MODS && rem > 1; i++, bit <<= 1) {
int len;
if (!(mask & bit))
continue;
len = snprintf(str, rem, "%s%s",
(str != buf ? "+" : ""), modNames[i]);
rem -= len;
str += len;
}
return buf;
}
const char *
ActionTypeText(unsigned type)
{
const char *name = LookupValue(actionTypeNames, type);
return name ? name : "Private";
}
const char *
KeysymText(xkb_keysym_t sym)
{
static char buffer[64];
xkb_keysym_get_name(sym, buffer, sizeof buffer);
return buffer;
}
const char *
KeyNameText(const char name[XKB_KEY_NAME_LENGTH])
{
char *buf;
int len;
buf = GetBuffer(7);
buf[0] = '<';
strncpy(&buf[1], name, 4);
buf[5] = '\0';
len = strlen(buf);
buf[len++] = '>';
buf[len] = '\0';
return buf;
}
const char *
SIMatchText(enum xkb_match_operation type)
{
const char *name;
char *buf;
type &= MATCH_OP_MASK;
name = LookupValue(symInterpretMatchMaskNames, type);
if (name)
return name;
buf = GetBuffer(40);
snprintf(buf, 40, "0x%x", type);
return buf;
}