我正在努力让ncurses生成KEY_HOME或KEY_END事件,而原始转义序列将作为一系列字符出现。
以下简单的C程序说明了这个问题:
#define _XOPEN_SOURCE 700
#include <curses.h>
#include <stdio.h>
#include <stdlib.h>
#include <err.h>
void clean(void)
{
echo();
nl();
nocbreak();
endwin();
}
int main(int argc, char *argv[])
{
setvbuf(stderr, NULL, _IONBF, 0);
initscr();
cbreak();
nonl();
noecho();
atexit(clean);
keypad(stdscr, TRUE);
clear();
refresh();
int ch = getch();
if (ch == ERR)
errx(EXIT_FAILURE, "getch");
warnx("read: %x", ch);
halfdelay(1);
while((ch = getch()) != ERR)
{
warnx("read: %x", ch);
}
exit(EXIT_SUCCESS);
}
使用-lncurses进行编译,并将stderr重定向到日志文件。按HOME时:
test: read: 1b
test: read: 5b
test: read: 31
test: read: 7e
按UP时
test: read: 103
为什么HOME和END(实际上是F1等)没有被ncurses解析为KEY_HOME?
您可能已将TERM
设置为与终端行为不匹配的值。例如,linux
终端描述有khome=\E[1~
(对应于示例输出),而xterm
有khome=\E[OH
。你可以看到这个
infocmp linux xterm | grep khome
如果终端描述与实际行为不匹配,则ncurses将不会与传入的字节匹配,并且行为如图所示。
我认为你不应该在curses上下文中使用warnx
。
如果你使用mvprintw
代替,问题似乎消失了。
int main(int argc, char *argv[])
{
setvbuf(stderr, NULL, _IONBF, 0);
initscr();
cbreak();
nonl();
noecho();
int y = 1;
atexit(clean);
keypad(stdscr, TRUE);
clear();
refresh();
int ch = getch();
if (ch == ERR)
errx(EXIT_FAILURE, "getch");
mvprintw(y++, 1, "read: %x", ch);
halfdelay(1);
while((ch = getch()) != ERR)
{
mvprintw(y++, 1, "read: %x", ch);
}
/* added some sleep to see the result */
sleep(3);
exit(EXIT_SUCCESS);
}