【发布时间】:2018-02-09 23:58:04
【问题描述】:
在使用curses 或ncurses 库的程序中,getch() 函数可以识别普通字符(如'x')或箭头和功能键发送的转义序列。例如,键入向上箭头键可能会发送序列(Escape、'['、'A'),但getch() 将返回int 值KEY_UP。它甚至使用时间信息来区分自己发送的转义字符和序列中的转义字符。
要成功使用getch(),您首先必须调用initscr(),它会清除屏幕以便curses 可以控制显示的内容。
有没有一种方便的方法来识别特殊键而不占据屏幕?理想情况下,我想在不先调用initscr() 的情况下调用getch(),并让它返回与调用initscr() 相同的值,但实验表明这不起作用。
这是我正在尝试做的一个无效示例。程序提示用户输入 Up、Down、Escape、Left、Right,并确认输入了正确的键。
使用-c 运行程序会调用initscr() 并使其正常工作。在没有-c 的情况下运行它会调用getch() 而无需先调用initscr();所有getch() 调用都没有等待输入就失败,返回ERR (-1)。
// gcc arrows.c -o arrows -lncurses
#include <term.h>
#include <stdio.h>
#include <curses.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int use_curses = 0;
if (argc == 2 && strcmp(argv[1], "-c") == 0) {
use_curses = 1;
}
else if (argc != 1) {
fprintf(stderr, "Usage: %s [-c]\n", argv[0]);
exit(EXIT_FAILURE);
}
WINDOW *win;
if (use_curses) {
win = initscr();
cbreak();
noecho();
nonl();
intrflush(stdscr, FALSE);
keypad(stdscr, TRUE);
mvaddstr(0, 0, "Press UP, DOWN, Escape, LEFT, RIGHT");
}
else {
puts("Press UP, DOWN, Escape, LEFT, RIGHT");
}
int keys[5];
for (int i = 0; i < 5; i ++) {
keys[i] = getch();
}
int ok;
if (keys[0] == KEY_UP &&
keys[1] == KEY_DOWN &&
keys[2] == '\x1b' &&
keys[3] == KEY_LEFT &&
keys[4] == KEY_RIGHT)
{
ok = 1;
if (use_curses) {
mvaddstr(2, 0, "OK");
}
else {
puts("OK");
}
}
else {
ok = 0;
char message[100];
sprintf(message,
"Incorrect input: (%d, %d, %d, %d, %d)",
keys[0], keys[1], keys[2], keys[3], keys[4]);
if (use_curses) {
mvaddstr(2, 0, message);
}
else {
puts(message);
}
}
if (use_curses) {
mvaddstr(4, 0, "Press any key to quit ");
(void)getch();
endwin();
}
exit(ok ? EXIT_SUCCESS : EXIT_FAILURE);
}
没有-c 选项的输出(在 Ubuntu 17.04 x86_64 上)是:
Press UP, DOWN, Escape, LEFT, RIGHT
Incorrect input: (-1, -1, -1, -1, -1)
更新:使用除诅咒以外的解决方案就可以了。它必须直接或间接地使用 terminfo 来了解要查找的输入序列。 (在我看来,识别特殊键输入应该很简单,并且与接管整个屏幕密切相关。)
【问题讨论】:
-
没时间回答,但也许
man 3 termcap与你想要的有关 -
curses 库不提供这样的代码,AFAIK。您必须自己使用终端属性。您可能会发现(部分)How to distinguish between escape and escape sequence 中的讨论很有用。问题的一部分是为键序列定义代码。另一部分是识别关键序列。其余大部分或多或少是机械编码。