split direct into its own header

This commit is contained in:
nick black 2020-07-10 15:51:28 -04:00 committed by Nick Black
parent b617587ade
commit 750f88b70a
13 changed files with 228 additions and 202 deletions

View File

@ -8,7 +8,7 @@ ncdirect_init - minimal notcurses instances for styling text
# SYNOPSIS
**#include <notcurses/notcurses.h>**
**#include <notcurses/direct.h>**
**struct ncdirect* ncdirect_init(const char* termtype, FILE* fp);**

View File

@ -2,6 +2,7 @@
#define __NCPP_DIRECT_HH
#include <cstdio>
#include <notcurses/direct.h>
#include <notcurses/notcurses.h>
#include "Root.hh"

108
include/notcurses/direct.h Normal file
View File

@ -0,0 +1,108 @@
#ifndef NOTCURSES_DIRECT
#define NOTCURSES_DIRECT
#include <notcurses/notcurses.h>
#ifdef __cplusplus
extern "C" {
#endif
#define API __attribute__((visibility("default")))
// Initialize a direct-mode notcurses context on the connected terminal at 'fp'.
// 'fp' must be a tty. You'll usually want stdout. Direct mode supportes a
// limited subset of notcurses routines which directly affect 'fp', and neither
// supports nor requires notcurses_render(). This can be used to add color and
// styling to text in the standard output paradigm. Returns NULL on error,
// including any failure initializing terminfo.
API struct ncdirect* ncdirect_init(const char* termtype, FILE* fp);
// Direct mode. This API can be used to colorize and stylize output generated
// outside of notcurses, without ever calling notcurses_render(). These should
// not be intermixed with standard notcurses rendering.
API int ncdirect_fg(struct ncdirect* nc, unsigned rgb);
API int ncdirect_bg(struct ncdirect* nc, unsigned rgb);
API int ncdirect_fg_palindex(struct ncdirect* nc, int pidx);
API int ncdirect_bg_palindex(struct ncdirect* nc, int pidx);
// Returns the number of simultaneous colors claimed to be supported, or 1 if
// there is no color support. Note that several terminal emulators advertise
// more colors than they actually support, downsampling internally.
API int ncdirect_palette_size(const struct ncdirect* nc);
// Output the EGC |egc| according to the channels |channels|.
API int ncdirect_putc(struct ncdirect* nc, uint64_t channels, const char* egc);
static inline int
ncdirect_bg_rgb(struct ncdirect* nc, unsigned r, unsigned g, unsigned b){
if(r > 255 || g > 255 || b > 255){
return -1;
}
return ncdirect_bg(nc, (r << 16u) + (g << 8u) + b);
}
static inline int
ncdirect_fg_rgb(struct ncdirect* nc, unsigned r, unsigned g, unsigned b){
if(r > 255 || g > 255 || b > 255){
return -1;
}
return ncdirect_fg(nc, (r << 16u) + (g << 8u) + b);
}
API int ncdirect_fg_default(struct ncdirect* nc);
API int ncdirect_bg_default(struct ncdirect* nc);
// Get the current number of columns/rows.
API int ncdirect_dim_x(const struct ncdirect* nc);
API int ncdirect_dim_y(const struct ncdirect* nc);
// ncplane_styles_*() analogues
API int ncdirect_styles_set(struct ncdirect* n, unsigned stylebits);
API int ncdirect_styles_on(struct ncdirect* n, unsigned stylebits);
API int ncdirect_styles_off(struct ncdirect* n, unsigned stylebits);
// Move the cursor in direct mode. -1 to retain current location on that axis.
API int ncdirect_cursor_move_yx(struct ncdirect* n, int y, int x);
API int ncdirect_cursor_enable(struct ncdirect* nc);
API int ncdirect_cursor_disable(struct ncdirect* nc);
API int ncdirect_cursor_up(struct ncdirect* nc, int num);
API int ncdirect_cursor_left(struct ncdirect* nc, int num);
API int ncdirect_cursor_right(struct ncdirect* nc, int num);
API int ncdirect_cursor_down(struct ncdirect* nc, int num);
// Get the cursor position, when supported. This requires writing to the
// terminal, and then reading from it. If the terminal doesn't reply, or
// doesn't reply in a way we understand, the results might be deleterious.
API int ncdirect_cursor_yx(struct ncdirect* n, int* y, int* x);
// Push or pop the cursor location to the terminal's stack. The depth of this
// stack, and indeed its existence, is terminal-dependent.
API int ncdirect_cursor_push(struct ncdirect* n);
API int ncdirect_cursor_pop(struct ncdirect* n);
// Formatted printing (plus alignment relative to the terminal).
API int ncdirect_printf_aligned(struct ncdirect* n, int y, ncalign_e align,
const char* fmt, ...)
__attribute__ ((format (printf, 4, 5)));
// Display an image using the specified blitter and scaling. The image may
// // be arbitrarily many rows -- the output will scroll -- but will only occupy
// // the column of the cursor, and those to the right.
API nc_err_e ncdirect_render_image(struct ncdirect* n, const char* filename,
ncalign_e align, ncblitter_e blitter,
ncscale_e scale);
// Clear the screen.
API int ncdirect_clear(struct ncdirect* nc);
// Release 'nc' and any associated resources. 0 on success, non-0 on failure.
API int ncdirect_stop(struct ncdirect* nc);
#undef API
#ifdef __cplusplus
}
#endif
#endif

