关于C#:ncurses下如何可靠处理KEY_HOME和KEY_END

How to process KEY_HOME and KEY_END reliably under ncurses

我正在努力让 ncurses 生成 KEY_HOME 或 KEY_END 事件,而不是原始转义序列作为字符序列出现。

下面的简单 C 程序说明了这个问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#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 时:

1
2
3
4
test: read: 1b
test: read: 5b
test: read: 31
test: read: 7e

按下UP时

1
test: read: 103

ncurses 为何不将 HOME 和 END(以及 F1 等)解析为 KEY_HOME?


您可能已将 TERM 设置为与终端行为不匹配的值。例如,linux 终端描述有 khome=\\E[1~(对应于示例输出),而 xtermkhome=\\E[OH。您可以使用

看到这一点

1
infocmp linux xterm | grep khome

如果终端描述与实际行为不匹配,ncurses 将不匹配传入的字节,并且将按所示行为。