Emacs for Windows的TUI IME支持
本文介绍我给 GNU Emacs for Windows 上对于 TUI 的IME输入法支持.
相关的 bug报告.
1. 问题描述
在终端里面启动 emacs (emacs -nw), 输入中文字符串完成按下回车或者候选数字
emacs接收不到结果.
2. 前置知识
首先要了解Windows上的控制台方面api, 且了解Emacs相关代码
GNU Emacs政策禁止AI编写代码, 要遵循相关政策知道贡献指南.
开发流程通过邮件列表和linux一模一样.
参考链接
3. 修复过程
commit的链接
原先代码有一个分支会忽略emacs自己的状态键
if (faked_key == event->wVirtualKeyCode)
{
faked_key = 0;
return 0
}
问题出现在这个分支上, IME消息发送时, event->wVirtualKeyCode的值为0,
同时faked_key未赋值也是0, 就把IME消息给忽略了.
修复的地方同时还有处理读取字符版本的分支, emacs需要兼容Windows 9x版本,
也就是是上世纪的Windows 95等, 所用到的api会有大量ascii版本带A后缀的.
所以emacs会有多个flag变量来判断支不支持Unicode, 当前代码需要用到的变量是
w32_console_unicode_input.
原先代码的判断逻辑
if (event->uChar.AsciiChar == 0)
{
// ...
}
else if (event->uChar.AsciiChar > 0)
{
// ...
}
这个分支的判断可能在几十年前是对的, 但是现在是错误的. 根据微软文档 KEY_EVENT_RECORD
结构体的uChar类型是一个 AsciiChar 低8位, UnicodeChar 高16位的联合体
union {
WCHAR UnicodeChar;
CHAR AsciiChar;
} uChar;
所以得先判断高位的UnicodeChar, 不然会混进AsciiChar的数据导致乱码.
if ((w32_console_unicode_input && event->uChar.UnicodeChar < 128)
|| (!w32_console_unicode_input && event->uChar.AsciiChar > 0))
这样判断就能有效判断是ascii支持还是unicode, 同时还兼容了上世纪的代码.
相关技术细节bug报告会更详细.
4. 后日谈
这是我第二次给GNU项目贡献代码, 非常有趣的一次贡献, 改动的代码虽然小, 但花费了我大量的
时间和精力, 隐约有掉头发的感觉, 最后代码成功合并到emacs的master主线了.