如何在ncurses下可靠地处理KEY_HOME和KEY_END

时间:2019-03-26 12:42:19

标签: c ncurses

我正在努力让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);
}

使用-inccurses进行编译,然后将stderr重定向到日志文件。 按下HOME时:

test: read: 1b
test: read: 5b
test: read: 31
test: read: 7e

按UP

test: read: 103

为什么ncurses不能将HOME和END(甚至F1等)解析为KEY_HOME?

2 个答案:

答案 0 :(得分:2)

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

查看
infocmp linux xterm | grep khome

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

答案 1 :(得分:0)

我认为您不应在诅咒上下文中使用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);
}