ncdirect: open an fd for the controlling terminal

Use ctermid(3) to identify the controlling terminal device.
When one exists, open(2) it up, and retain this file descriptor
across the life of the ncdirect context. Allow a failure, since
not everything requires such an fd. This will be used for tty-
specific activity such as ioctl()s and escape sequences
involving terminal replies (such as get absolute cursor
position). #752
pull/760/head
nick black 4 years ago committed by Nick Black
parent cda4253a0a
commit 93ff1d7789

@ -1,3 +1,5 @@
#include <ncurses.h> // needed for some definitions, see terminfo(3ncurses)
#include <fcntl.h>
#include <errno.h>
#include <cstring>
#include <unistd.h>
@ -335,23 +337,6 @@ nc_err_e ncdirect_render_image(ncdirect* n, const char* file, ncblitter_e blitte
return NCERR_SUCCESS;
}
int ncdirect_stop(ncdirect* nc){
int ret = 0;
if(nc){
if(nc->tcache.op && term_emit("op", nc->tcache.op, nc->ttyfp, true)){
ret = -1;
}
if(nc->tcache.sgr0 && term_emit("sgr0", nc->tcache.sgr0, nc->ttyfp, true)){
ret = -1;
}
if(nc->tcache.oc && term_emit("oc", nc->tcache.oc, nc->ttyfp, true)){
ret = -1;
}
free(nc);
}
return ret;
}
int ncdirect_fg_palindex(ncdirect* nc, int pidx){
return term_emit("setaf", tiparm(nc->tcache.setaf, pidx), nc->ttyfp, false);
}
@ -403,3 +388,72 @@ int ncdirect_printf_aligned(ncdirect* n, int y, ncalign_e align, const char* fmt
va_end(va);
return ret;
}
int get_controlling_tty(void){
char cbuf[L_ctermid + 1];
if(ctermid(cbuf) == NULL){
return -1;
}
return open(cbuf, O_RDWR | O_CLOEXEC);
}
ncdirect* ncdirect_init(const char* termtype, FILE* outfp){
if(outfp == NULL){
outfp = stdout;
}
auto ret = new ncdirect{};
if(ret == NULL){
return ret;
}
ret->ttyfp = outfp;
memset(&ret->palette, 0, sizeof(ret->palette));
int ttyfd = fileno(ret->ttyfp);
if(ttyfd < 0){
fprintf(stderr, "No file descriptor was available in outfp %p\n", outfp);
delete(ret);
return NULL;
}
int termerr;
if(setupterm(termtype, ttyfd, &termerr) != OK){
fprintf(stderr, "Terminfo error %d (see terminfo(3ncurses))\n", termerr);
delete(ret);
return NULL;
}
if(interrogate_terminfo(&ret->tcache)){
delete(ret);
return NULL;
}
// we don't need a controlling tty for everything we do; allow a failure here
ret->ctermfd = get_controlling_tty();
ret->fgdefault = ret->bgdefault = true;
ret->fgrgb = ret->bgrgb = 0;
ncdirect_styles_set(ret, 0);
const char* encoding = nl_langinfo(CODESET);
if(encoding && strcmp(encoding, "UTF-8") == 0){
ret->utf8 = true;
}else if(encoding && strcmp(encoding, "ANSI_X3.4-1968") == 0){
ret->utf8 = false;
}
return ret;
}
int ncdirect_stop(ncdirect* nc){
int ret = 0;
if(nc){
if(nc->tcache.op && term_emit("op", nc->tcache.op, nc->ttyfp, true)){
ret = -1;
}
if(nc->tcache.sgr0 && term_emit("sgr0", nc->tcache.sgr0, nc->ttyfp, true)){
ret = -1;
}
if(nc->tcache.oc && term_emit("oc", nc->tcache.oc, nc->ttyfp, true)){
ret = -1;
}
if(nc->ctermfd >= 0){
ret |= close(nc->ctermfd);
}
delete(nc);
}
return ret;
}

@ -268,9 +268,10 @@ typedef struct tinfo {
typedef struct ncdirect {
int attrword; // current styles
palette256 palette; // 256-indexed palette can be used instead of/with RGB
FILE* ttyfp; // FILE* for controlling tty
FILE* ttyfp; // FILE* for output tty
int ctermfd; // fd for controlling terminal
tinfo tcache; // terminfo cache
uint16_t fgrgb, bgrgb; // last RGB values of foreground/background
unsigned fgrgb, bgrgb; // last RGB values of foreground/background
bool fgdefault, bgdefault; // are FG/BG currently using default colors?
bool utf8; // are we using utf-8 encoding, as hoped?
} ncdirect;
@ -781,6 +782,9 @@ nc_err_e ncvisual_blit(struct ncvisual* ncv, int rows, int cols,
void nclog(const char* fmt, ...);
// get a file descriptor for the controlling tty device, -1 on error
int get_controlling_tty(void);
// logging
#define logerror(nc, fmt, ...) do{ \
if((nc)->loglevel >= NCLOGLEVEL_ERROR){ \

@ -631,44 +631,6 @@ ffmpeg_log_level(ncloglevel_e level){
#endif
}
ncdirect* ncdirect_init(const char* termtype, FILE* outfp){
if(outfp == NULL){
outfp = stdout;
}
ncdirect* ret = malloc(sizeof(*ret));
if(ret == NULL){
return ret;
}
ret->ttyfp = outfp;
memset(&ret->palette, 0, sizeof(ret->palette));
int ttyfd = fileno(ret->ttyfp);
if(ttyfd < 0){
fprintf(stderr, "No file descriptor was available in outfp %p\n", outfp);
free(ret);
return NULL;
}
int termerr;
if(setupterm(termtype, ttyfd, &termerr) != OK){
fprintf(stderr, "Terminfo error %d (see terminfo(3ncurses))\n", termerr);
free(ret);
return NULL;
}
if(interrogate_terminfo(&ret->tcache)){
free(ret);
return NULL;
}
ret->fgdefault = ret->bgdefault = true;
ret->fgrgb = ret->bgrgb = 0;
ncdirect_styles_set(ret, 0);
const char* encoding = nl_langinfo(CODESET);
if(encoding && strcmp(encoding, "UTF-8") == 0){
ret->utf8 = true;
}else if(encoding && strcmp(encoding, "ANSI_X3.4-1968") == 0){
ret->utf8 = false;
}
return ret;
}
// unless the suppress_banner flag was set, print some version information and
// (if applicable) warnings to stdout. we are not yet on the alternate screen.
static void

Loading…
Cancel
Save