View File

@ -76,96 +76,6 @@ typedef enum {
NCSCALE_STRETCH,
} ncscale_e;
// Initialize a direct-mode notcurses context on the connected terminal at 'fp'.
// 'fp' must be a tty. You'll usually want stdout. Direct mode supportes a
// limited subset of notcurses routines which directly affect 'fp', and neither
// supports nor requires notcurses_render(). This can be used to add color and
// styling to text in the standard output paradigm. Returns NULL on error,
// including any failure initializing terminfo.
API struct ncdirect* ncdirect_init(const char* termtype, FILE* fp);
// Direct mode. This API can be used to colorize and stylize output generated
// outside of notcurses, without ever calling notcurses_render(). These should
// not be intermixed with standard notcurses rendering.
API int ncdirect_fg(struct ncdirect* nc, unsigned rgb);
API int ncdirect_bg(struct ncdirect* nc, unsigned rgb);
API int ncdirect_fg_palindex(struct ncdirect* nc, int pidx);
API int ncdirect_bg_palindex(struct ncdirect* nc, int pidx);
// Returns the number of simultaneous colors claimed to be supported, or 1 if
// there is no color support. Note that several terminal emulators advertise
// more colors than they actually support, downsampling internally.
API int ncdirect_palette_size(const struct ncdirect* nc);
// Output the EGC |egc| according to the channels |channels|.
API int ncdirect_putc(struct ncdirect* nc, uint64_t channels, const char* egc);
static inline int
ncdirect_bg_rgb(struct ncdirect* nc, unsigned r, unsigned g, unsigned b){
if(r > 255 || g > 255 || b > 255){
return -1;
}
return ncdirect_bg(nc, (r << 16u) + (g << 8u) + b);
}
static inline int
ncdirect_fg_rgb(struct ncdirect* nc, unsigned r, unsigned g, unsigned b){
if(r > 255 || g > 255 || b > 255){
return -1;
}
return ncdirect_fg(nc, (r << 16u) + (g << 8u) + b);
}
API int ncdirect_fg_default(struct ncdirect* nc);
API int ncdirect_bg_default(struct ncdirect* nc);
// Get the current number of columns/rows.
API int ncdirect_dim_x(const struct ncdirect* nc);
API int ncdirect_dim_y(const struct ncdirect* nc);
// ncplane_styles_*() analogues
API int ncdirect_styles_set(struct ncdirect* n, unsigned stylebits);
API int ncdirect_styles_on(struct ncdirect* n, unsigned stylebits);
API int ncdirect_styles_off(struct ncdirect* n, unsigned stylebits);
// Move the cursor in direct mode. -1 to retain current location on that axis.
API int ncdirect_cursor_move_yx(struct ncdirect* n, int y, int x);
API int ncdirect_cursor_enable(struct ncdirect* nc);
API int ncdirect_cursor_disable(struct ncdirect* nc);
API int ncdirect_cursor_up(struct ncdirect* nc, int num);
API int ncdirect_cursor_left(struct ncdirect* nc, int num);
API int ncdirect_cursor_right(struct ncdirect* nc, int num);
API int ncdirect_cursor_down(struct ncdirect* nc, int num);
// Get the cursor position, when supported. This requires writing to the
// terminal, and then reading from it. If the terminal doesn't reply, or
// doesn't reply in a way we understand, the results might be deleterious.
API int ncdirect_cursor_yx(struct ncdirect* n, int* y, int* x);
// Push or pop the cursor location to the terminal's stack. The depth of this
// stack, and indeed its existence, is terminal-dependent.
API int ncdirect_cursor_push(struct ncdirect* n);
API int ncdirect_cursor_pop(struct ncdirect* n);
// Formatted printing (plus alignment relative to the terminal).
API int ncdirect_printf_aligned(struct ncdirect* n, int y, ncalign_e align,
const char* fmt, ...)
__attribute__ ((format (printf, 4, 5)));
// Display an image using the specified blitter and scaling. The image may
// // be arbitrarily many rows -- the output will scroll -- but will only occupy
// // the column of the cursor, and those to the right.
API nc_err_e ncdirect_render_image(struct ncdirect* n, const char* filename,
ncalign_e align, ncblitter_e blitter,
ncscale_e scale);
// Clear the screen.
API int ncdirect_clear(struct ncdirect* nc);
// Release 'nc' and any associated resources. 0 on success, non-0 on failure.
API int ncdirect_stop(struct ncdirect* nc);
// Returns the number of columns occupied by a multibyte (UTF-8) string, or
// -1 if a non-printable/illegal character is encountered.
static inline int

