From d3f9329737b9fa668664dde4b42e5467611a6abf Mon Sep 17 00:00:00 2001 From: nick black Date: Tue, 19 Nov 2019 09:54:14 -0500 Subject: [PATCH] notcurses_options: allow outfd to be specified --- include/notcurses.h | 4 ++++ src/bin/demo.c | 7 ++++++- src/lib/notcurses.c | 8 +++++++- tests/notcurses.cpp | 5 +++-- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/notcurses.h b/include/notcurses.h index 6dc114f44..9e1b7049b 100644 --- a/include/notcurses.h +++ b/include/notcurses.h @@ -17,6 +17,10 @@ typedef struct notcurses_options { // the environment variable TERM is used. Failure to open the terminal // definition will result in failure to initialize notcurses. const char* termtype; + // A file descriptor for this terminal on which we will generate output. + // Must be a valid file descriptor attached to a terminal, or notcurses will + // refuse to start. You'll usually want STDOUT_FILENO. + int outfd; // If smcup/rmcup capabilities are indicated, notcurses defaults to making // use of the "alternate screen." This flag inhibits use of smcup/rmcup. bool inhibit_alternate_screen; diff --git a/src/bin/demo.c b/src/bin/demo.c index e57543823..9fbadec61 100644 --- a/src/bin/demo.c +++ b/src/bin/demo.c @@ -5,7 +5,12 @@ int main(void){ struct notcurses* nc; - if((nc = notcurses_init(NULL)) == NULL){ + notcurses_options nopts = { + .inhibit_alternate_screen = false, + .outfd = STDOUT_FILENO, + .termtype = NULL, + }; + if((nc = notcurses_init(&nopts)) == NULL){ return EXIT_FAILURE; } if(notcurses_fg_rgb8(nc, 200, 0, 200)){ diff --git a/src/lib/notcurses.c b/src/lib/notcurses.c index e17d1df95..62086d804 100644 --- a/src/lib/notcurses.c +++ b/src/lib/notcurses.c @@ -145,12 +145,15 @@ alloc_plane(notcurses* nc, cell* oldplane, int* rows, int* cols){ // FIXME should probably register a SIGWINCH handler here // FIXME install other sighandlers to clean things up notcurses* notcurses_init(const notcurses_options* opts){ +if(!ttyname(opts->outfd)){ + exit(EXIT_FAILURE); +} struct termios modtermios; notcurses* ret = malloc(sizeof(*ret)); if(ret == NULL){ return ret; } - ret->ttyfd = STDOUT_FILENO; // FIXME use others if stdout is redirected? + ret->ttyfd = opts->outfd; if(tcgetattr(ret->ttyfd, &ret->tpreserved)){ fprintf(stderr, "Couldn't preserve terminal state for %d (%s)\n", ret->ttyfd, strerror(errno)); @@ -193,6 +196,8 @@ notcurses* notcurses_init(const notcurses_options* opts){ if(!opts->inhibit_alternate_screen){ term_verify_seq(&ret->smcup, "smcup"); term_verify_seq(&ret->rmcup, "rmcup"); + }else{ + ret->smcup = ret->rmcup = NULL; } if((ret->plane = alloc_plane(ret, NULL, &ret->rows, &ret->cols)) == NULL){ goto err; @@ -224,6 +229,7 @@ int notcurses_stop(notcurses* nc){ return ret; } +// FIXME don't go using STDOUT_FILENO here, we want nc->outfd! // only works with string literals! #define strout(x) write(STDOUT_FILENO, (x), sizeof(x)) diff --git a/tests/notcurses.cpp b/tests/notcurses.cpp index 2e24acc12..1dc33258a 100644 --- a/tests/notcurses.cpp +++ b/tests/notcurses.cpp @@ -9,7 +9,9 @@ class NotcursesTest : public :: testing::Test { if(getenv("TERM") == nullptr){ GTEST_SKIP(); } - nc_ = notcurses_init(nullptr); + notcurses_options nopts{}; + nopts.outfd = STDIN_FILENO; + nc_ = notcurses_init(&nopts); ASSERT_NE(nullptr, nc_); } @@ -21,7 +23,6 @@ TEST_F(NotcursesTest, BasicLifetime) { } TEST_F(NotcursesTest, TermDimensions) { - ASSERT_NE(nullptr, nc_); int x, y; EXPECT_EQ(0, notcurses_term_dimensions(nc_, &y, &x)); auto stry = getenv("LINES");