Ian
Ian

Reputation: 422

How to process KEY_HOME and KEY_END reliably under ncurses

I am struggling to have ncurses generate KEY_HOME or KEY_END events, instead the raw escape sequence is coming through as a sequence of characters.

The following simple C program illustrates the problem:

#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);
}

Compile with -lncurses, and redirect stderr to a log file. When pressing HOME:

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

When pressing UP

test: read: 103

How come HOME and END (and indeed F1 etc.) are not parsed by ncurses into KEY_HOME?

Upvotes: 0

Views: 461

Answers (1)

Thomas Dickey
Thomas Dickey

Reputation: 54505

You probably have set TERM to a value which does not match the terminal's behavior. For instance, the linux terminal description has khome=\E[1~ (which corresponds to the example output), while xterm has khome=\E[OH. You can see this using

infocmp linux xterm | grep khome

If the terminal description does not match the actual behavior, ncurses will not match the incoming bytes, and will behave as shown.

Upvotes: 3

Related Questions