View File

@ -4,6 +4,7 @@ ffibuild = FFI()
ffibuild.set_source(
"_notcurses",
"""
#include <notcurses/direct.h>
#include <notcurses/notcurses.h>
""",
libraries=["notcurses"],

View File

@ -9,6 +9,7 @@
#include <getopt.h>
#include <stdlib.h>
#include <stdatomic.h>
#include <notcurses/direct.h>
#include "demo.h"
// (non-)ansi terminal definition-4-life

View File

@ -9,6 +9,7 @@
#include <sys/sysinfo.h>
#endif
#include <sys/utsname.h>
#include <notcurses/direct.h>
#include <notcurses/notcurses.h>
typedef struct distro_info {

View File

@ -6,6 +6,7 @@
#include <termios.h>
#include "version.h"
#include "visual-details.h"
#include "notcurses/direct.h"
#include "internal.h"
int ncdirect_putc(ncdirect* nc, uint64_t channels, const char* egc){
@ -471,3 +472,82 @@ int ncdirect_stop(ncdirect* nc){
return ret;
}
static inline int
ncdirect_style_emit(ncdirect* n, const char* sgr, unsigned stylebits, FILE* out){
if(sgr == NULL){
return -1;
}
int r = term_emit("sgr", tiparm(sgr, stylebits & NCSTYLE_STANDOUT,
stylebits & NCSTYLE_UNDERLINE,
stylebits & NCSTYLE_REVERSE,
stylebits & NCSTYLE_BLINK,
stylebits & NCSTYLE_DIM,
stylebits & NCSTYLE_BOLD,
stylebits & NCSTYLE_INVIS,
stylebits & NCSTYLE_PROTECT, 0), out, false);
// sgr resets colors, so set them back up if not defaults
if(r == 0){
if(!n->fgdefault){
r |= ncdirect_fg(n, n->fgrgb);
}
if(!n->bgdefault){
r |= ncdirect_bg(n, n->bgrgb);
}
}
return r;
}
int ncdirect_styles_on(ncdirect* n, unsigned stylebits){
n->attrword |= stylebits;
if(ncdirect_style_emit(n, n->tcache.sgr, n->attrword, n->ttyfp)){
return 0;
}
return term_setstyle(n->ttyfp, n->attrword, stylebits, NCSTYLE_ITALIC,
n->tcache.italics, n->tcache.italoff);
}
// turn off any specified stylebits
int ncdirect_styles_off(ncdirect* n, unsigned stylebits){
n->attrword &= ~stylebits;
if(ncdirect_style_emit(n, n->tcache.sgr, n->attrword, n->ttyfp)){
return 0;
}
return term_setstyle(n->ttyfp, n->attrword, stylebits, NCSTYLE_ITALIC,
n->tcache.italics, n->tcache.italoff);
}
// set the current stylebits to exactly those provided
int ncdirect_styles_set(ncdirect* n, unsigned stylebits){
n->attrword = stylebits;
if(ncdirect_style_emit(n, n->tcache.sgr, n->attrword, n->ttyfp)){
return 0;
}
return term_setstyle(n->ttyfp, n->attrword, stylebits, NCSTYLE_ITALIC,
n->tcache.italics, n->tcache.italoff);
}
int ncdirect_palette_size(const ncdirect* nc){
return nc->tcache.colors;
}
int ncdirect_fg_default(ncdirect* nc){
if(term_emit("op", nc->tcache.op, nc->ttyfp, false) == 0){
nc->fgdefault = true;
if(nc->bgdefault){
return 0;
}
return ncdirect_bg(nc, nc->fgrgb);
}
return -1;
}
int ncdirect_bg_default(ncdirect* nc){
if(term_emit("op", nc->tcache.op, nc->ttyfp, false) == 0){
nc->bgdefault = true;
if(nc->fgdefault){
return 0;
}
return ncdirect_fg(nc, nc->bgrgb);
}
return -1;
}

View File

@ -823,6 +823,9 @@ int get_controlling_tty(void);
// Convert a notcurses log level to some multimedia library equivalent.
int ffmpeg_log_level(ncloglevel_e level);
int term_setstyle(FILE* out, unsigned cur, unsigned targ, unsigned stylebit,
const char* ton, const char* toff);
#ifdef __cplusplus
}
#endif

View File

@ -2,6 +2,7 @@
#include <ctype.h>
#include <limits.h>
#include <unistd.h>
#include <notcurses/direct.h>
#include "internal.h"
// Check whether the terminal geometry has changed, and if so, copies what can
@ -508,9 +509,8 @@ term_putc(FILE* out, const egcpool* e, const cell* c){
// check the current and target style bitmasks against the specified 'stylebit'.
// if they are different, and we have the necessary capability, write the
// applicable terminfo entry to 'out'. returns -1 only on a true error.
static int
term_setstyle(FILE* out, unsigned cur, unsigned targ, unsigned stylebit,
const char* ton, const char* toff){
int term_setstyle(FILE* out, unsigned cur, unsigned targ, unsigned stylebit,
const char* ton, const char* toff){
int ret = 0;
unsigned curon = cur & stylebit;
unsigned targon = targ & stylebit;
@ -694,112 +694,6 @@ term_fg_rgb8(bool RGBflag, const char* setaf, int colors, FILE* out,
return 0;
}
static inline int
ncdirect_style_emit(ncdirect* n, const char* sgr, unsigned stylebits, FILE* out){
if(sgr == NULL){
return -1;
}
int r = term_emit("sgr", tiparm(sgr, stylebits & NCSTYLE_STANDOUT,
stylebits & NCSTYLE_UNDERLINE,
stylebits & NCSTYLE_REVERSE,
stylebits & NCSTYLE_BLINK,
stylebits & NCSTYLE_DIM,
stylebits & NCSTYLE_BOLD,
stylebits & NCSTYLE_INVIS,
stylebits & NCSTYLE_PROTECT, 0), out, false);
// sgr resets colors, so set them back up if not defaults
if(r == 0){
if(!n->fgdefault){
r |= ncdirect_fg(n, n->fgrgb);
}
if(!n->bgdefault){
r |= ncdirect_bg(n, n->bgrgb);
}
}
return r;
}
int ncdirect_styles_on(ncdirect* n, unsigned stylebits){
n->attrword |= stylebits;
if(ncdirect_style_emit(n, n->tcache.sgr, n->attrword, n->ttyfp)){
return 0;
}
return term_setstyle(n->ttyfp, n->attrword, stylebits, NCSTYLE_ITALIC,
n->tcache.italics, n->tcache.italoff);
}
// turn off any specified stylebits
int ncdirect_styles_off(ncdirect* n, unsigned stylebits){
n->attrword &= ~stylebits;
if(ncdirect_style_emit(n, n->tcache.sgr, n->attrword, n->ttyfp)){
return 0;
}
return term_setstyle(n->ttyfp, n->attrword, stylebits, NCSTYLE_ITALIC,
n->tcache.italics, n->tcache.italoff);
}
// set the current stylebits to exactly those provided
int ncdirect_styles_set(ncdirect* n, unsigned stylebits){
n->attrword = stylebits;
if(ncdirect_style_emit(n, n->tcache.sgr, n->attrword, n->ttyfp)){
return 0;
}
return term_setstyle(n->ttyfp, n->attrword, stylebits, NCSTYLE_ITALIC,
n->tcache.italics, n->tcache.italoff);
}
int ncdirect_palette_size(const ncdirect* nc){
return nc->tcache.colors;
}
int ncdirect_fg_default(ncdirect* nc){
if(term_emit("op", nc->tcache.op, nc->ttyfp, false) == 0){
nc->fgdefault = true;
if(nc->bgdefault){
return 0;
}
return ncdirect_bg(nc, nc->fgrgb);
}
return -1;
}
int ncdirect_bg_default(ncdirect* nc){
if(term_emit("op", nc->tcache.op, nc->ttyfp, false) == 0){
nc->bgdefault = true;
if(nc->fgdefault){
return 0;
}
return ncdirect_fg(nc, nc->bgrgb);
}
return -1;
}
int ncdirect_bg(ncdirect* nc, unsigned rgb){
if(rgb > 0xffffffu){
return -1;
}
if(term_bg_rgb8(nc->tcache.RGBflag, nc->tcache.setab, nc->tcache.colors, nc->ttyfp,
(rgb & 0xff0000u) >> 16u, (rgb & 0xff00u) >> 8u, rgb & 0xffu)){
return -1;
}
nc->bgdefault = false;
nc->bgrgb = rgb;
return 0;
}
int ncdirect_fg(ncdirect* nc, unsigned rgb){
if(rgb > 0xffffffu){
return -1;
}
if(term_fg_rgb8(nc->tcache.RGBflag, nc->tcache.setaf, nc->tcache.colors, nc->ttyfp,
(rgb & 0xff0000u) >> 16u, (rgb & 0xff00u) >> 8u, rgb & 0xffu)){
return -1;
}
nc->fgdefault = false;
nc->fgrgb = rgb;
return 0;
}
static inline int
update_palette(notcurses* nc, FILE* out){
if(nc->tcache.CCCflag){
@ -1180,3 +1074,29 @@ char* notcurses_at_yx(notcurses* nc, int yoff, int xoff, uint32_t* attrword, uin
}
return egc;
}
int ncdirect_bg(ncdirect* nc, unsigned rgb){
if(rgb > 0xffffffu){
return -1;
}
if(term_bg_rgb8(nc->tcache.RGBflag, nc->tcache.setab, nc->tcache.colors, nc->ttyfp,
(rgb & 0xff0000u) >> 16u, (rgb & 0xff00u) >> 8u, rgb & 0xffu)){
return -1;
}
nc->bgdefault = false;
nc->bgrgb = rgb;
return 0;
}
int ncdirect_fg(ncdirect* nc, unsigned rgb){
if(rgb > 0xffffffu){
return -1;
}
if(term_fg_rgb8(nc->tcache.RGBflag, nc->tcache.setaf, nc->tcache.colors, nc->ttyfp,
(rgb & 0xff0000u) >> 16u, (rgb & 0xff00u) >> 8u, rgb & 0xffu)){
return -1;
}
nc->fgdefault = false;
nc->fgrgb = rgb;
return 0;
}

View File

@ -5,7 +5,7 @@
#include <string.h>
#include <locale.h>
#include <sys/ioctl.h>
#include <notcurses/notcurses.h>
#include <notcurses/direct.h>
// can we leave what was already on the screen there? (narrator: it seems not)
int main(void){

View File

@ -3,7 +3,7 @@
#include <stdlib.h>
#include <string.h>
#include <locale.h>
#include <notcurses/notcurses.h>
#include <notcurses/direct.h>
static int
print_b(struct ncdirect* nc, int r, int g, int total){

View File

@ -1,4 +1,5 @@
#include "main.h"
#include <notcurses/direct.h>
TEST_CASE("DirectMode") {
struct ncdirect* nc_ = ncdirect_init(NULL, stderr);