当在键盘上按下按键时,许多硬件和软件组件协同工作,以确保按键的预期含义(例如,发出特定字符)与按键的实际行为相匹配。我将专注于软件方面(因为我们对硬件部分的控制是不存在的),特别是,目前,专注于与控制台输出相关的事件。
按下按键会生成原始键盘扫描码;这些扫描码随后被转换为键码。在 i386 系统上,通常 退格键 发出 14,而 删除键 发出 111。
键码通过键盘库使用用户加载的键盘定义转换为键盘符号 (keysym)。如果您查看您的键盘数据库(例如,在/lib/kbd/中),您会发现针对不同计算机、不同布局以及可能对相同按键的不同解释的若干定义(例如,可能有人希望两个 Alt 键真正表现为不同的修饰键)。Linux 控制台键盘布局将键码 14 分配给键盘符号 Delete,并将键码 111 分配给键盘符号 Remove。这可能看起来很奇怪,但 Linux 控制台模拟 VT100 终端,这就是该领域的工作方式。[1]
我们的旅程尚未结束。控制台应用程序读取 ASCII 序列,而不是键盘符号。因此,控制台必须读取键盘符号并将它们转换为 ASCII 序列,以适当地编码按键。当然,此操作的执行方式必须是应用程序可以理解的。例如,在 Linux 控制台上,Delete 键盘符号映射到 ASCII 代码 127 (DEL),Remove 键盘符号映射到合适的转义序列,而 BackSpace 键盘符号映射到 ASCII 代码 8 (BS)。
最后,我们必须在某种意义上回滚到我们之前的内容,并将每个按键生成的 ASCII 序列转换为按键功能。此目标通过终端数据库实现,该数据库包含针对每种终端,从字符序列到按键功能(本质上是键盘符号的子集)的反向映射。[2]
![]() | 不幸的是,存在两个 “标准” 终端数据库,termcap 和 terminfo。根据您的发行版,您可能正在使用其中任何一个,或者数据库甚至可能取决于应用程序。我们的讨论将集中在更现代的 terminfo 数据库上,但建议的修复方法同时考虑了两者。 |
例如,在 Linux 控制台上,F1 生成一个转义符,后跟[[A,这可以转换为功能key_f1通过查看控制台的终端数据库条目(如果您想查看该条目,请尝试 infocmp linux)。关于终端数据库的非常好的和全面的讨论可以在 GNU 的 termcap 手册中找到。通常,Linux 应用程序使用更新的 terminfo 数据库,该数据库包含在 ncurses 软件包中。
也许在这一点上并不奇怪,Linux 控制台 terminfo 条目将 DEL 映射到kbs(退格键功能),以及转义符后跟[3~到kdch1(“删除一个字符” 键)功能。即使您可能觉得 退格键 发出 DEL 很奇怪,但终端数据库会将一切放回原位,并且行为正确的应用程序会将 DEL 解释为功能kbs,从而删除光标左侧的字符。
[1] | 此声明已被多次断言/质疑,评论了本文档。如果您对此主题有任何确凿的信息,请写信给我。 |
[2] | 某些程序依赖于终端驱动程序进行输入行编辑,例如删除字符或单词。使用 stty,您可以告诉终端驱动程序它应该使用什么字符来删除光标左侧的字符(擦除字符)。您可以使用 stty -a 检查您当前的设置,并使用 stty erase 字符 设置它们。 |