I don't understand why the getch() function returns ERR all the time if I have an application set up in this manner (stripped to the bones):
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')
{
}
}
I run the application in this manner:
./application < path/to/file
But the result of wgetch is always 'ERR'
.
Since you have read stdin
up to the end of file, wgetch
will immediately receive an end of file when it attempts to read. But in any case, you don't want ncurses to use the redirected stdin
; you want it to use the terminal.
One way of doing this is to simply reopen stdin
as the terminal before calling initscr
:
#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;
}
If you find freopen
hard to follow, you could replace it and the following call to initscr
with
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);
}
In the above code, I just used /dev/tty
as the name of the console, which will probably work in any moderately Posix compliant system. However, Posix also provides an interface which lets you discover the pathname for the current "controlling terminal", and importantly lets you know if there isn't one for your process. See man ctermid for details and an example of use.