Improved cell API #97 (#103)

* cell/ncplane: simplify box API (#97)
* widecolor: use new box api (#97)
* uniblock: use new box API #97
* intro: use new box api #97
* panelreel: use new box api
* boxdemo: use new box API #97
* sliding: use new box API #97
* maxcolor: use new box api #97
* factor out notcurses_channel_prep() #97
* maxcolor: use new channel API #97
* sliding: use new channel API #97
* intro: use new channel API #97
* new output functions with no need for a cell
* add ncplane_putegc() and ncplane_putsimple(). the former takes an EGC, the latter a simple char less than 0x80. (#97)
* cell_prime: directly load all parts of a cell with immediates
* widecolor: use new output API #97
* boxdemo: properly initialize cells
* slider: total time cap of 5 * delaydemo
* maxcolor: use new output API #97
pull/108/head
Nick Black 5 years ago committed by GitHub
parent e21594b4e9
commit 8e8cb92c54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -291,6 +291,19 @@ API void ncplane_cursor_yx(const struct ncplane* n, int* RESTRICT y,
// On failure, -1 is returned.
API int ncplane_putc(struct ncplane* n, const cell* c);
// Replace the cell underneath the cursor with the provided 7-bit char 'c',
// using the specified 'attr' and 'channels' for styling. Advance the cursor by
// 1. On success, returns 1. On failure, returns -1.
API int ncplane_putsimple(struct ncplane* n, char c, uint32_t attr, uint64_t channels);
// Replace the cell underneath the cursor with the provided EGC, using the
// specified 'attr' and 'channels' for styling, and advance the cursor by the
// width of the cluster (but not past the end of the plane). On success, returns
// the number of columns the cursor was advanced. On failure, -1 is returned.
// The number of bytes converted from gclust is written to 'sbytes' if non-NULL.
API int ncplane_putegc(struct ncplane* n, const char* gclust, uint32_t attr,
uint64_t channels, int* sbytes);
// Write a series of cells to the current location, using the current style.
// They will be interpreted as a series of columns (according to the definition
// of ncplane_putc()). Advances the cursor by some positive number of cells
@ -388,6 +401,16 @@ cell_init(cell* c){
// of the cell is left untouched, but any resources are released.
API int cell_load(struct ncplane* n, cell* c, const char* gcluster);
// cell_load(), plus blast the styling with 'attr' and 'channels'.
static inline int
cell_prime(struct ncplane* n, cell* c, const char *gcluster,
uint32_t attr, uint64_t channels){
c->attrword = attr;
c->channels = channels;
int ret = cell_load(n, c, gcluster);
return ret;
}
// Duplicate 'c' into 'targ'. Not intended for external use; exposed for the
// benefit of unit tests.
API int cell_duplicate(struct ncplane* n, cell* targ, const cell* c);
@ -484,46 +507,46 @@ cell_rgb_get_bg(uint64_t channels, unsigned* r, unsigned* g, unsigned* b){
*b = cell_rgb_blue(bg);
}
// set the r, g, and b channels for either the foreground or background
// component of this 64-bit 'channels' variable. 'shift' is the base number
// of bits to shift r/g/b by; it ought either be 0 (bg) or 32 (fg). each of
// r, g, and b must be in [0, 256), or -1 is returned. 'mask' is the
// appropriate r/g/b mask, and 'nodefbit' is the appropriate nodefault bit.
static inline int
cell_rgb_set_fg(uint64_t* channels, int r, int g, int b){
notcurses_channel_prep(uint64_t* channels, uint64_t mask, unsigned shift,
int r, int g, int b, uint64_t nodefbit){
if(r >= 256 || g >= 256 || b >= 256){
return -1;
}
if(r < 0 || g < 0 || b < 0){
return -1;
}
uint64_t rgb = (r & 0xffull) << 48u;
rgb |= (g & 0xffull) << 40u;
rgb |= (b & 0xffull) << 32u;
rgb |= CELL_FGDEFAULT_MASK;
*channels = (*channels & ~(CELL_FGDEFAULT_MASK | CELL_FG_MASK)) | rgb;
uint64_t rgb = (r & 0xffull) << (shift + 16);
rgb |= (g & 0xffull) << (shift + 8);
rgb |= (b & 0xffull) << shift;
rgb |= nodefbit;
*channels = (*channels & ~(mask | nodefbit)) | rgb;
return 0;
}
static inline int
cell_rgb_set_bg(uint64_t* channels, int r, int g, int b){
if(r >= 256 || g >= 256 || b >= 256){
return -1;
}
if(r < 0 || g < 0 || b < 0){
return -1;
}
uint64_t rgb = (r & 0xffull) << 16u;
rgb |= (g & 0xffull) << 8u;
rgb |= (b & 0xffull);
rgb |= CELL_BGDEFAULT_MASK;
*channels = (*channels & ~(CELL_BGDEFAULT_MASK | CELL_BG_MASK)) | rgb;
return 0;
notcurses_fg_prep(uint64_t* channels, int r, int g, int b){
return notcurses_channel_prep(channels, CELL_FG_MASK, 32, r, g, b, CELL_FGDEFAULT_MASK);
}
static inline int
notcurses_bg_prep(uint64_t* channels, int r, int g, int b){
return notcurses_channel_prep(channels, CELL_BG_MASK, 0, r, g, b, CELL_BGDEFAULT_MASK);
}
static inline void
cell_set_fg(cell* c, unsigned r, unsigned g, unsigned b){
cell_rgb_set_fg(&c->channels, r, g, b);
notcurses_fg_prep(&c->channels, r, g, b);
}
static inline void
cell_set_bg(cell* c, unsigned r, unsigned g, unsigned b){
cell_rgb_set_bg(&c->channels, r, g, b);
notcurses_bg_prep(&c->channels, r, g, b);
}
static inline void
@ -598,7 +621,8 @@ API const char* cell_extended_gcluster(const struct ncplane* n, const cell* c);
// have loaded before the error are cell_release()d. There must be at least
// six EGCs in gcluster.
static inline int
cells_load_box(struct ncplane* n, cell* ul, cell* ur, cell* ll, cell* lr,
cells_load_box(struct ncplane* n, uint32_t attrs, uint64_t channels,
cell* ul, cell* ur, cell* ll, cell* lr,
cell* hl, cell* vl, const char* gclusters){
int ulen;
if((ulen = cell_load(n, ul, gclusters)) > 0){
@ -607,6 +631,12 @@ cells_load_box(struct ncplane* n, cell* ul, cell* ur, cell* ll, cell* lr,
if((ulen = cell_load(n, lr, gclusters += ulen)) > 0){
if((ulen = cell_load(n, hl, gclusters += ulen)) > 0){
if((ulen = cell_load(n, vl, gclusters += ulen)) > 0){
ul->attrword = attrs; ul->channels = channels;
ur->attrword = attrs; ur->channels = channels;
ll->attrword = attrs; ll->channels = channels;
lr->attrword = attrs; lr->channels = channels;
hl->attrword = attrs; hl->channels = channels;
vl->attrword = attrs; vl->channels = channels;
return 0;
}
cell_release(n, hl);
@ -623,15 +653,69 @@ cells_load_box(struct ncplane* n, cell* ul, cell* ur, cell* ll, cell* lr,
}
static inline int
cells_rounded_box(struct ncplane* n, cell* ul, cell* ur, cell* ll,
cell* lr, cell* hl, cell* vl){
return cells_load_box(n, ul, ur, ll, lr, hl, vl, "╭╮╰╯─│");
cells_rounded_box(struct ncplane* n, uint32_t attr, uint64_t channels,
cell* ul, cell* ur, cell* ll, cell* lr, cell* hl, cell* vl){
return cells_load_box(n, attr, channels, ul, ur, ll, lr, hl, vl, "╭╮╰╯─│");
}
static inline int
ncplane_rounded_box(struct ncplane* n, uint32_t attr, uint64_t channels,
int ystop, int xstop){
int ret = 0;
cell ul = CELL_TRIVIAL_INITIALIZER, ur = CELL_TRIVIAL_INITIALIZER;
cell ll = CELL_TRIVIAL_INITIALIZER, lr = CELL_TRIVIAL_INITIALIZER;
cell hl = CELL_TRIVIAL_INITIALIZER, vl = CELL_TRIVIAL_INITIALIZER;
if((ret = cells_rounded_box(n, attr, channels, &ul, &ur, &ll, &lr, &hl, &vl)) == 0){
ret = ncplane_box(n, &ul, &ur, &ll, &lr, &hl, &vl, ystop, xstop);
}
cell_release(n, &ul);
cell_release(n, &ur);
cell_release(n, &ll);
cell_release(n, &lr);
cell_release(n, &hl);
cell_release(n, &vl);
return ret;
}
static inline int
ncplane_rounded_box_sized(struct ncplane* n, uint32_t attr, uint64_t channels,
int ylen, int xlen){
int y, x;
ncplane_cursor_yx(n, &y, &x);
return ncplane_rounded_box(n, attr, channels, y + ylen - 1, x + xlen - 1);
}
static inline int
cells_double_box(struct ncplane* n, uint32_t attr, uint64_t channels,
cell* ul, cell* ur, cell* ll, cell* lr, cell* hl, cell* vl){
return cells_load_box(n, attr, channels, ul, ur, ll, lr, hl, vl, "╔╗╚╝═║");
}
static inline int
ncplane_double_box(struct ncplane* n, uint32_t attr, uint64_t channels,
int ystop, int xstop){
int ret = 0;
cell ul = CELL_TRIVIAL_INITIALIZER, ur = CELL_TRIVIAL_INITIALIZER;
cell ll = CELL_TRIVIAL_INITIALIZER, lr = CELL_TRIVIAL_INITIALIZER;
cell hl = CELL_TRIVIAL_INITIALIZER, vl = CELL_TRIVIAL_INITIALIZER;
if((ret = cells_double_box(n, attr, channels, &ul, &ur, &ll, &lr, &hl, &vl)) == 0){
ret = ncplane_box(n, &ul, &ur, &ll, &lr, &hl, &vl, ystop, xstop);
}
cell_release(n, &ul);
cell_release(n, &ur);
cell_release(n, &ll);
cell_release(n, &lr);
cell_release(n, &hl);
cell_release(n, &vl);
return ret;
}
static inline int
cells_double_box(struct ncplane* n, cell* ul, cell* ur, cell* ll,
cell* lr, cell* hl, cell* vl){
return cells_load_box(n, ul, ur, ll, lr, hl, vl, "╔╗╚╝═║");
ncplane_double_box_sized(struct ncplane* n, uint32_t attr, uint64_t channels,
int ylen, int xlen){
int y, x;
ncplane_cursor_yx(n, &y, &x);
return ncplane_double_box(n, attr, channels, y + ylen - 1, x + xlen - 1);
}
// multimedia functionality

@ -7,16 +7,12 @@ int box_demo(struct notcurses* nc){
notcurses_term_dim_yx(nc, &ylen, &xlen);
struct ncplane* n = notcurses_stdplane(nc);
ncplane_erase(n);
cell ul, ll, lr, ur, hl, vl;
cell ul = CELL_TRIVIAL_INITIALIZER, ll = CELL_TRIVIAL_INITIALIZER;
cell lr = CELL_TRIVIAL_INITIALIZER, ur = CELL_TRIVIAL_INITIALIZER;
cell hl = CELL_TRIVIAL_INITIALIZER, vl = CELL_TRIVIAL_INITIALIZER;
ncplane_fg_rgb8(n, 255, 255, 255);
ncplane_bg_rgb8(n, 180, 40, 180);
cell_init(&ul);
cell_init(&ur);
cell_init(&ll);
cell_init(&lr);
cell_init(&hl);
cell_init(&vl);
if(cells_double_box(n, &ul, &ur, &ll, &lr, &hl, &vl)){
if(cells_double_box(n, 0, 0, &ul, &ur, &ll, &lr, &hl, &vl)){
return -1;
}
int y = 0, x = 0;

@ -136,31 +136,13 @@ intro(struct notcurses* nc){
}
}
cell_release(ncp, &c);
cell ul = CELL_TRIVIAL_INITIALIZER;
cell ur = CELL_TRIVIAL_INITIALIZER;
cell ll = CELL_TRIVIAL_INITIALIZER;
cell lr = CELL_TRIVIAL_INITIALIZER;
cell vl = CELL_TRIVIAL_INITIALIZER;
cell hl = CELL_TRIVIAL_INITIALIZER;
if(cells_rounded_box(ncp, &ul, &ur, &ll, &lr, &hl, &vl)){
return -1;
}
cell_set_fg(&ul, 90, 0, 90);
cell_set_fg(&ur, 90, 0, 90);
cell_set_fg(&ll, 90, 0, 90);
cell_set_fg(&lr, 90, 0, 90);
cell_set_fg(&vl, 90, 0, 90);
cell_set_fg(&hl, 90, 0, 90);
cell_set_bg(&ul, 0, 0, 180);
cell_set_bg(&ur, 0, 0, 180);
cell_set_bg(&ll, 0, 0, 180);
cell_set_bg(&lr, 0, 0, 180);
cell_set_bg(&vl, 0, 0, 180);
cell_set_bg(&hl, 0, 0, 180);
uint64_t channels = 0;
notcurses_fg_prep(&channels, 90, 0, 90);
notcurses_bg_prep(&channels, 0, 0, 180);
if(ncplane_cursor_move_yx(ncp, 4, 4)){
return -1;
}
if(ncplane_box(ncp, &ul, &ur, &ll, &lr, &hl, &vl, rows - 6, cols - 6)){
if(ncplane_rounded_box(ncp, 0, channels, rows - 6, cols - 6)){
return -1;
}
const char s1[] = " Die Welt ist alles, was der Fall ist. ";
@ -207,6 +189,7 @@ intro(struct notcurses* nc){
static int
ext_demos(struct notcurses* nc, const char* demos){
int dimy, dimx;
while(*demos){
int ret = 0;
switch(*demos){
@ -222,9 +205,11 @@ ext_demos(struct notcurses* nc, const char* demos){
case 'p': ret = panelreel_demo(nc); break;
}
if(ret){
fprintf(stderr, "Unknown demo specification: %c\n", *demos);
return ret;
}
++demos;
notcurses_resize(nc, &dimy, &dimx);
}
return 0;
}

@ -11,8 +11,6 @@ extern "C" {
// configured via command line option -- the base number of ns between demos
extern struct timespec demodelay;
#define FADE_MILLISECONDS 500
int unicodeblocks_demo(struct notcurses* nc);
int widecolor_demo(struct notcurses* nc);
int box_demo(struct notcurses* nc);

@ -33,61 +33,32 @@ int maxcolor_demo(struct notcurses* nc){
notcurses_term_dim_yx(nc, &maxy, &maxx);
struct ncplane* n = notcurses_stdplane(nc);
ncplane_fg_rgb8(n, 255, 255, 255);
cell ul = CELL_TRIVIAL_INITIALIZER;
cell ll = CELL_TRIVIAL_INITIALIZER;
cell lr = CELL_TRIVIAL_INITIALIZER;
cell ur = CELL_TRIVIAL_INITIALIZER;
cell hl = CELL_TRIVIAL_INITIALIZER;
cell vl = CELL_TRIVIAL_INITIALIZER;
if(cells_rounded_box(n, &ul, &ur, &ll, &lr, &hl, &vl)){
return -1;
}
cell_set_fg(&ul, 0, 128, 128);
cell_set_fg(&ur, 0, 128, 128);
cell_set_fg(&ll, 0, 128, 128);
cell_set_fg(&lr, 0, 128, 128);
cell_set_fg(&vl, 0, 128, 128);
cell_set_fg(&hl, 0, 128, 128);
cell_set_bg(&ul, 90, 0, 90);
cell_set_bg(&ur, 90, 0, 90);
cell_set_bg(&ll, 90, 0, 90);
cell_set_bg(&lr, 90, 0, 90);
cell_set_bg(&vl, 90, 0, 90);
cell_set_bg(&hl, 90, 0, 90);
uint64_t channels = 0;
notcurses_fg_prep(&channels, 0, 128, 128);
notcurses_bg_prep(&channels, 90, 0, 90);
int y = 0, x = 0;
ncplane_cursor_move_yx(n, y, x);
if(ncplane_box_sized(n, &ul, &ur, &ll, &lr, &hl, &vl, maxy, maxx)){
if(ncplane_rounded_box_sized(n, 0, channels, maxy, maxx)){
return -1;
}
uint32_t rgb = 0;
char buf[2] = "";
cell c = CELL_TRIVIAL_INITIALIZER;
for(y = 1 ; y < maxy - 1 ; ++y){
x = 1;
if(ncplane_cursor_move_yx(n, y, x)){
return -1;
}
while(x < maxx - 1){
cell_set_fg(&c, (rgb & 0xff0000) >> 16u, (rgb & 0xff00) >> 8u, rgb & 0xff);
cell_set_bg(&c, 0, 10, 0);
buf[0] = (x % 10) + '0';
cell_load(n, &c, buf);
ncplane_putc(n, &c);
notcurses_fg_prep(&channels, (rgb & 0xff0000) >> 16u,
(rgb & 0xff00) >> 8u, rgb & 0xff);
notcurses_bg_prep(&channels, 0, 10, 0);
ncplane_putsimple(n, x % 10 + '0', 0, channels);
grow_rgb(&rgb);
++x;
}
}
cell_release(n, &c);
if(notcurses_render(nc)){
return -1;
}
cell_release(n, &ul);
cell_release(n, &ur);
cell_release(n, &ll);
cell_release(n, &lr);
cell_release(n, &vl);
cell_release(n, &hl);
nanosleep(&demodelay, NULL);
return 0;
}

@ -7,10 +7,11 @@
#define CHUNKS_VERT 6
#define CHUNKS_HORZ 12
#define MOVES 45
#define GIG 1000000000
#define GIG 1000000000ul
static int
move_square(struct notcurses* nc, struct ncplane* chunk, int* holey, int* holex){
move_square(struct notcurses* nc, struct ncplane* chunk, int* holey, int* holex,
uint64_t movens){
int newholex, newholey;
ncplane_yx(chunk, &newholey, &newholex);
// we need to move from newhole to hole over the course of movetime
@ -19,7 +20,6 @@ move_square(struct notcurses* nc, struct ncplane* chunk, int* holey, int* holex)
deltax = *holex - newholex;
// divide movetime into abs(max(deltay, deltax)) units, and move delta
int units = abs(deltay) > abs(deltax) ? abs(deltay) : abs(deltax);
uint64_t movens = (MOVES / 5) * (demodelay.tv_sec * GIG + demodelay.tv_nsec);
movens /= units;
struct timespec movetime = {
.tv_sec = movens / MOVES / GIG,
@ -48,8 +48,14 @@ move_square(struct notcurses* nc, struct ncplane* chunk, int* holey, int* holex)
// we take (MOVES / 5) * demodelay to play MOVES moves
static int
play(struct notcurses* nc, struct ncplane** chunks){
const uint64_t delayns = demodelay.tv_sec * GIG + demodelay.tv_nsec;
const int chunkcount = CHUNKS_VERT * CHUNKS_HORZ;
// struct ncplane* n = notcurses_stdplane(nc);
struct timespec cur;
clock_gettime(CLOCK_MONOTONIC, &cur);
// we don't want to spend more than demodelay * 5
const uint64_t totalns = delayns * 5;
const uint64_t deadline_ns = cur.tv_sec * GIG + cur.tv_nsec + totalns;
const uint64_t movens = totalns / MOVES;
int hole = random() % chunkcount;
int holex, holey;
ncplane_yx(chunks[hole], &holey, &holex);
@ -58,6 +64,11 @@ play(struct notcurses* nc, struct ncplane** chunks){
int m;
int lastdir = -1;
for(m = 0 ; m < MOVES ; ++m){
clock_gettime(CLOCK_MONOTONIC, &cur);
uint64_t now = cur.tv_sec * GIG + cur.tv_nsec;
if(now >= deadline_ns){
break;
}
int mover = chunkcount;
int direction;
do{
@ -74,7 +85,7 @@ play(struct notcurses* nc, struct ncplane** chunks){
}
}while(mover == chunkcount);
lastdir = direction;
move_square(nc, chunks[mover], &holey, &holex);
move_square(nc, chunks[mover], &holey, &holex, movens);
chunks[hole] = chunks[mover];
chunks[mover] = NULL;
hole = mover;
@ -88,20 +99,10 @@ fill_chunk(struct ncplane* n, int idx){
int maxy, maxx;
ncplane_dim_yx(n, &maxy, &maxx);
snprintf(buf, sizeof(buf), "%03d", idx);
cell ul = CELL_TRIVIAL_INITIALIZER, ur = CELL_TRIVIAL_INITIALIZER;
cell ll = CELL_TRIVIAL_INITIALIZER, lr = CELL_TRIVIAL_INITIALIZER;
cell hl = CELL_TRIVIAL_INITIALIZER, vl = CELL_TRIVIAL_INITIALIZER;
if(cells_double_box(n, &ul, &ur, &ll, &lr, &hl, &vl)){
return -1;
}
uint64_t channels = 0;
int r = random() % 256, g = random() % 256, b = random() % 256;
cell_set_fg(&ul, r, g, b);
cell_set_fg(&ur, r, g, b);
cell_set_fg(&ll, r, g, b);
cell_set_fg(&lr, r, g, b);
cell_set_fg(&hl, r, g, b);
cell_set_fg(&vl, r, g, b);
if(ncplane_box(n, &ul, &ur, &ll, &lr, &hl, &vl, maxy - 1, maxx - 1)){
notcurses_fg_prep(&channels, r, g, b);
if(ncplane_double_box(n, 0, channels, maxy - 1, maxx - 1)){
return -1;
}
if(maxx >= 5 && maxy >= 3){
@ -114,46 +115,23 @@ fill_chunk(struct ncplane* n, int idx){
return -1;
}
}
cell_release(n, &ul);
cell_release(n, &ur);
cell_release(n, &ll);
cell_release(n, &lr);
cell_release(n, &hl);
cell_release(n, &vl);
cell bg = CELL_TRIVIAL_INITIALIZER;
cell_set_bg(&bg, r, g, b);
ncplane_set_background(n, &bg);
cell_release(n, &bg);
cell style;
cell_init(&style);
cell_set_bg(&style, r, g, b);
ncplane_set_background(n, &style);
cell_release(n, &style);
return 0;
}
static int
draw_bounding_box(struct ncplane* n, int yoff, int xoff, int chunky, int chunkx){
int ret = -1;
cell ul = CELL_TRIVIAL_INITIALIZER, ur = CELL_TRIVIAL_INITIALIZER;
cell ll = CELL_TRIVIAL_INITIALIZER, lr = CELL_TRIVIAL_INITIALIZER;
cell hl = CELL_TRIVIAL_INITIALIZER, vl = CELL_TRIVIAL_INITIALIZER;
if(cells_rounded_box(n, &ul, &ur, &ll, &lr, &hl, &vl)){
return -1;
}
cell_set_fg(&ul, 180, 80, 180);
cell_set_fg(&ur, 180, 80, 180);
cell_set_fg(&ll, 180, 80, 180);
cell_set_fg(&lr, 180, 80, 180);
cell_set_fg(&hl, 180, 80, 180);
cell_set_fg(&vl, 180, 80, 180);
int ret;
uint64_t channels = 0;
notcurses_fg_prep(&channels, 180, 80, 180);
ncplane_cursor_move_yx(n, yoff, xoff);
if(!ncplane_box(n, &ul, &ur, &ll, &lr, &hl, &vl,
CHUNKS_VERT * chunky + yoff + 1,
CHUNKS_HORZ * chunkx + xoff + 1)){
ret = 0;
}
cell_release(n, &ul);
cell_release(n, &ur);
cell_release(n, &ll);
cell_release(n, &lr);
cell_release(n, &hl);
cell_release(n, &vl);
ret = ncplane_rounded_box(n, 0, channels,
CHUNKS_VERT * chunky + yoff + 1,
CHUNKS_HORZ * chunkx + xoff + 1);
return ret;
}

@ -94,15 +94,6 @@ int unicodeblocks_demo(struct notcurses* nc){
subdelay.tv_nsec = nstotal % 1000000000;
for(sindex = 0 ; sindex < sizeof(blocks) / sizeof(*blocks) ; ++sindex){
ncplane_erase(n);
cell ul = CELL_TRIVIAL_INITIALIZER;
cell ur = CELL_TRIVIAL_INITIALIZER;
cell ll = CELL_TRIVIAL_INITIALIZER;
cell lr = CELL_TRIVIAL_INITIALIZER;
cell vl = CELL_TRIVIAL_INITIALIZER;
cell hl = CELL_TRIVIAL_INITIALIZER;
if(cells_rounded_box(n, &ul, &ur, &ll, &lr, &hl, &vl)){
return -1;
}
uint32_t blockstart = blocks[sindex].start;
const char* description = blocks[sindex].name;
int chunk;
@ -118,8 +109,7 @@ int unicodeblocks_demo(struct notcurses* nc){
return -1;
}
++xstart;
if(ncplane_box_sized(n, &ul, &ur, &ll, &lr, &hl, &vl,
BLOCKSIZE / CHUNKSIZE + 2, (CHUNKSIZE * 2) + 2)){
if(ncplane_rounded_box_sized(n, 0, 0, BLOCKSIZE / CHUNKSIZE + 2, (CHUNKSIZE * 2) + 2)){
return -1;
}
for(chunk = 0 ; chunk < BLOCKSIZE / CHUNKSIZE ; ++chunk){
@ -186,8 +176,6 @@ int unicodeblocks_demo(struct notcurses* nc){
// for a 32-bit wchar_t, we would want up through 24 bits of block ID. but
// really, the vast majority of space is unused.
blockstart += BLOCKSIZE;
cell_release(n, &ul); cell_release(n, &ur); cell_release(n, &hl);
cell_release(n, &ll); cell_release(n, &lr); cell_release(n, &vl);
}
return 0;
}

@ -1,3 +1,4 @@
#include <assert.h>
#include <ctype.h>
#include <curses.h>
#include <unistd.h>
@ -8,39 +9,29 @@
static int
message(struct ncplane* n, int maxy, int maxx, int num, int total){
ncplane_bg_default(n);
cell ul, ur, ll, lr, vl, hl;
cell_init(&ul);
cell_init(&ur);
cell_init(&ll);
cell_init(&lr);
cell_init(&hl);
cell_init(&vl);
if(cells_rounded_box(n, &ul, &ur, &ll, &lr, &hl, &vl)){
return -1;
}
ncplane_cursor_move_yx(n, 3, 1);
ncplane_fg_rgb8(n, 255, 255, 255);
ncplane_fg_rgb8(n, 0, 0, 0);
ncplane_bg_rgb8(n, 255, 255, 255);
ncplane_styles_on(n, CELL_STYLE_BOLD);
if(ncplane_box(n, &ul, &ur, &ll, &lr, &hl, &vl, 5, 57)){
if(ncplane_rounded_box(n, 0, 0, 5, 57)){
return -1;
}
cell_load(n, &ll, "");
ncplane_cursor_move_yx(n, 3, 4);
ncplane_putc(n, &ll);
ncplane_cursor_move_yx(n, 3, 20);
ncplane_putc(n, &ll);
cell_load(n, &vl, "");
ncplane_cursor_move_yx(n, 2, 20);
ncplane_putc(n, &vl);
ncplane_putegc(n, "", 0, 0, NULL);
ncplane_cursor_move_yx(n, 2, 4);
ncplane_putc(n, &vl);
cell_load(n, &ul, "");
ncplane_putegc(n, "", 0, 0, NULL);
ncplane_cursor_move_yx(n, 1, 4);
ncplane_putc(n, &ul);
ncplane_putegc(n, "", 0, 0, NULL);
cell hl = CELL_TRIVIAL_INITIALIZER;
cell_load(n, &hl, "");
ncplane_hline(n, &hl, 15);
cell_load(n, &ur, "");
ncplane_putc(n, &ur);
cell_release(n, &hl);
ncplane_cursor_move_yx(n, 1, 20);
ncplane_putegc(n, "", 0, 0, NULL);
ncplane_cursor_move_yx(n, 2, 20);
ncplane_putegc(n, "", 0, 0, NULL);
ncplane_cursor_move_yx(n, 3, 20);
ncplane_putegc(n, "", 0, 0, NULL);
ncplane_cursor_move_yx(n, 2, 5);
ncplane_printf(n, " %03dx%03d (%d/%d) ", maxx, maxy, num + 1, total);
ncplane_cursor_move_yx(n, 4, 2);
@ -247,18 +238,22 @@ int widecolor_demo(struct notcurses* nc){
};
const char** s;
int count = notcurses_palette_size(nc);
const int steps[] = { 128, 64, 16, 1, };
const int starts[] = { 0, 16, 62, 128, };
const int steps[] = { 1, 0x100, 0x40000, 0x10001, };
const int starts[] = { 1, 0x100, 0x10000, 0x10001, };
struct ncplane* n = notcurses_stdplane(nc);
size_t i;
for(i = 0 ; i < sizeof(steps) / sizeof(*steps) ; ++i){
// ncplane_erase(n);
const size_t screens = sizeof(steps) / sizeof(*steps);
for(i = 0 ; i < screens ; ++i){
const int start = starts[i];
const int step = steps[i];
int step = steps[i];
ncspecial_key special;
cell c;
do{
do{ // (re)draw a screen
// ncplane_erase(n);
const int rollover = 256 / ((step & 0xff) | ((step & 0xff00) >> 8u)
| ((step & 0xff0000) >> 16u));
int rollcount = 0; // number of times we've added this step
int dimy, dimx;
notcurses_resize(nc, &dimy, &dimx);
cell_init(&c);
@ -271,17 +266,21 @@ int widecolor_demo(struct notcurses* nc){
}
y = 0;
x = 0;
do{ // we fill up the entire screen, however large
do{ // we fill up the entire screen, however large, walking our strtable
s = strs;
uint64_t channels = 0;
notcurses_bg_prep(&channels, 20, 20, 20);
for(s = strs ; *s ; ++s){
cell wch = CELL_TRIVIAL_INITIALIZER;
cell_set_fg(&wch, cell_rgb_red(rgb), 255 - cell_rgb_green(rgb),
cell_rgb_blue(rgb));
cell_set_bg(&wch, 64, 64, 64);
size_t idx = 0;
ncplane_cursor_yx(n, &y, &x);
// fprintf(stderr, "%02d %s\n", y, *s);
while((*s)[idx]){
while((*s)[idx]){ // each multibyte char of string
if(notcurses_fg_prep(&channels,
cell_rgb_red(rgb),
cell_rgb_green(rgb),
cell_rgb_blue(rgb))){
return -1;
}
if(y >= maxy || x >= maxx){
break;
}
@ -289,21 +288,30 @@ int widecolor_demo(struct notcurses* nc){
++idx;
continue;
}
// cell_load frees the previous contents
int ulen = cell_load(n, &wch, &(*s)[idx]);
if(ulen < 0){
return -1;
}
if(ncplane_putc(n, &wch) < 0){
int ulen = 0;
int r;
if((r = ncplane_putegc(n, &(*s)[idx], 0, channels, &ulen)) < 0){
if(ulen < 0){
return -1;
}
break;
}
ncplane_cursor_yx(n, &y, &x);
if((rgb += step) >= count){
rgb = 1;
}
idx += ulen;
}
cell_release(n, &wch);
if(++rollcount % rollover == 0){
step *= 256;
}
if((unsigned)step >= 1ul << 24){
step >>= 24u;
}
if(step == 0){
step = 1;
}
if((rgb += step) >= count){
rgb = 0;
step *= 256;
}
}
}while(y < maxy && x < maxx);
if(message(n, maxy, maxx, i, sizeof(steps) / sizeof(*steps))){
@ -313,8 +321,10 @@ int widecolor_demo(struct notcurses* nc){
return -1;
}
if(i){
uint64_t delay = demodelay.tv_sec * 1000000000 + demodelay.tv_nsec;
delay /= screens;
struct timespec tv = {
.tv_sec = 0, .tv_nsec = FADE_MILLISECONDS * 1000000,
.tv_sec = delay / 1000000000, .tv_nsec = delay % 1000000000,
};
ncplane_fadein(n, &tv);
}

@ -754,11 +754,11 @@ void ncplane_bg_default(struct ncplane* n){
}
int ncplane_bg_rgb8(ncplane* n, int r, int g, int b){
return cell_rgb_set_bg(&n->channels, r, g, b);
return notcurses_bg_prep(&n->channels, r, g, b);
}
int ncplane_fg_rgb8(ncplane* n, int r, int g, int b){
return cell_rgb_set_fg(&n->channels, r, g, b);
return notcurses_fg_prep(&n->channels, r, g, b);
}
int ncplane_set_background(ncplane* ncp, const cell* c){
@ -1245,6 +1245,33 @@ int ncplane_putc(ncplane* n, const cell* c){
return ret;
}
int ncplane_putsimple(struct ncplane* n, char c, uint32_t attr, uint64_t channels){
cell ce = {
.gcluster = c,
.attrword = attr,
.channels = channels,
};
if(!cell_simple_p(&ce)){
return -1;
}
return ncplane_putc(n, &ce);
}
int ncplane_putegc(struct ncplane* n, const char* gclust, uint32_t attr,
uint64_t channels, int* sbytes){
cell c = CELL_TRIVIAL_INITIALIZER;
int primed = cell_prime(n, &c, gclust, attr, channels);
if(primed < 0){
return -1;
}
if(sbytes){
*sbytes = primed;
}
int ret = ncplane_putc(n, &c);
cell_release(n, &c);
return ret;
}
int ncplane_cursor_at(const ncplane* n, cell* c, char** gclust){
if(n->y == n->leny && n->x == n->lenx){
return -1;

@ -72,18 +72,12 @@ draw_borders(ncplane* w, unsigned nobordermask, const cell* attr,
cell ul, ur, ll, lr, hl, vl;
cell_init(&ul); cell_init(&ur); cell_init(&hl);
cell_init(&ll); cell_init(&lr); cell_init(&vl);
if(cells_rounded_box(w, &ul, &ur, &ll, &lr, &hl, &vl)){
if(cells_rounded_box(w, attr->attrword, attr->channels, &ul, &ur, &ll, &lr, &hl, &vl)){
return -1;
}
/*fprintf(stderr, "drawing borders %p %d/%d->%d/%d, mask: %04x, clipping: %c%c\n",
w, begx, begy, maxx, maxy, nobordermask,
cliphead ? 'T' : 't', clipfoot ? 'F' : 'f');*/
ul.attrword = attr->attrword; ul.channels = attr->channels;
ur.attrword = attr->attrword; ur.channels = attr->channels;
ll.attrword = attr->attrword; ll.channels = attr->channels;
lr.attrword = attr->attrword; lr.channels = attr->channels;
hl.attrword = attr->attrword; hl.channels = attr->channels;
vl.attrword = attr->attrword; vl.channels = attr->channels;
if(!cliphead){
// lenx - begx + 1 is the number of columns we have, but drop 2 due to
// corners. we thus want lenx - begx - 1 horizontal lines.

@ -175,7 +175,7 @@ TEST_F(NcplaneTest, BadlyPlacedBoxen) {
ASSERT_LT(2, y);
ASSERT_LT(2, x);
cell ul{}, ll{}, lr{}, ur{}, hl{}, vl{};
ASSERT_EQ(0, cells_rounded_box(n_, &ul, &ur, &ll, &lr, &hl, &vl));
ASSERT_EQ(0, cells_rounded_box(n_, 0, 0, &ul, &ur, &ll, &lr, &hl, &vl));
EXPECT_GT(0, ncplane_box(n_, &ul, &ur, &ll, &lr, &hl, &vl, y + 1, x + 1));
EXPECT_EQ(0, ncplane_cursor_move_yx(n_, 1, 0));
EXPECT_GT(0, ncplane_box(n_, &ul, &ur, &ll, &lr, &hl, &vl, y, x));
@ -190,37 +190,43 @@ TEST_F(NcplaneTest, BadlyPlacedBoxen) {
EXPECT_EQ(0, notcurses_render(nc_));
}
TEST_F(NcplaneTest, PerimeterBox) {
TEST_F(NcplaneTest, PerimeterRoundedBox) {
int x, y;
ncplane_dim_yx(n_, &y, &x);
ASSERT_LT(2, y);
ASSERT_LT(2, x);
cell ul{}, ll{}, lr{}, ur{}, hl{}, vl{};
ASSERT_EQ(0, cells_rounded_box(n_, &ul, &ur, &ll, &lr, &hl, &vl));
EXPECT_EQ(0, ncplane_box(n_, &ul, &ur, &ll, &lr, &hl, &vl, y - 1, x - 1));
cell_release(n_, &vl);
cell_release(n_, &hl);
cell_release(n_, &ul);
cell_release(n_, &ll);
cell_release(n_, &ur);
cell_release(n_, &lr);
ASSERT_EQ(0, ncplane_cursor_move_yx(n_, 0, 0));
EXPECT_EQ(0, ncplane_rounded_box(n_, 0, 0, y - 1, x - 1));
EXPECT_EQ(0, notcurses_render(nc_));
}
TEST_F(NcplaneTest, PerimeterBoxSized) {
TEST_F(NcplaneTest, PerimeterRoundedBoxSized) {
int x, y;
ncplane_dim_yx(n_, &y, &x);
ASSERT_LT(2, y);
ASSERT_LT(2, x);
cell ul{}, ll{}, lr{}, ur{}, hl{}, vl{};
ASSERT_EQ(0, cells_rounded_box(n_, &ul, &ur, &ll, &lr, &hl, &vl));
EXPECT_EQ(0, ncplane_box_sized(n_, &ul, &ur, &ll, &lr, &hl, &vl, y, x));
cell_release(n_, &vl);
cell_release(n_, &hl);
cell_release(n_, &ul);
cell_release(n_, &ll);
cell_release(n_, &ur);
cell_release(n_, &lr);
ASSERT_EQ(0, ncplane_cursor_move_yx(n_, 0, 0));
EXPECT_EQ(0, ncplane_rounded_box_sized(n_, 0, 0, y, x));
EXPECT_EQ(0, notcurses_render(nc_));
}
TEST_F(NcplaneTest, PerimeterDoubleBox) {
int x, y;
ncplane_dim_yx(n_, &y, &x);
ASSERT_LT(2, y);
ASSERT_LT(2, x);
ASSERT_EQ(0, ncplane_cursor_move_yx(n_, 0, 0));
EXPECT_EQ(0, ncplane_double_box(n_, 0, 0, y - 1, x - 1));
EXPECT_EQ(0, notcurses_render(nc_));
}
TEST_F(NcplaneTest, PerimeterDoubleBoxSized) {
int x, y;
ncplane_dim_yx(n_, &y, &x);
ASSERT_LT(2, y);
ASSERT_LT(2, x);
ASSERT_EQ(0, ncplane_cursor_move_yx(n_, 0, 0));
EXPECT_EQ(0, ncplane_double_box_sized(n_, 0, 0, y, x));
EXPECT_EQ(0, notcurses_render(nc_));
}

Loading…
Cancel
Save