NCurses 标准输入重定向

NCurses stdin redirection

我不明白为什么 getch() 函数 returns 如果我有一个应用程序,它总是出错 以这种方式设置(剥离到骨头):

static char data[DATA_SIZE]; // Very big - covers all input for sure

int main(int argn, char ** argv)
{

  // Slurp the file in
  int length = read(0, &data[0], DATA_SIZE);
  if (length == 0)
  {
    fprintf(stderr, "Nothing to read\n");
    return 0;
  }

  initscr();
  cbreak();
  refresh();
  WINDOW * woutput = newwin(LINES - 1, COLS, 0, 0);
  WINDOW * winput  = newwin(1, COLS, LINES - 1, 0);
  wattron(winput, A_REVERSE);
  keypad(winput, TRUE);

   //print the data buffer into a window

  int c;
  while ((c = wgetch(winput)) != 'q')
  {
  }
}

我运行是这样申请的:

./application < path/to/file

但是wgetch的结果总是'ERR'

由于您已读取 stdin 直到文件末尾,因此 wgetch 在尝试读取时将立即接收到文件末尾。但是无论如何,您都不希望 ncurses 使用重定向的 stdin;你想让它使用终端。

这样做的一种方法是在调用 initscr:

之前简单地重新打开 stdin 作为终端
#include <stdio.h>
#include <ncurses.h>

int main(int argn, char ** argv)
{
  // Just discard all of stdin for a minimal example
  while (fgetc(stdin) != EOF) { }

  // See note
  if (!freopen("/dev/tty", "r", stdin)) {
    perror("/dev/tty");
    exit(1);
  }
  initscr();

  cbreak();
  refresh();
  WINDOW * woutput = newwin(LINES - 1, COLS, 0, 0);
  WINDOW * winput  = newwin(1, COLS, LINES - 1, 0);
  wattron(winput, A_REVERSE);
  keypad(winput, TRUE);

  // Echo input into full screen
  int c;
  while ((c = wgetch(winput)) != 'q') { wechochar(woutput, c); }
  endwin();
  return 0;
}

如果您发现 freopen 难以遵循,您可以将它和以下对 initscr 的调用替换为

FILE* tty = fopen("/dev/tty", "r");
if (!tty) { perror("/dev/tty"); exit(1); }
if (!newterm(NULL, stdout, tty) {
  fprintf(stderr, "%s\n", "Unable to initialise ncurses");
  exit(1);
}

注:

在上面的代码中,我只是使用 /dev/tty 作为控制台的名称,它可能会在任何适度 Posix 兼容的系统中工作。但是,Posix 还提供了一个接口,让您可以发现当前 "controlling terminal" 的路径名,重要的是让您知道是否没有适合您的进程的路径名。有关详细信息和使用示例,请参阅 man ctermid