让您的程序从配置文件中读取名称到代码的映射,例如/usr/share/yourprogram/keycodes
和/或$HOME/.yourprogram/keycodes
.
记录任何人都可以从他们的文件中重新生成该文件/usr/include/linux/input.h
- 并自己重新生成初始文件 - 例如使用
awk '$2 ~ /^KEY_/ { code[$2] = $3 }
END {
for (name in code)
if (code[name] ~ /^KEY_/)
code[name] = code[code[name]];
for (name in code)
if (code[name] !~ /KEY_/)
printf "%-24s %s\n", name, code[name]
}' /usr/include/linux/input.h | sort
您可能需要自己添加KEY_CNT
(它的值比 大一KEY_MAX
),因为上面的脚本不做数学运算,只做直接别名。
为了描述名称到代码的映射,我会使用
struct keycode {
struct keycode *next;
unsigned int code;
unsigned int hash;
unsigned char namelen;
char name[];
};
其中哈希是一个简单的哈希,比如 djb2,
unsigned int djb2(const char *const str, const size_t len)
{
unsigned int result = 5831U;
size_t i;
for (i = 0; i < len; i++)
result = result * 33U ^ (unsigned int)str[i];
return result;
}
当前定义的键码中,只有KEY_CUT
和KEY_F15
映射到相同的 djb2 哈希,1857856141。(如果你使用31U
而不是33U
,当前集合将没有冲突,但这并不能证明未来的冲突。最好已经有一个冲突,所以你可以测试它被正确处理。)
读取配置文件的函数可以通过将新代码添加到单链表来返回代码,也许
int read_keycodes(const char *const filename,
struct keycode **list);
如果您添加到列表中,您应该稍后忽略同名的重新定义。这样,如果您首先阅读系统范围的配置,然后是特定于用户的配置,则特定于用户的配置可以覆盖系统范围的配置。
读取所有键码映射后,您将构建一个哈希表,例如
struct keytab {
unsigned int size; /* index = hash % size */
struct keycode **slot;
};
(在构建哈希表时,丢弃其确切名称已经在 keytab 中的键码。这样以后的定义会覆盖之前的定义。)
这样你只需要计算你要查找的名字的哈希值,然后在你的keytab结构中探测链表。首先比较哈希,然后是长度;如果两者都匹配,最后做一个strcmp()
. 这样查找将非常快,并且实现起来也相对简单。使用当前的密钥代码,您只需为和执行strcmp()
两次慢速操作;对于所有其他人,一个就足够了。KEY_F15
KEY_CUT
strcmp()
问题?