我正在编写一个终端程序来识别单个按键,包括键盘键,但如果可能的话,我不希望在诅咒/程序模式下这样做。我认为我可能只是利用诅咒和tcgetattr()和tcsetattr()来完成我想要的外部诅咒模式,而不是使用诅咒I/O函数为我完成键盘键的转换,而不是使用still和某种映射或树结构来实现快速键盘键匹配。令我非常惊讶的是,这是可行的(Linux,ncurses 6.1.20180127):
/**
* Most error checking elided for brevity.
*/
#include <stdio.h> // printf
#include <string.h> // memcpy
#include <curses.h>
#include <termios.h> // tcgetattr, tcsetattr
int main(void)
{
struct termios curr, new_shell_mode;
int c, fd;
SCREEN *sp;
FILE *ttyf;
/*
* Initialize desired abilities in curses.
* This unfortunately clears the screen, so
* a refresh() is required, followed by
* endwin().
*/
ttyf = fopen("/dev/tty", "r+b");
fd = fileno(ttyf);
sp = newterm(NULL, ttyf, ttyf);
raw();
noecho();
nonl();
keypad(stdscr, TRUE);
refresh();
// Save the current curses mode TTY attributes for later use.
tcgetattr(fd, &curr);
endwin();
/*
* Set the shell/non-curses mode TTY attributes to
* match those of program/curses mode (3 attempts).
*/
memcpy(&new_shell_mode, &curr, sizeof curr);
for (c = 0; c < 3; c++) {
tcsetattr(fd, TCSADRAIN, &new_shell_mode);
tcgetattr(fd, &curr);
if (0 == memcmp(&new_shell_mode, &curr, sizeof curr))
break;
}
// If new shell mode could fully be set, get a key press.
if (c != 3)
c = getch();
reset_shell_mode();
delscreen(sp);
fclose(ttyf);
printf("%02X\n", c);
return 0;
}但是,考虑到我已经退出了诅咒模式,仍然以所示的方式使用getch()是否安全/可移植?
或者,我是否需要采取更困难的路径,使用setupterm()加载strnames数组并遍历strnames数组,为每个数组调用tigetstr(),再手动设置自己的termios标志,并自行读取按键呢?
XSI规范中没有任何东西禁止这一点,只要stdscr仍然有效,这似乎在程序退出或调用delwin()之前都是有效的,我可以继续使用它,而且由于stdscr连接到作为终端的ttyf文件,所以我可以使用它获得按键,而无需自己处理一切。
发布于 2019-01-13 01:07:47
您使用newterm,初始化了诅咒,如果使用refresh作为调用getch.的副作用,那么您调用的将恢复全屏模式。
这不仅是ncurses,还包括任何诅咒实现(除了1980年代长期过时的BSD版本)。X/公开诅咒注释
如果当前或指定的窗口不是衬垫,并且自上次刷新操作以来已被移动或修改,则将在读取其他字符之前刷新该窗口。
在您的示例中,没有任何内容被“移动或修改”。但是getch检查。( endwin/termios的内容可能没有什么好处,因为newterm在第一个refresh).之前不执行清屏幕操作。)
https://stackoverflow.com/questions/54164942
复制相似问题