Как надежно обрабатывать KEY_HOME и KEY_END под ncurses - PullRequest
0 голосов
/ 26 марта 2019

Я пытаюсь, чтобы ncurses генерировал события KEY_HOME или KEY_END, вместо этого необработанная escape-последовательность проходит как последовательность символов.

Следующая простая программа на 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?

Ответы [ 2 ]

2 голосов
/ 26 марта 2019

Возможно, вы установили TERM в значение, которое не соответствует поведению терминала.Например, описание терминала linux имеет khome=\E[1~ (что соответствует выходному примеру), в то время как xtermимеет khome=\E[OH.Это можно увидеть с помощью

infocmp linux xterm | grep khome

Если описание терминала не соответствует фактическому поведению, ncurses не будет соответствовать входящим байтам и будет вести себя так, как показано.

0 голосов
/ 26 марта 2019

Я думаю, вы не должны использовать 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);
}
...